-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathunion.go
More file actions
74 lines (62 loc) · 1.64 KB
/
union.go
File metadata and controls
74 lines (62 loc) · 1.64 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
package check
import "fmt"
// UnionSchema validates that a value matches at least one of the given schemas.
type UnionSchema struct {
optional bool
schemas []Schema
}
func NewUnion(schemas ...Schema) *UnionSchema {
return &UnionSchema{schemas: schemas}
}
// clone returns a copy of this schema to preserve immutability in chains.
func (s *UnionSchema) clone() *UnionSchema {
copy := *s
if s.schemas != nil {
copySchemas := make([]Schema, len(s.schemas))
for i, v := range s.schemas {
copySchemas[i] = v
}
copy.schemas = copySchemas
}
return ©
}
func (s *UnionSchema) Optional() *UnionSchema {
s = s.clone()
s.optional = true
return s
}
func (s *UnionSchema) IsOptional() bool { return s.optional }
func (s *UnionSchema) Parse(value any) (any, error) {
if value == nil {
if s.optional {
return nil, nil
}
return nil, ValidationErrors([]ValidationError{{Message: "required value is missing"}})
}
for _, schema := range s.schemas {
if result, err := schema.Parse(value); err == nil {
return result, nil
}
}
return nil, ValidationErrors([]ValidationError{{
Message: fmt.Sprintf("value does not match any of the %d schemas in union", len(s.schemas)),
Value: value,
}})
}
func (s *UnionSchema) Validate(value any) []ValidationError {
if value == nil {
if s.optional {
return nil
}
return []ValidationError{{Message: "required value is missing"}}
}
for _, schema := range s.schemas {
if errs := schema.Validate(value); len(errs) == 0 {
return nil
}
}
return []ValidationError{{
Message: fmt.Sprintf("value does not match any of the %d schemas in union", len(s.schemas)),
Value: value,
}}
}