-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathvalidator.go
More file actions
147 lines (133 loc) · 2.97 KB
/
validator.go
File metadata and controls
147 lines (133 loc) · 2.97 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package validator
import (
"github.com/dlclark/regexp2"
"github.com/islisp-dev/iris/core"
)
type ValidationError struct {
Actual core.Instance
Expected core.Instance
}
func (err ValidationError) Error() string {
return "Validation Error"
}
type Validator = func (core.Instance) error
func Any(_ core.Instance) error {
return nil
}
func InstanceOf(class core.Class) Validator {
return func (instance core.Instance) error {
ok := core.InstanceOf(class, instance)
if !ok {
return ValidationError{instance, class}
}
return nil
}
}
func Symbol(pattern string) Validator {
re := regexp2.MustCompile(pattern, 0)
return func (instance core.Instance) error {
symbol, ok := instance.(core.Symbol)
if !ok {
return ValidationError{instance, core.SymbolClass}
}
ok, err := re.MatchString(symbol.String())
if err != nil || !ok {
return ValidationError{instance, core.SymbolClass}
}
return nil
}
}
func Or(validators ...Validator) Validator {
return func (instance core.Instance) error {
for _, validator := range validators {
if err := validator(instance); err == nil {
return nil
}
}
return ValidationError{instance, core.ObjectClass}
}
}
func And(validators ...Validator) Validator {
return func (instance core.Instance) error {
for _, validator := range validators {
if err := validator(instance); err != nil {
return err
}
}
return nil
}
}
func Not(validator Validator) Validator {
return func (instance core.Instance) error {
if err := validator(instance); err != nil {
return nil
}
return ValidationError{instance, core.ObjectClass}
}
}
func List(validators ...Validator) Validator {
return func (args core.Instance) error {
if len(validators) == 0 && args == core.Nil {
return nil
}
if len(validators) == 0 || args == core.Nil {
return ValidationError{args, core.ListClass}
}
cons, ok := args.(*core.Cons)
if !ok {
return ValidationError{args, core.ConsClass}
}
if err := validators[0](cons.Car); err != nil {
return err
}
if err := List(validators...)(cons.Cdr); err != nil {
return err
}
return nil
}
}
var Nil = List()
func Append(validators ...Validator) Validator {
return func (args core.Instance) error {
if len(validators) == 0 {
return nil
}
rest := args
for {
cons, ok := rest.(*core.Cons)
if !ok {
return ValidationError{rest, core.ConsClass}
}
rest := cons.Cdr
cons.Cdr = core.Nil
if err := validators[0](args); err != nil {
cons.Cdr = rest
continue
}
if err := Append(validators...)(rest); err != nil {
cons.Cdr = rest
continue
}
return nil
}
}
}
func Repeat(inner Validator) (outer Validator) {
outer = func (args core.Instance) error {
if args == core.Nil {
return nil
}
cons, ok := args.(*core.Cons)
if !ok {
return ValidationError{args, core.ConsClass}
}
if err := inner(cons.Car); err != nil {
return err
}
if err := outer(cons.Cdr); err != nil {
return err
}
return nil
}
return
}