-
Notifications
You must be signed in to change notification settings - Fork 3
/
validator.go
76 lines (66 loc) · 1.85 KB
/
validator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package popart
var (
errInvalidSyntax = NewReportableError("invalid syntax")
errUnexpectedState = NewReportableError("unexpected state transition")
)
var (
validators = map[string]*validator{
"APOP": validates(state(stateAuthorization), arity(2)),
"CAPA": validates(state(stateAuthorization, stateTransaction), arity(0)),
"DELE": validates(state(stateTransaction), arity(1)),
"LIST": validates(state(stateTransaction), arity(0, 1)),
"NOOP": validates(state(stateTransaction), arity(0)),
"PASS": validates(state(stateAuthorization), arity(1)),
"QUIT": validates(state(stateAuthorization, stateTransaction), arity(0)),
"RETR": validates(state(stateTransaction), arity(1)),
"RSET": validates(state(stateTransaction), arity(0)),
"STAT": validates(state(stateTransaction), arity(0)),
"TOP": validates(state(stateTransaction), arity(2)),
"UIDL": validates(state(stateTransaction), arity(0, 1)),
"USER": validates(state(stateAuthorization), arity(1)),
}
)
type validator struct {
allowedStates []int
allowedArities []int
}
type option func(*validator)
func validates(opts ...option) *validator {
ret := &validator{}
for _, opt := range opts {
opt(ret)
}
return ret
}
func (v *validator) validate(s *session, args []string) error {
if err := v.allowedState(s); err != nil {
return err
}
return v.allowedArity(args)
}
func (v *validator) allowedState(s *session) error {
for _, state := range v.allowedStates {
if state == s.state {
return nil
}
}
return errUnexpectedState
}
func (v *validator) allowedArity(args []string) error {
for _, ar := range v.allowedArities {
if ar == len(args) {
return nil
}
}
return errInvalidSyntax
}
func state(states ...int) option {
return func(v *validator) {
v.allowedStates = states
}
}
func arity(arities ...int) option {
return func(v *validator) {
v.allowedArities = arities
}
}