@@ -43,6 +43,9 @@ type mergingWalker struct {
43
43
44
44
// internal housekeeping--don't set when constructing.
45
45
inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list
46
+
47
+ // Allocate only as many walkers as needed for the depth by storing them here.
48
+ spareWalkers * []* mergingWalker
46
49
}
47
50
48
51
// merge rules examine w.lhs and w.rhs (up to one of which may be nil) and
@@ -117,13 +120,30 @@ func (w *mergingWalker) doScalar(t schema.Scalar) (errs ValidationErrors) {
117
120
}
118
121
119
122
func (w * mergingWalker ) prepareDescent (pe fieldpath.PathElement , tr schema.TypeRef ) * mergingWalker {
120
- w2 := * w
123
+ if w .spareWalkers == nil {
124
+ // first descent.
125
+ w .spareWalkers = & []* mergingWalker {}
126
+ }
127
+ var w2 * mergingWalker
128
+ if n := len (* w .spareWalkers ); n > 0 {
129
+ w2 , * w .spareWalkers = (* w .spareWalkers )[n - 1 ], (* w .spareWalkers )[:n - 1 ]
130
+ } else {
131
+ w2 = & mergingWalker {}
132
+ }
133
+ * w2 = * w
121
134
w2 .typeRef = tr
122
135
w2 .errorFormatter .descend (pe )
123
136
w2 .lhs = nil
124
137
w2 .rhs = nil
125
138
w2 .out = nil
126
- return & w2
139
+ return w2
140
+ }
141
+
142
+ func (w * mergingWalker ) finishDescent (w2 * mergingWalker ) {
143
+ // if the descent caused a realloc, ensure that we reuse the buffer
144
+ // for the next sibling.
145
+ w .errorFormatter = w2 .errorFormatter .parent ()
146
+ * w .spareWalkers = append (* w .spareWalkers , w2 )
127
147
}
128
148
129
149
func (w * mergingWalker ) derefMap (prefix string , v * value.Value , dest * * value.Map ) (errs ValidationErrors ) {
@@ -198,6 +218,7 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
198
218
} else if w2 .out != nil {
199
219
out .Items = append (out .Items , * w2 .out )
200
220
}
221
+ w .finishDescent (w2 )
201
222
// Keep track of children that have been handled
202
223
delete (observedRHS , keyStr )
203
224
}
@@ -212,6 +233,7 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err
212
233
} else if w2 .out != nil {
213
234
out .Items = append (out .Items , * w2 .out )
214
235
}
236
+ w .finishDescent (w2 )
215
237
}
216
238
}
217
239
@@ -272,13 +294,13 @@ func (w *mergingWalker) visitMapItems(t schema.Map, lhs, rhs *value.Map) (errs V
272
294
}
273
295
274
296
if lhs != nil {
275
- for _ , litem := range lhs .Items {
276
- name := litem . Name
297
+ for i := range lhs .Items {
298
+ litem := & lhs . Items [ i ]
277
299
fieldType := t .ElementType
278
- if ft , ok := fieldTypes [name ]; ok {
300
+ if ft , ok := fieldTypes [litem . Name ]; ok {
279
301
fieldType = ft
280
302
}
281
- w2 := w .prepareDescent (fieldpath.PathElement {FieldName : & name }, fieldType )
303
+ w2 := w .prepareDescent (fieldpath.PathElement {FieldName : & litem . Name }, fieldType )
282
304
w2 .lhs = & litem .Value
283
305
if rhs != nil {
284
306
if ritem , ok := rhs .Get (litem .Name ); ok {
@@ -288,31 +310,33 @@ func (w *mergingWalker) visitMapItems(t schema.Map, lhs, rhs *value.Map) (errs V
288
310
if newErrs := w2 .merge (); len (newErrs ) > 0 {
289
311
errs = append (errs , newErrs ... )
290
312
} else if w2 .out != nil {
291
- out .Set ( name , * w2 .out )
313
+ out .Items = append ( out . Items , value. Field { litem . Name , * w2 .out } )
292
314
}
315
+ w .finishDescent (w2 )
293
316
}
294
317
}
295
318
296
319
if rhs != nil {
297
- for _ , ritem := range rhs .Items {
320
+ for j := range rhs .Items {
321
+ ritem := & rhs .Items [j ]
298
322
if lhs != nil {
299
323
if _ , ok := lhs .Get (ritem .Name ); ok {
300
324
continue
301
325
}
302
326
}
303
327
304
- name := ritem .Name
305
328
fieldType := t .ElementType
306
- if ft , ok := fieldTypes [name ]; ok {
329
+ if ft , ok := fieldTypes [ritem . Name ]; ok {
307
330
fieldType = ft
308
331
}
309
- w2 := w .prepareDescent (fieldpath.PathElement {FieldName : & name }, fieldType )
332
+ w2 := w .prepareDescent (fieldpath.PathElement {FieldName : & ritem . Name }, fieldType )
310
333
w2 .rhs = & ritem .Value
311
334
if newErrs := w2 .merge (); len (newErrs ) > 0 {
312
335
errs = append (errs , newErrs ... )
313
336
} else if w2 .out != nil {
314
- out .Set ( name , * w2 .out )
337
+ out .Items = append ( out . Items , value. Field { ritem . Name , * w2 .out } )
315
338
}
339
+ w .finishDescent (w2 )
316
340
}
317
341
}
318
342
0 commit comments