Skip to content

Commit 43b4ba1

Browse files
authored
Feat opt (#13)
* optimize code * update README_zh.md * update travis * update travis * fix travis * update README
1 parent 5dcf01f commit 43b4ba1

20 files changed

+695
-439
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ install:
1212
script:
1313
- test -z "`gofmt -l -d .`"
1414
- go test -v -covermode=count -coverprofile=coverage.out
15-
- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci
15+
- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci

README.md

Lines changed: 110 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,35 +29,127 @@ When use `Add` to add rule,`fieldExpr` has three situations:
2929
- `fieldExpr` is single field,fetch value in struct, then validate.
3030
- `fieldExpr` is string separated by `.`, fetch value in struct according hierarchy of struct, then validate.
3131

32+
When fetching value by `fieldExpr`, if the field is pointer, it will fetch the underlying value of pointer
33+
to validate; if the field is nil pointer, it failed validation rule.
3234

35+
example from `checker_test.go`
3336
```go
37+
// Item.Email is the format of email address
3438
type Item struct {
35-
Info typeInfo
39+
Info typeInfo
40+
Email string
3641
}
3742

38-
// typeInfo.Type = "range", length of typeInfo.Type is 2,elements meets format of "2006-01-02"
39-
// typeInfo.Type = "last", length of typeInfo.Typeis 1,elements meets of format positive integer,
40-
// Granularity must be one of day/week/month
43+
type typeStr string
44+
// Item.Info.Type = "range",typeInfo.Type 's length is 2,elements with format of "2006-01-02"
45+
// Item.Info.Type = "last",typeInfo.Type 'is length is 1,elements is positive integer,Granularity is one of day/week/month
4146
type typeInfo struct {
42-
Type string
47+
Type typeStr
4348
Range []string
4449
Unit string
4550
Granularity string
4651
}
4752

48-
// here is the rule
49-
rule := Field("Info",
50-
Or(
51-
And(
52-
EqStr("Type", "range"),
53-
Length("Range", 2, 2),
54-
Array("Range", isDatetime("", "2006-01-02")),
55-
),
56-
And(
57-
EqStr("Type", "last"),
58-
InStr("Granularity", "day", "week", "month"),
59-
Number("Unit"),
53+
54+
// rules are as follow
55+
rule := And(
56+
Email("Email"),
57+
Field("Info",
58+
Or(
59+
And(
60+
EqStr("Type", "range"),
61+
Length("Range", 2, 2),
62+
Array("Range", isDatetime("", "2006-01-02")),
63+
),
64+
And(
65+
EqStr("Type", "last"),
66+
InStr("Granularity", "day", "week", "month"),
67+
Number("Unit"),
68+
),
6069
),
6170
),
6271
)
63-
```
72+
itemChecker := NewChecker()
73+
// validate parameter
74+
itemChecker.Add(rule, "wrong item")
75+
```
76+
77+
## Rule
78+
`Rule` is an interface, it has many implementations. Its implementations can be categorized into
79+
two kinds: composite rule and singleton rule.
80+
81+
### Composite Rule
82+
83+
Composite Rule contains other rules.
84+
85+
| Name | Usage |
86+
| ---------------------------------------------------------- | ----------------------------------------------------- |
87+
| `Field(fieldExpr string, rule Rule) Rule` | Applies `rule` to validate `fieldExpr` |
88+
| `And(rules ...Rule) Rule` | It needs all rules pass |
89+
| `Or(rules ...Rule) Rule` | It needs any rule passed |
90+
| `Not(innerRule Rule) Rule` | opposite the rule |
91+
| `Array(fieldExpr string, innerRule Rule) Rule` | Applies rule to elements in array |
92+
| `Map(fieldExpr string, keyRule Rule, valueRule Rule) Rule` | Applies keyRule and valueRule to key and value in map |
93+
94+
95+
96+
### Singleton Rule
97+
98+
Singleton Rule can be categorized into comparison rule, enum rule and format rule.
99+
100+
#### Comparison Rule
101+
102+
103+
Comparison Rule can be categorized into single field comparison rule and multi-field comparison rule
104+
105+
106+
107+
single field comparison rule includes:
108+
109+
| Name |
110+
| ------------------------------------------------- |
111+
| `EqInt(filedExpr string, equivalent int) Rule` |
112+
| `NeInt(filedExpr string, inequivalent int) Rule` |
113+
| `RangeInt(filedExpr string, ge int, le int) Rule` |
114+
115+
116+
It also has the implementation of `uint`, `string``float``time.Time` , `Comparable`.
117+
118+
119+
120+
multi-field comparison rule includes
121+
122+
| Name |
123+
| ------------------------------------------------------------ |
124+
| `CrossComparable(fieldExprLeft string, fieldExprRight string, op operand) Rule` |
125+
126+
127+
`fieldExprLeft``fieldExprRight` is to located the field involving comparsion, `op` is the operand.
128+
129+
`CrossComparable` supports `int`\`uint`\`float`\`string`\`time.Time`\`Comparable`.
130+
131+
#### Enum Rule
132+
133+
Enum Rule includes
134+
135+
| Name |
136+
| ------------------------------------------------- |
137+
| `InStr(filedExpr string, enum ...string) Rule` |
138+
| `InInt(filedExpr string, enum ...int) Rule` |
139+
| `InUint(filedExpr string, enum ...uint) Rule` |
140+
| `InFloat(filedExpr string, enum ...float64) Rule` |
141+
142+
143+
144+
#### Format Rule
145+
146+
Format Rule includes
147+
148+
| Name |
149+
| ------------------------------- |
150+
| `Email(fieldExpr string) Rule` |
151+
| `Number(fieldExpr string) Rule` |
152+
| `URL(fieldExpr string) Rule` |
153+
| `Ip(fieldExpr string) Rule` |
154+
155+
etc.

README_zh.md

Lines changed: 107 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,124 @@ go get -u github.com/liangyaopei/checker
2727
- `fieldExpr`为单个字段,这时会先取字段的值,再校验。
2828
- `fieldExpr`为点(.)分割的字段,先按照`.`的层级关系取值,再校验。
2929

30+
按字段取值时,如果字段是指针,就取指针的值校验;如果是空指针,则视为没有通过校验。
31+
32+
来自`checker_test.go`的例子:
3033
```go
34+
// Item.Email需要符合电子邮箱的格式
3135
type Item struct {
32-
Info typeInfo
36+
Info typeInfo
37+
Email string
3338
}
3439

35-
// typeInfo.Type = "range",typeInfo.Type的长度为2,元素都是格式符合"2006-01-02"
36-
// typeInfo.Type = "last",typeInfo.Type的长度为1,元素是正整数,Granularity只能是day/week/month之一
40+
type typeStr string
41+
// Item.Info.Type = "range",typeInfo.Type的长度为2,元素都是格式符合"2006-01-02"
42+
// Item.Info.Type = "last",typeInfo.Type的长度为1,元素是正整数,Granularity只能是day/week/month之一
3743
type typeInfo struct {
38-
Type string
44+
Type typeStr
3945
Range []string
4046
Unit string
4147
Granularity string
4248
}
4349

50+
4451
// 规则如下
45-
rule := Field("Info",
46-
Or(
47-
And(
48-
EqStr("Type", "range"),
49-
Length("Range", 2, 2),
50-
Array("Range", isDatetime("", "2006-01-02")),
51-
),
52-
And(
53-
EqStr("Type", "last"),
54-
InStr("Granularity", "day", "week", "month"),
55-
Number("Unit"),
52+
rule := And(
53+
Email("Email"),
54+
Field("Info",
55+
Or(
56+
And(
57+
EqStr("Type", "range"),
58+
Length("Range", 2, 2),
59+
Array("Range", isDatetime("", "2006-01-02")),
60+
),
61+
And(
62+
EqStr("Type", "last"),
63+
InStr("Granularity", "day", "week", "month"),
64+
Number("Unit"),
65+
),
5666
),
5767
),
5868
)
59-
```
69+
itemChecker := NewChecker()
70+
// 校验参数
71+
itemChecker.Add(rule, "wrong item")
72+
```
73+
74+
## 规则
75+
`Rule`是一个接口,它有很多的实现。`Rule`的实现可以分为复合规则和单个规则。
76+
77+
78+
79+
### 复合规则
80+
81+
复合规则包含其他的规则。
82+
83+
| 名字 | 作用 |
84+
| ---------------------------------------------------------- | ---------------------------------------------- |
85+
| `Field(fieldExpr string, rule Rule) Rule` | 对字段使用`rule`校验 |
86+
| `And(rules ...Rule) Rule` | 需要所有的规则都通过 |
87+
| `Or(rules ...Rule) Rule` | 需要由一个规则通过 |
88+
| `Not(innerRule Rule) Rule` | 对规则取反 |
89+
| `Array(fieldExpr string, innerRule Rule) Rule` | 对数组的每一个元素使用规则 |
90+
| `Map(fieldExpr string, keyRule Rule, valueRule Rule) Rule` | 对map的key/value使用keyRule和valueRule进行校验 |
91+
92+
93+
94+
### 单个规则
95+
96+
单个规则可分为比较型,枚举型,格式型等。
97+
98+
#### 比较型规则
99+
100+
比较型规则分为单个字段比较规则,多个字段比较规则。
101+
102+
103+
104+
单个字段比较规则包括:
105+
106+
| 名字 |
107+
| ------------------------------------------------- |
108+
| `EqInt(filedExpr string, equivalent int) Rule` |
109+
| `NeInt(filedExpr string, inequivalent int) Rule` |
110+
| `RangeInt(filedExpr string, ge int, le int) Rule` |
111+
112+
以及`uint`, `string``float``time.Time` , `Comparable`的实现。
113+
114+
多个字段比较规则
115+
116+
| 名字 |
117+
| ------------------------------------------------------------ |
118+
| `CrossComparable(fieldExprLeft string, fieldExprRight string, op operand) Rule` |
119+
120+
`fieldExprLeft``fieldExprRight`用来定位参加比较的字段,`op`是运算操作符,包括相等/不等/大于等。
121+
122+
``CrossComparable`支持的字段类型包括`int`\`uint`\`float`\`string`\`time.Time`\`Comparable`。
123+
124+
125+
126+
#### 枚举型规则
127+
128+
枚举型包括
129+
130+
| 名字 |
131+
| ------------------------------------------------- |
132+
| `InStr(filedExpr string, enum ...string) Rule` |
133+
| `InInt(filedExpr string, enum ...int) Rule` |
134+
| `InUint(filedExpr string, enum ...uint) Rule` |
135+
| `InFloat(filedExpr string, enum ...float64) Rule` |
136+
137+
138+
139+
#### 格式型规则
140+
141+
格式型规则包括
142+
143+
| 名字 |
144+
| ------------------------------- |
145+
| `Email(fieldExpr string) Rule` |
146+
| `Number(fieldExpr string) Rule` |
147+
| `URL(fieldExpr string) Rule` |
148+
| `Ip(fieldExpr string) Rule` |
149+
150+
等等

benchmark_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package checker
2+
3+
import "testing"
4+
5+
func BenchmarkIp(b *testing.B) {
6+
type Test struct {
7+
IP string
8+
}
9+
test := Test{IP: "127.0.0.1"}
10+
11+
ipChecker := NewChecker()
12+
ipChecker.Add(Ip("IP"), "wrong ip")
13+
b.ResetTimer()
14+
for n := 0; n < b.N; n++ {
15+
_, _, _ = ipChecker.Check(test)
16+
}
17+
}
18+
19+
func BenchmarkNot(b *testing.B) {
20+
type Test struct {
21+
NotIP string
22+
}
23+
test := Test{NotIP: "127.0.0.1.1"}
24+
25+
notIPChecker := NewChecker()
26+
notIPChecker.Add(Not(Ip("IP")), "wrong ip")
27+
b.ResetTimer()
28+
for n := 0; n < b.N; n++ {
29+
_, _, _ = notIPChecker.Check(test)
30+
}
31+
}
32+
33+
func BenchmarkMap(b *testing.B) {
34+
35+
kvMap := make(map[keyStruct]valueStruct)
36+
keys := []keyStruct{{1}, {2}, {3}}
37+
for _, key := range keys {
38+
kvMap[key] = valueStruct{Value: 9}
39+
}
40+
m := mapStruct{
41+
kvMap,
42+
}
43+
44+
mapChecker := NewChecker()
45+
mapRule := Map("Map",
46+
RangeInt("Key", 1, 10),
47+
InInt("Value", 8, 9, 10))
48+
mapChecker.Add(mapRule, "invalid map")
49+
50+
b.ResetTimer()
51+
for n := 0; n < b.N; n++ {
52+
_, _, _ = mapChecker.Check(m)
53+
}
54+
}

0 commit comments

Comments
 (0)