...
1
13
14 package typed
15
16 import (
17 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
18 "sigs.k8s.io/structured-merge-diff/v4/schema"
19 "sigs.k8s.io/structured-merge-diff/v4/value"
20 )
21
22 type removingWalker struct {
23 value value.Value
24 out interface{}
25 schema *schema.Schema
26 toRemove *fieldpath.Set
27 allocator value.Allocator
28 shouldExtract bool
29 }
30
31
32
33
34
35
36 func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef, shouldExtract bool) value.Value {
37 w := &removingWalker{
38 value: val,
39 schema: schema,
40 toRemove: toRemove,
41 allocator: value.NewFreelistAllocator(),
42 shouldExtract: shouldExtract,
43 }
44 resolveSchema(schema, typeRef, val, w)
45 return value.NewValueInterface(w.out)
46 }
47
48 func (w *removingWalker) doScalar(t *schema.Scalar) ValidationErrors {
49 w.out = w.value.Unstructured()
50 return nil
51 }
52
53 func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
54 if !w.value.IsList() {
55 return nil
56 }
57 l := w.value.AsListUsing(w.allocator)
58 defer w.allocator.Free(l)
59
60 if l == nil || l.Length() == 0 {
61 return nil
62 }
63
64
65
66 if t.ElementRelationship == schema.Atomic {
67 if w.shouldExtract {
68 w.out = w.value.Unstructured()
69 }
70 return nil
71 }
72
73 var newItems []interface{}
74 iter := l.RangeUsing(w.allocator)
75 defer w.allocator.Free(iter)
76 for iter.Next() {
77 _, item := iter.Item()
78
79 pe, _ := listItemToPathElement(w.allocator, w.schema, t, item)
80 path, _ := fieldpath.MakePath(pe)
81
82
83 if w.toRemove.Has(path) {
84 if w.shouldExtract {
85 newItems = append(newItems, removeItemsWithSchema(item, w.toRemove, w.schema, t.ElementType, w.shouldExtract).Unstructured())
86 } else {
87 continue
88 }
89 }
90 if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
91 item = removeItemsWithSchema(item, subset, w.schema, t.ElementType, w.shouldExtract)
92 } else {
93
94 if w.shouldExtract {
95 continue
96 }
97 }
98 newItems = append(newItems, item.Unstructured())
99 }
100 if len(newItems) > 0 {
101 w.out = newItems
102 }
103 return nil
104 }
105
106 func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
107 if !w.value.IsMap() {
108 return nil
109 }
110 m := w.value.AsMapUsing(w.allocator)
111 if m != nil {
112 defer w.allocator.Free(m)
113 }
114
115 if m == nil || m.Empty() {
116 return nil
117 }
118
119
120
121 if t.ElementRelationship == schema.Atomic {
122 if w.shouldExtract {
123 w.out = w.value.Unstructured()
124 }
125 return nil
126 }
127
128 fieldTypes := map[string]schema.TypeRef{}
129 for _, structField := range t.Fields {
130 fieldTypes[structField.Name] = structField.Type
131 }
132
133 newMap := map[string]interface{}{}
134 m.Iterate(func(k string, val value.Value) bool {
135 pe := fieldpath.PathElement{FieldName: &k}
136 path, _ := fieldpath.MakePath(pe)
137 fieldType := t.ElementType
138 if ft, ok := fieldTypes[k]; ok {
139 fieldType = ft
140 }
141
142
143 if w.toRemove.Has(path) {
144 if w.shouldExtract {
145 newMap[k] = removeItemsWithSchema(val, w.toRemove, w.schema, fieldType, w.shouldExtract).Unstructured()
146
147 }
148 return true
149 }
150 if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
151 val = removeItemsWithSchema(val, subset, w.schema, fieldType, w.shouldExtract)
152 } else {
153
154 if w.shouldExtract {
155 return true
156 }
157 }
158 newMap[k] = val.Unstructured()
159 return true
160 })
161 if len(newMap) > 0 {
162 w.out = newMap
163 }
164 return nil
165 }
166
View as plain text