-
Notifications
You must be signed in to change notification settings - Fork 7
/
struct_helpers.go
132 lines (122 loc) · 3.7 KB
/
struct_helpers.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
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
package zog
import (
"maps"
p "github.com/Oudwins/zog/internals"
)
// Merge combines two or more schemas into a new schema.
// It performs a shallow merge, meaning:
// - Fields with the same key from later schemas override earlier ones
// - PreTransforms, PostTransforms and tests are concatenated in order
// - Modifying nested schemas may affect the original schemas
//
// Parameters:
// - other: The first schema to merge with
// - others: Additional schemas to merge
//
// Returns a new schema containing the merged fields and transforms
func (v *structProcessor) Merge(other *structProcessor, others ...*structProcessor) *structProcessor {
new := &structProcessor{
preTransforms: make([]p.PreTransform, 0),
postTransforms: make([]p.PostTransform, 0),
tests: make([]p.Test, 0),
required: other.required,
schema: Schema{},
}
if v.preTransforms != nil {
new.preTransforms = append(new.preTransforms, v.preTransforms...)
}
if other.preTransforms != nil {
new.preTransforms = append(new.preTransforms, other.preTransforms...)
}
if v.postTransforms != nil {
new.postTransforms = append(new.postTransforms, v.postTransforms...)
}
if other.postTransforms != nil {
new.postTransforms = append(new.postTransforms, other.postTransforms...)
}
if v.tests != nil {
new.tests = append(new.tests, v.tests...)
}
if other.tests != nil {
new.tests = append(new.tests, other.tests...)
}
maps.Copy(new.schema, v.schema)
maps.Copy(new.schema, other.schema)
for _, o := range others {
new = new.Merge(o)
}
return new
}
// cloneShallow creates a shallow copy of the schema.
// The new schema shares references to the transforms, tests and inner schema.
func (v *structProcessor) cloneShallow() *structProcessor {
new := &structProcessor{
preTransforms: v.preTransforms,
postTransforms: v.postTransforms,
tests: v.tests,
required: v.required,
schema: v.schema,
}
return new
}
// Omit creates a new schema with specified fields removed.
// It accepts either strings or map[string]bool as arguments:
// - Strings directly specify fields to omit
// - For maps, fields are omitted when their boolean value is true
//
// Returns a new schema with the specified fields removed
func (v *structProcessor) Omit(vals ...any) *structProcessor {
new := v.cloneShallow()
new.schema = Schema{}
maps.Copy(new.schema, v.schema)
for _, k := range vals {
switch k := k.(type) {
case string:
delete(new.schema, k)
case map[string]bool:
for key, val := range k {
if val {
delete(new.schema, key)
}
}
}
}
return new
}
// Pick creates a new schema keeping only the specified fields.
// It accepts either strings or map[string]bool as arguments:
// - Strings directly specify fields to keep
// - For maps, fields are kept when their boolean value is true
//
// Returns a new schema containing only the specified fields
func (v *structProcessor) Pick(picks ...any) *structProcessor {
new := v.cloneShallow()
new.schema = Schema{}
for _, pick := range picks {
switch pick := pick.(type) {
case string:
new.schema[pick] = v.schema[pick]
case map[string]bool:
for k, pick := range pick {
if pick {
new.schema[k] = v.schema[k]
}
}
}
}
return new
}
// Extend creates a new schema by adding additional fields from the provided schema.
// Fields in the provided schema override any existing fields with the same key.
//
// Parameters:
// - schema: The schema containing fields to add
//
// Returns a new schema with the additional fields
func (v *structProcessor) Extend(schema Schema) *structProcessor {
new := v.cloneShallow()
new.schema = Schema{}
maps.Copy(new.schema, v.schema)
maps.Copy(new.schema, schema)
return new
}