Skip to content

Commit da9d832

Browse files
author
Antoine Pelisse
committed
Create map of PathElement to Value and use it instead of Strings
1 parent 55299fe commit da9d832

File tree

1 file changed

+73
-24
lines changed

1 file changed

+73
-24
lines changed

typed/merge.go

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,62 @@ limitations under the License.
1717
package typed
1818

1919
import (
20+
"sort"
21+
2022
"sigs.k8s.io/structured-merge-diff/fieldpath"
2123
"sigs.k8s.io/structured-merge-diff/schema"
2224
"sigs.k8s.io/structured-merge-diff/value"
2325
)
2426

27+
type pathElementValueMap struct {
28+
members sortedPathElementValues
29+
}
30+
31+
type pathElementValue struct {
32+
PathElement fieldpath.PathElement
33+
Value value.Value
34+
}
35+
36+
type sortedPathElementValues []pathElementValue
37+
38+
// Implement the sort interface; this would permit bulk creation, which would
39+
// be faster than doing it one at a time via Insert.
40+
func (spev sortedPathElementValues) Len() int { return len(spev) }
41+
func (spev sortedPathElementValues) Less(i, j int) bool {
42+
return spev[i].PathElement.Less(spev[j].PathElement)
43+
}
44+
func (spev sortedPathElementValues) Swap(i, j int) { spev[i], spev[j] = spev[j], spev[i] }
45+
46+
// Insert adds pe to the set.
47+
func (s *pathElementValueMap) Insert(pe fieldpath.PathElement, v value.Value) {
48+
loc := sort.Search(len(s.members), func(i int) bool {
49+
return !s.members[i].PathElement.Less(pe)
50+
})
51+
if loc == len(s.members) {
52+
s.members = append(s.members, pathElementValue{pe, v})
53+
return
54+
}
55+
if s.members[loc].PathElement.Equals(pe) {
56+
return
57+
}
58+
s.members = append(s.members, pathElementValue{})
59+
copy(s.members[loc+1:], s.members[loc:])
60+
s.members[loc] = pathElementValue{pe, v}
61+
}
62+
63+
func (s *pathElementValueMap) Get(pe fieldpath.PathElement) *value.Value {
64+
loc := sort.Search(len(s.members), func(i int) bool {
65+
return !s.members[i].PathElement.Less(pe)
66+
})
67+
if loc == len(s.members) {
68+
return nil
69+
}
70+
if s.members[loc].PathElement.Equals(pe) {
71+
return &s.members[loc].Value
72+
}
73+
return nil
74+
}
75+
2576
type mergingWalker struct {
2677
errorFormatter
2778
lhs *value.Value
@@ -168,7 +219,7 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
168219
rhsOrder := []fieldpath.PathElement{}
169220

170221
// First, collect all RHS children.
171-
observedRHS := map[string]value.Value{}
222+
observedRHS := pathElementValueMap{}
172223
if rhs != nil {
173224
for i, child := range rhs.Items {
174225
pe, err := listItemToPathElement(t, i, child)
@@ -179,17 +230,16 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
179230
// this element.
180231
continue
181232
}
182-
keyStr := pe.String()
183-
if _, found := observedRHS[keyStr]; found {
184-
errs = append(errs, w.errorf("rhs: duplicate entries for key %v", keyStr)...)
233+
if observedRHS.Get(pe) != nil {
234+
errs = append(errs, w.errorf("rhs: duplicate entries for key %v", pe.String())...)
185235
}
186-
observedRHS[keyStr] = child
236+
observedRHS.Insert(pe, child)
187237
rhsOrder = append(rhsOrder, pe)
188238
}
189239
}
190240

191241
// Then merge with LHS children.
192-
observedLHS := map[string]struct{}{}
242+
observedLHS := fieldpath.PathElementSet{}
193243
if lhs != nil {
194244
for i, child := range lhs.Items {
195245
pe, err := listItemToPathElement(t, i, child)
@@ -200,39 +250,38 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
200250
// this element.
201251
continue
202252
}
203-
keyStr := pe.String()
204-
if _, found := observedLHS[keyStr]; found {
205-
errs = append(errs, w.errorf("lhs: duplicate entries for key %v", keyStr)...)
253+
if observedLHS.Has(pe) {
254+
errs = append(errs, w.errorf("lhs: duplicate entries for key %v", pe.String())...)
206255
continue
207256
}
208-
observedLHS[keyStr] = struct{}{}
257+
observedLHS.Insert(pe)
209258
w2 := w.prepareDescent(pe, t.ElementType)
210259
w2.lhs = &child
211-
if rchild, ok := observedRHS[keyStr]; ok {
212-
w2.rhs = &rchild
260+
if rchild := observedRHS.Get(pe); rchild != nil {
261+
w2.rhs = rchild
213262
}
214263
if newErrs := w2.merge(); len(newErrs) > 0 {
215264
errs = append(errs, newErrs...)
216265
} else if w2.out != nil {
217266
out.Items = append(out.Items, *w2.out)
218267
}
219268
w.finishDescent(w2)
220-
// Keep track of children that have been handled
221-
delete(observedRHS, keyStr)
222269
}
223270
}
224271

225-
for _, rhsToCheck := range rhsOrder {
226-
if unmergedChild, ok := observedRHS[rhsToCheck.String()]; ok {
227-
w2 := w.prepareDescent(rhsToCheck, t.ElementType)
228-
w2.rhs = &unmergedChild
229-
if newErrs := w2.merge(); len(newErrs) > 0 {
230-
errs = append(errs, newErrs...)
231-
} else if w2.out != nil {
232-
out.Items = append(out.Items, *w2.out)
233-
}
234-
w.finishDescent(w2)
272+
for _, pe := range rhsOrder {
273+
if observedLHS.Has(pe) {
274+
continue
275+
}
276+
value := observedRHS.Get(pe)
277+
w2 := w.prepareDescent(pe, t.ElementType)
278+
w2.rhs = value
279+
if newErrs := w2.merge(); len(newErrs) > 0 {
280+
errs = append(errs, newErrs...)
281+
} else if w2.out != nil {
282+
out.Items = append(out.Items, *w2.out)
235283
}
284+
w.finishDescent(w2)
236285
}
237286

238287
if len(out.Items) > 0 {

0 commit comments

Comments
 (0)