...
1
16
17 package fieldpath
18
19 import (
20 "sigs.k8s.io/structured-merge-diff/v4/value"
21 )
22
23
24 func SetFromValue(v value.Value) *Set {
25 s := NewSet()
26
27 w := objectWalker{
28 path: Path{},
29 value: v,
30 allocator: value.NewFreelistAllocator(),
31 do: func(p Path) { s.Insert(p) },
32 }
33
34 w.walk()
35 return s
36 }
37
38 type objectWalker struct {
39 path Path
40 value value.Value
41 allocator value.Allocator
42
43 do func(Path)
44 }
45
46 func (w *objectWalker) walk() {
47 switch {
48 case w.value.IsNull():
49 case w.value.IsFloat():
50 case w.value.IsInt():
51 case w.value.IsString():
52 case w.value.IsBool():
53
54
55
56
57 case w.value.IsList():
58
59
60 l := w.value.AsListUsing(w.allocator)
61 defer w.allocator.Free(l)
62 iter := l.RangeUsing(w.allocator)
63 defer w.allocator.Free(iter)
64 for iter.Next() {
65 i, value := iter.Item()
66 w2 := *w
67 w2.path = append(w.path, w.GuessBestListPathElement(i, value))
68 w2.value = value
69 w2.walk()
70 }
71 return
72 case w.value.IsMap():
73
74
75
76 m := w.value.AsMapUsing(w.allocator)
77 defer w.allocator.Free(m)
78 m.IterateUsing(w.allocator, func(k string, val value.Value) bool {
79 w2 := *w
80 w2.path = append(w.path, PathElement{FieldName: &k})
81 w2.value = val
82 w2.walk()
83 return true
84 })
85 return
86 }
87
88
89 if len(w.path) > 0 {
90 w.do(w.path)
91 }
92 }
93
94
95
96 var AssociativeListCandidateFieldNames = []string{
97 "key",
98 "id",
99 "name",
100 }
101
102
103
104
105
106
107 func (w *objectWalker) GuessBestListPathElement(index int, item value.Value) PathElement {
108 if !item.IsMap() {
109
110
111
112 return PathElement{Index: &index}
113 }
114
115 m := item.AsMapUsing(w.allocator)
116 defer w.allocator.Free(m)
117 var keys value.FieldList
118 for _, name := range AssociativeListCandidateFieldNames {
119 f, ok := m.Get(name)
120 if !ok {
121 continue
122 }
123
124 if f.IsNull() || f.IsMap() || f.IsList() {
125 continue
126 }
127 keys = append(keys, value.Field{Name: name, Value: f})
128 }
129 if len(keys) > 0 {
130 keys.Sort()
131 return PathElement{Key: &keys}
132 }
133 return PathElement{Index: &index}
134 }
135
View as plain text