Skip to content

Commit 58f35c4

Browse files
committed
Add map checker
1 parent 4d93361 commit 58f35c4

10 files changed

+206
-14
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import (
1414
"log"
1515
)
1616
17-
var checker *ov.Checker
17+
var checker *ov.ListChecker
1818
1919
func init() {
2020
// Expect (int, int) or (float64, float64)
21-
checker = ov.NewChecker(
21+
checker = ov.NewListChecker(
2222
ov.NewRule(
2323
ov.NewArgument("int"),
2424
ov.NewArgument("int")),
@@ -63,11 +63,11 @@ import (
6363
"log"
6464
)
6565
66-
var checker *ov.Checker
66+
var checker *ov.ListChecker
6767
6868
func init() {
6969
// Expect (int, int) or (int)
70-
checker = ov.NewChecker(
70+
checker = ov.NewListChecker(
7171
ov.NewRule(
7272
ov.NewArgument("int"),
7373
ov.NewArgument("int", 3)))

argument.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package overloading
22

33
type Argument struct {
4-
_type string
5-
_default interface{}
4+
_type string
5+
isOptional bool
6+
_default interface{}
67
}
78

89
func NewArgument(args ...interface{}) *Argument {
@@ -23,6 +24,7 @@ func NewArgument(args ...interface{}) *Argument {
2324
p._type = arr[0].(string)
2425

2526
if len(arr) == 2 {
27+
p.isOptional = true
2628
p._default = arr[1]
2729
}
2830

@@ -34,7 +36,7 @@ func (a *Argument) Type() string {
3436
}
3537

3638
func (a *Argument) IsOptional() bool {
37-
return a._default != nil
39+
return a.isOptional
3840
}
3941

4042
func (a *Argument) Default() interface{} {

checker.go list_checker.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package overloading
22

3-
type Checker struct {
3+
type ListChecker struct {
44
rules []*Rule
55
}
66

7-
func NewChecker(rules ...*Rule) *Checker {
8-
c := new(Checker)
7+
func NewListChecker(rules ...*Rule) *ListChecker {
8+
c := new(ListChecker)
99
c.rules = make([]*Rule, len(rules))
1010

1111
for i, r := range rules {
@@ -15,7 +15,7 @@ func NewChecker(rules ...*Rule) *Checker {
1515
return c
1616
}
1717

18-
func (c *Checker) Check(args []interface{}) []interface{} {
18+
func (c *ListChecker) Check(args []interface{}) []interface{} {
1919
for _, r := range c.rules {
2020
out, err := r.Check(args)
2121
if err == nil {

checker_test.go list_checker_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ func TestChecker(t *testing.T) {
99
t.Parallel()
1010

1111
// Expect (int, int)
12-
c := NewChecker(
12+
c := NewListChecker(
1313
NewRule(
1414
NewArgument("int"),
1515
NewArgument("int")))
@@ -37,7 +37,7 @@ func TestCheckerViolation(t *testing.T) {
3737
}()
3838

3939
// Expect (int, int)
40-
c := NewChecker(
40+
c := NewListChecker(
4141
NewRule(
4242
NewArgument("int"),
4343
NewArgument("int")))
@@ -58,7 +58,7 @@ func TestMultiRuleChecker(t *testing.T) {
5858
t.Parallel()
5959

6060
// Expect (int, int) or (float64, float64)
61-
c := NewChecker(
61+
c := NewListChecker(
6262
NewRule(
6363
NewArgument("int"),
6464
NewArgument("int")),

rule.go list_rule.go

File renamed without changes.

rule_test.go list_rule_test.go

File renamed without changes.

map_checker.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package overloading
2+
3+
type MapChecker struct {
4+
rules []*MapRule
5+
}
6+
7+
func NewMapChecker(args ...*MapRule) *MapChecker {
8+
m := new(MapChecker)
9+
m.rules = make([]*MapRule, len(args))
10+
11+
for i, a := range args {
12+
m.rules[i] = a
13+
}
14+
15+
return m
16+
}
17+
18+
func (m *MapChecker) Check(args map[string]interface{}) map[string]interface{} {
19+
for _, r := range m.rules {
20+
out, err := r.Check(args)
21+
if err == nil {
22+
return out
23+
}
24+
}
25+
26+
panic("No valid argument")
27+
}

map_checker_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package overloading
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func TestMapChecker(t *testing.T) {
9+
c := NewMapChecker(
10+
NewMapRule(
11+
"x", NewArgument("int"),
12+
"y", NewArgument("int")),
13+
NewMapRule(
14+
"x", NewArgument("float64"),
15+
"y", NewArgument("float64")))
16+
17+
f := func(arg map[string]interface{}) interface{} {
18+
out := c.Check(arg)
19+
20+
t := reflect.TypeOf(out["x"]).String()
21+
switch t {
22+
case "int":
23+
na := out["x"].(int)
24+
nb := out["y"].(int)
25+
return na + nb
26+
case "float64":
27+
na := out["x"].(float64)
28+
nb := out["y"].(float64)
29+
return na + nb
30+
default:
31+
panic("Unknown type")
32+
}
33+
}
34+
35+
arg1 := make(map[string]interface{})
36+
arg1["x"] = 3
37+
arg1["y"] = 2
38+
if f(arg1).(int) != 5 {
39+
t.Error("Wrong map checker")
40+
}
41+
42+
arg2 := make(map[string]interface{})
43+
arg2["x"] = 3.0
44+
arg2["y"] = 2.0
45+
if f(arg2).(float64) != 5.0 {
46+
t.Error("Wrong map checker")
47+
}
48+
}

map_rule.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package overloading
2+
3+
import (
4+
"errors"
5+
"reflect"
6+
)
7+
8+
type MapRule struct {
9+
m map[string]*Argument
10+
}
11+
12+
func NewMapRule(args ...interface{}) *MapRule {
13+
_len := len(args)
14+
if _len%2 != 0 {
15+
panic("Wrong argument length")
16+
}
17+
r := new(MapRule)
18+
r.m = make(map[string]*Argument)
19+
20+
for i := 0; i < _len; i += 2 {
21+
k := args[i].(string)
22+
r.m[k] = args[i+1].(*Argument)
23+
}
24+
25+
return r
26+
}
27+
28+
func (r *MapRule) Check(args map[string]interface{}) (map[string]interface{}, error) {
29+
out := make(map[string]interface{})
30+
31+
for k, v := range args {
32+
arg, ok := r.m[k]
33+
if !ok {
34+
return out, errors.New("Unknown argument " + k)
35+
}
36+
37+
t := reflect.TypeOf(v).String()
38+
if t != arg.Type() {
39+
return out, errors.New("Wrong argument type on " + k)
40+
}
41+
42+
out[k] = v
43+
}
44+
45+
for k := range r.m {
46+
_, ok := args[k]
47+
if !ok {
48+
if r.m[k].IsOptional() {
49+
out[k] = r.m[k].Default()
50+
} else {
51+
return out, errors.New("No default value on " + k)
52+
}
53+
}
54+
}
55+
56+
return out, nil
57+
}

map_rule_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package overloading
2+
3+
import "testing"
4+
5+
func TestMapRule(t *testing.T) {
6+
t.Parallel()
7+
r := NewMapRule(
8+
"x", NewArgument("int"),
9+
"y", NewArgument("int", 3))
10+
11+
f := func(arg map[string]interface{}) int {
12+
out, err := r.Check(arg)
13+
if err != nil {
14+
t.Error("The argument should be correct")
15+
}
16+
17+
na := out["x"].(int)
18+
nb := out["y"].(int)
19+
20+
return na + nb
21+
}
22+
23+
args := make(map[string]interface{})
24+
args["x"] = 3
25+
26+
n := f(args)
27+
if n != 6 {
28+
t.Error("Wrong rule")
29+
}
30+
}
31+
32+
func TestMapRuleViolation(t *testing.T) {
33+
t.Parallel()
34+
35+
r := NewMapRule(
36+
"x", NewArgument("int"),
37+
"y", NewArgument("int", 3))
38+
39+
f := func(arg map[string]interface{}) int {
40+
out, err := r.Check(arg)
41+
if err == nil {
42+
t.Error("The argument should be wrong")
43+
} else {
44+
return 0
45+
}
46+
47+
na := out["x"].(int)
48+
nb := out["y"].(int)
49+
50+
return na + nb
51+
}
52+
53+
args := make(map[string]interface{})
54+
args["x"] = 3
55+
args["z"] = 5
56+
57+
_ = f(args)
58+
}

0 commit comments

Comments
 (0)