-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmap_schema.go
More file actions
93 lines (77 loc) · 1.95 KB
/
map_schema.go
File metadata and controls
93 lines (77 loc) · 1.95 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
package check
import "fmt"
// MapSchema validates map[string]any where all keys match a key schema
// and all values match a value schema.
type MapSchema struct {
optional bool
key Schema
value Schema
minLen *int
maxLen *int
}
func NewMap(key, value Schema) *MapSchema {
return &MapSchema{key: key, value: value}
}
// clone returns a copy of this schema to preserve immutability in chains.
func (s *MapSchema) clone() *MapSchema {
copy := *s
return ©
}
func (s *MapSchema) Optional() *MapSchema {
s = s.clone()
s.optional = true
return s
}
func (s *MapSchema) MinLength(n int) *MapSchema {
s = s.clone()
s.minLen = &n
return s
}
func (s *MapSchema) MaxLength(n int) *MapSchema {
s = s.clone()
s.maxLen = &n
return s
}
func (s *MapSchema) IsOptional() bool { return s.optional }
func (s *MapSchema) Parse(value any) (any, error) {
errs := s.Validate(value)
if len(errs) > 0 {
return nil, ValidationErrors(errs)
}
if value == nil {
return nil, nil
}
return value, nil
}
func (s *MapSchema) Validate(value any) []ValidationError {
if value == nil {
if s.optional {
return nil
}
return []ValidationError{{Message: "required value is missing"}}
}
m, ok := value.(map[string]any)
if !ok {
return []ValidationError{{Message: fmt.Sprintf("expected map, got %T", value), Value: value}}
}
var errs []ValidationError
if s.minLen != nil && len(m) < *s.minLen {
errs = append(errs, ValidationError{
Message: fmt.Sprintf("map must have at least %d entries (got %d)", *s.minLen, len(m)),
Value: len(m),
})
}
if s.maxLen != nil && len(m) > *s.maxLen {
errs = append(errs, ValidationError{
Message: fmt.Sprintf("map must have at most %d entries (got %d)", *s.maxLen, len(m)),
Value: len(m),
})
}
for k, v := range m {
keyErrs := s.key.Validate(k)
errs = append(errs, prefixErrors(k+"(key)", keyErrs)...)
valErrs := s.value.Validate(v)
errs = append(errs, prefixErrors(k, valErrs)...)
}
return errs
}