Skip to content

Commit 6cd662f

Browse files
committed
Expose ExtractItems as the opposite of RemoveItems
This exposes a new method on TypedValue called ExtractItems. Whereas RemoveItems takes a fieldpath.Set and returns the typed value with the provided set items removed from it, ExtractItems returns ONLY those items provided by the fieldpath.Set, effectively extracting them from the original TypedValue.
1 parent f3141d6 commit 6cd662f

File tree

3 files changed

+822
-14
lines changed

3 files changed

+822
-14
lines changed

typed/remove.go

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,26 @@ import (
2020
)
2121

2222
type removingWalker struct {
23-
value value.Value
24-
out interface{}
25-
schema *schema.Schema
26-
toRemove *fieldpath.Set
27-
allocator value.Allocator
23+
value value.Value
24+
out interface{}
25+
schema *schema.Schema
26+
toRemove *fieldpath.Set
27+
allocator value.Allocator
28+
shouldExtract bool
2829
}
2930

30-
func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef) value.Value {
31+
// removeItemsWithSchema will walk the given value and look for items from the toRemove set.
32+
// Depending on whether shouldExtract is set true or false, it will return a modified version
33+
// of the input value with either:
34+
// 1. only the items in the toRemove set (when shouldExtract is true) or
35+
// 2. the items from the toRemove set removed from the value (when shouldExtract is false).
36+
func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef, shouldExtract bool) value.Value {
3137
w := &removingWalker{
32-
value: val,
33-
schema: schema,
34-
toRemove: toRemove,
35-
allocator: value.NewFreelistAllocator(),
38+
value: val,
39+
schema: schema,
40+
toRemove: toRemove,
41+
allocator: value.NewFreelistAllocator(),
42+
shouldExtract: shouldExtract,
3643
}
3744
resolveSchema(schema, typeRef, val, w)
3845
return value.NewValueInterface(w.out)
@@ -59,11 +66,22 @@ func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
5966
// Ignore error because we have already validated this list
6067
pe, _ := listItemToPathElement(w.allocator, w.schema, t, i, item)
6168
path, _ := fieldpath.MakePath(pe)
69+
// save items on the path when we shouldExtract
70+
// but ignore them when we are removing (i.e. !w.shouldExtract)
6271
if w.toRemove.Has(path) {
63-
continue
72+
if w.shouldExtract {
73+
newItems = append(newItems, item.Unstructured())
74+
} else {
75+
continue
76+
}
6477
}
6578
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
66-
item = removeItemsWithSchema(item, subset, w.schema, t.ElementType)
79+
item = removeItemsWithSchema(item, subset, w.schema, t.ElementType, w.shouldExtract)
80+
} else {
81+
// don't save items not on the path when we shouldExtract.
82+
if w.shouldExtract {
83+
continue
84+
}
6785
}
6886
newItems = append(newItems, item.Unstructured())
6987
}
@@ -96,11 +114,21 @@ func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
96114
if ft, ok := fieldTypes[k]; ok {
97115
fieldType = ft
98116
}
117+
// save values on the path when we shouldExtract
118+
// but ignore them when we are removing (i.e. !w.shouldExtract)
99119
if w.toRemove.Has(path) {
120+
if w.shouldExtract {
121+
newMap[k] = val.Unstructured()
122+
}
100123
return true
101124
}
102125
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
103-
val = removeItemsWithSchema(val, subset, w.schema, fieldType)
126+
val = removeItemsWithSchema(val, subset, w.schema, fieldType, w.shouldExtract)
127+
} else {
128+
// don't save values not on the path when we shouldExtract.
129+
if w.shouldExtract {
130+
return true
131+
}
104132
}
105133
newMap[k] = val.Unstructured()
106134
return true

0 commit comments

Comments
 (0)