1
16
17 package fieldpath
18
19 import (
20 "sort"
21 "strings"
22
23 "sigs.k8s.io/structured-merge-diff/v4/schema"
24 )
25
26
27 type Set struct {
28
29
30 Members PathElementSet
31
32
33
34
35 Children SetNodeMap
36 }
37
38
39 func NewSet(paths ...Path) *Set {
40 s := &Set{}
41 for _, p := range paths {
42 s.Insert(p)
43 }
44 return s
45 }
46
47
48
49 func (s *Set) Insert(p Path) {
50 if len(p) == 0 {
51
52
53 return
54 }
55 for {
56 if len(p) == 1 {
57 s.Members.Insert(p[0])
58 return
59 }
60 s = s.Children.Descend(p[0])
61 p = p[1:]
62 }
63 }
64
65
66 func (s *Set) Union(s2 *Set) *Set {
67 return &Set{
68 Members: *s.Members.Union(&s2.Members),
69 Children: *s.Children.Union(&s2.Children),
70 }
71 }
72
73
74
75
76 func (s *Set) Intersection(s2 *Set) *Set {
77 return &Set{
78 Members: *s.Members.Intersection(&s2.Members),
79 Children: *s.Children.Intersection(&s2.Children),
80 }
81 }
82
83
84
85
86
87
88
89
90
91
92 func (s *Set) Difference(s2 *Set) *Set {
93 return &Set{
94 Members: *s.Members.Difference(&s2.Members),
95 Children: *s.Children.Difference(s2),
96 }
97 }
98
99
100
101
102
103
104
105
106
107
108 func (s *Set) RecursiveDifference(s2 *Set) *Set {
109 return &Set{
110 Members: *s.Members.Difference(&s2.Members),
111 Children: *s.Children.RecursiveDifference(s2),
112 }
113 }
114
115
116
117
118
119 func (s *Set) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.TypeRef) *Set {
120 members := PathElementSet{
121 members: make(sortedPathElements, 0, s.Members.Size()+len(s.Children.members)),
122 }
123 atom, _ := sc.Resolve(tr)
124 members.members = append(members.members, s.Members.members...)
125 for _, node := range s.Children.members {
126
127 if node.pathElement.FieldName != nil && atom.Map != nil {
128 if _, has := atom.Map.FindField(*node.pathElement.FieldName); has {
129 members.Insert(node.pathElement)
130 }
131 }
132 }
133 return &Set{
134 Members: members,
135 Children: *s.Children.EnsureNamedFieldsAreMembers(sc, tr),
136 }
137 }
138
139
140 func (s *Set) Size() int {
141 return s.Members.Size() + s.Children.Size()
142 }
143
144
145
146
147 func (s *Set) Empty() bool {
148 if s.Members.Size() > 0 {
149 return false
150 }
151 return s.Children.Empty()
152 }
153
154
155 func (s *Set) Has(p Path) bool {
156 if len(p) == 0 {
157
158 return false
159 }
160 for {
161 if len(p) == 1 {
162 return s.Members.Has(p[0])
163 }
164 var ok bool
165 s, ok = s.Children.Get(p[0])
166 if !ok {
167 return false
168 }
169 p = p[1:]
170 }
171 }
172
173
174 func (s *Set) Equals(s2 *Set) bool {
175 return s.Members.Equals(&s2.Members) && s.Children.Equals(&s2.Children)
176 }
177
178
179 func (s *Set) String() string {
180 elements := []string{}
181 s.Iterate(func(p Path) {
182 elements = append(elements, p.String())
183 })
184 return strings.Join(elements, "\n")
185 }
186
187
188
189
190 func (s *Set) Iterate(f func(Path)) {
191 s.iteratePrefix(Path{}, f)
192 }
193
194 func (s *Set) iteratePrefix(prefix Path, f func(Path)) {
195 s.Members.Iterate(func(pe PathElement) { f(append(prefix, pe)) })
196 s.Children.iteratePrefix(prefix, f)
197 }
198
199
200
201 func (s *Set) WithPrefix(pe PathElement) *Set {
202 subset, ok := s.Children.Get(pe)
203 if !ok {
204 return NewSet()
205 }
206 return subset
207 }
208
209
210
211 func (s *Set) Leaves() *Set {
212 leaves := PathElementSet{}
213 im := 0
214 ic := 0
215
216
217 outer:
218 for im < len(s.Members.members) {
219 member := s.Members.members[im]
220
221 for ic < len(s.Children.members) {
222 d := member.Compare(s.Children.members[ic].pathElement)
223 if d == 0 {
224 ic++
225 im++
226 continue outer
227 } else if d < 0 {
228 break
229 } else {
230 ic++
231 }
232 }
233 leaves.members = append(leaves.members, member)
234 im++
235 }
236
237 return &Set{
238 Members: leaves,
239 Children: *s.Children.Leaves(),
240 }
241 }
242
243
244
245 type setNode struct {
246 pathElement PathElement
247 set *Set
248 }
249
250
251 type SetNodeMap struct {
252 members sortedSetNode
253 }
254
255 type sortedSetNode []setNode
256
257
258
259 func (s sortedSetNode) Len() int { return len(s) }
260 func (s sortedSetNode) Less(i, j int) bool { return s[i].pathElement.Less(s[j].pathElement) }
261 func (s sortedSetNode) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
262
263
264 func (s *SetNodeMap) Descend(pe PathElement) *Set {
265 loc := sort.Search(len(s.members), func(i int) bool {
266 return !s.members[i].pathElement.Less(pe)
267 })
268 if loc == len(s.members) {
269 s.members = append(s.members, setNode{pathElement: pe, set: &Set{}})
270 return s.members[loc].set
271 }
272 if s.members[loc].pathElement.Equals(pe) {
273 return s.members[loc].set
274 }
275 s.members = append(s.members, setNode{})
276 copy(s.members[loc+1:], s.members[loc:])
277 s.members[loc] = setNode{pathElement: pe, set: &Set{}}
278 return s.members[loc].set
279 }
280
281
282 func (s *SetNodeMap) Size() int {
283 count := 0
284 for _, v := range s.members {
285 count += v.set.Size()
286 }
287 return count
288 }
289
290
291 func (s *SetNodeMap) Empty() bool {
292 for _, n := range s.members {
293 if !n.set.Empty() {
294 return false
295 }
296 }
297 return true
298 }
299
300
301 func (s *SetNodeMap) Get(pe PathElement) (*Set, bool) {
302 loc := sort.Search(len(s.members), func(i int) bool {
303 return !s.members[i].pathElement.Less(pe)
304 })
305 if loc == len(s.members) {
306 return nil, false
307 }
308 if s.members[loc].pathElement.Equals(pe) {
309 return s.members[loc].set, true
310 }
311 return nil, false
312 }
313
314
315
316 func (s *SetNodeMap) Equals(s2 *SetNodeMap) bool {
317 if len(s.members) != len(s2.members) {
318 return false
319 }
320 for i := range s.members {
321 if !s.members[i].pathElement.Equals(s2.members[i].pathElement) {
322 return false
323 }
324 if !s.members[i].set.Equals(s2.members[i].set) {
325 return false
326 }
327 }
328 return true
329 }
330
331
332 func (s *SetNodeMap) Union(s2 *SetNodeMap) *SetNodeMap {
333 out := &SetNodeMap{}
334
335 i, j := 0, 0
336 for i < len(s.members) && j < len(s2.members) {
337 if s.members[i].pathElement.Less(s2.members[j].pathElement) {
338 out.members = append(out.members, s.members[i])
339 i++
340 } else {
341 if !s2.members[j].pathElement.Less(s.members[i].pathElement) {
342 out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set.Union(s2.members[j].set)})
343 i++
344 } else {
345 out.members = append(out.members, s2.members[j])
346 }
347 j++
348 }
349 }
350
351 if i < len(s.members) {
352 out.members = append(out.members, s.members[i:]...)
353 }
354 if j < len(s2.members) {
355 out.members = append(out.members, s2.members[j:]...)
356 }
357 return out
358 }
359
360
361 func (s *SetNodeMap) Intersection(s2 *SetNodeMap) *SetNodeMap {
362 out := &SetNodeMap{}
363
364 i, j := 0, 0
365 for i < len(s.members) && j < len(s2.members) {
366 if s.members[i].pathElement.Less(s2.members[j].pathElement) {
367 i++
368 } else {
369 if !s2.members[j].pathElement.Less(s.members[i].pathElement) {
370 res := s.members[i].set.Intersection(s2.members[j].set)
371 if !res.Empty() {
372 out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: res})
373 }
374 i++
375 }
376 j++
377 }
378 }
379 return out
380 }
381
382
383 func (s *SetNodeMap) Difference(s2 *Set) *SetNodeMap {
384 out := &SetNodeMap{}
385
386 i, j := 0, 0
387 for i < len(s.members) && j < len(s2.Children.members) {
388 if s.members[i].pathElement.Less(s2.Children.members[j].pathElement) {
389 out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set})
390 i++
391 } else {
392 if !s2.Children.members[j].pathElement.Less(s.members[i].pathElement) {
393
394 diff := s.members[i].set.Difference(s2.Children.members[j].set)
395
396 if !diff.Empty() {
397 out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: diff})
398 }
399
400 i++
401 }
402 j++
403 }
404 }
405
406 if i < len(s.members) {
407 out.members = append(out.members, s.members[i:]...)
408 }
409 return out
410 }
411
412
413
414
415
416
417
418
419 func (s *SetNodeMap) RecursiveDifference(s2 *Set) *SetNodeMap {
420 out := &SetNodeMap{}
421
422 i, j := 0, 0
423 for i < len(s.members) && j < len(s2.Children.members) {
424 if s.members[i].pathElement.Less(s2.Children.members[j].pathElement) {
425 if !s2.Members.Has(s.members[i].pathElement) {
426 out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set})
427 }
428 i++
429 } else {
430 if !s2.Children.members[j].pathElement.Less(s.members[i].pathElement) {
431 if !s2.Members.Has(s.members[i].pathElement) {
432 diff := s.members[i].set.RecursiveDifference(s2.Children.members[j].set)
433 if !diff.Empty() {
434 out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: diff})
435 }
436 }
437 i++
438 }
439 j++
440 }
441 }
442
443 if i < len(s.members) {
444 for _, c := range s.members[i:] {
445 if !s2.Members.Has(c.pathElement) {
446 out.members = append(out.members, c)
447 }
448 }
449 }
450
451 return out
452 }
453
454
455 func (s *SetNodeMap) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.TypeRef) *SetNodeMap {
456 out := make(sortedSetNode, 0, s.Size())
457 atom, _ := sc.Resolve(tr)
458 for _, member := range s.members {
459 tr := schema.TypeRef{}
460 if member.pathElement.FieldName != nil && atom.Map != nil {
461 tr = atom.Map.ElementType
462 if sf, ok := atom.Map.FindField(*member.pathElement.FieldName); ok {
463 tr = sf.Type
464 }
465 } else if member.pathElement.Key != nil && atom.List != nil {
466 tr = atom.List.ElementType
467 }
468 out = append(out, setNode{
469 pathElement: member.pathElement,
470 set: member.set.EnsureNamedFieldsAreMembers(sc, tr),
471 })
472 }
473
474 return &SetNodeMap{
475 members: out,
476 }
477 }
478
479
480 func (s *SetNodeMap) Iterate(f func(PathElement)) {
481 for _, n := range s.members {
482 f(n.pathElement)
483 }
484 }
485
486 func (s *SetNodeMap) iteratePrefix(prefix Path, f func(Path)) {
487 for _, n := range s.members {
488 pe := n.pathElement
489 n.set.iteratePrefix(append(prefix, pe), f)
490 }
491 }
492
493
494
495 func (s *SetNodeMap) Leaves() *SetNodeMap {
496 out := &SetNodeMap{}
497 out.members = make(sortedSetNode, len(s.members))
498 for i, n := range s.members {
499 out.members[i] = setNode{
500 pathElement: n.pathElement,
501 set: n.set.Leaves(),
502 }
503 }
504 return out
505 }
506
View as plain text