@@ -94,6 +94,24 @@ func NewProtoMap(adapter Adapter, value *pb.Map) traits.Mapper {
94
94
}
95
95
}
96
96
97
+ // NewMutableMap constructs a mutable map from an adapter and a set of map values.
98
+ func NewMutableMap (adapter Adapter , mutableValues map [ref.Val ]ref.Val ) traits.MutableMapper {
99
+ mutableCopy := make (map [ref.Val ]ref.Val , len (mutableValues ))
100
+ for k , v := range mutableValues {
101
+ mutableCopy [k ] = v
102
+ }
103
+ m := & mutableMap {
104
+ baseMap : & baseMap {
105
+ Adapter : adapter ,
106
+ mapAccessor : newRefValMapAccessor (mutableCopy ),
107
+ value : mutableCopy ,
108
+ size : len (mutableCopy ),
109
+ },
110
+ mutableValues : mutableCopy ,
111
+ }
112
+ return m
113
+ }
114
+
97
115
// mapAccessor is a private interface for finding values within a map and iterating over the keys.
98
116
// This interface implements portions of the API surface area required by the traits.Mapper
99
117
// interface.
@@ -105,6 +123,9 @@ type mapAccessor interface {
105
123
106
124
// Iterator returns an Iterator over the map key set.
107
125
Iterator () traits.Iterator
126
+
127
+ // Fold calls the FoldEntry method for each (key, value) pair in the map.
128
+ Fold (traits.Folder )
108
129
}
109
130
110
131
// baseMap is a reflection based map implementation designed to handle a variety of map-like types.
@@ -307,6 +328,28 @@ func (m *baseMap) Value() any {
307
328
return m .value
308
329
}
309
330
331
+ // mutableMap holds onto a set of mutable values which are used for intermediate computations.
332
+ type mutableMap struct {
333
+ * baseMap
334
+ mutableValues map [ref.Val ]ref.Val
335
+ }
336
+
337
+ // Insert implements the traits.MutableMapper interface method, returning true if the key insertion
338
+ // succeeds.
339
+ func (m * mutableMap ) Insert (k , v ref.Val ) bool {
340
+ if _ , found := m .mutableValues [k ]; found {
341
+ return false
342
+ }
343
+ m .mutableValues [k ] = v
344
+ return true
345
+ }
346
+
347
+ // ToImmutableMap implements the traits.MutableMapper interface method, converting a mutable map
348
+ // an immutable map implementation.
349
+ func (m * mutableMap ) ToImmutableMap () traits.Mapper {
350
+ return NewRefValMap (m .Adapter , m .mutableValues )
351
+ }
352
+
310
353
func newJSONStructAccessor (adapter Adapter , st map [string ]* structpb.Value ) mapAccessor {
311
354
return & jsonStructAccessor {
312
355
Adapter : adapter ,
@@ -350,6 +393,15 @@ func (a *jsonStructAccessor) Iterator() traits.Iterator {
350
393
}
351
394
}
352
395
396
+ // Fold calls the FoldEntry method for each (key, value) pair in the map.
397
+ func (a * jsonStructAccessor ) Fold (f traits.Folder ) {
398
+ for k , v := range a .st {
399
+ if ! f .FoldEntry (k , v ) {
400
+ break
401
+ }
402
+ }
403
+ }
404
+
353
405
func newReflectMapAccessor (adapter Adapter , value reflect.Value ) mapAccessor {
354
406
keyType := value .Type ().Key ()
355
407
return & reflectMapAccessor {
@@ -424,6 +476,16 @@ func (m *reflectMapAccessor) Iterator() traits.Iterator {
424
476
}
425
477
}
426
478
479
+ // Fold calls the FoldEntry method for each (key, value) pair in the map.
480
+ func (m * reflectMapAccessor ) Fold (f traits.Folder ) {
481
+ mapRange := m .refValue .MapRange ()
482
+ for mapRange .Next () {
483
+ if ! f .FoldEntry (mapRange .Key ().Interface (), mapRange .Value ().Interface ()) {
484
+ break
485
+ }
486
+ }
487
+ }
488
+
427
489
func newRefValMapAccessor (mapVal map [ref.Val ]ref.Val ) mapAccessor {
428
490
return & refValMapAccessor {mapVal : mapVal }
429
491
}
@@ -477,6 +539,15 @@ func (a *refValMapAccessor) Iterator() traits.Iterator {
477
539
}
478
540
}
479
541
542
+ // Fold calls the FoldEntry method for each (key, value) pair in the map.
543
+ func (a * refValMapAccessor ) Fold (f traits.Folder ) {
544
+ for k , v := range a .mapVal {
545
+ if ! f .FoldEntry (k , v ) {
546
+ break
547
+ }
548
+ }
549
+ }
550
+
480
551
func newStringMapAccessor (strMap map [string ]string ) mapAccessor {
481
552
return & stringMapAccessor {mapVal : strMap }
482
553
}
@@ -515,6 +586,15 @@ func (a *stringMapAccessor) Iterator() traits.Iterator {
515
586
}
516
587
}
517
588
589
+ // Fold calls the FoldEntry method for each (key, value) pair in the map.
590
+ func (a * stringMapAccessor ) Fold (f traits.Folder ) {
591
+ for k , v := range a .mapVal {
592
+ if ! f .FoldEntry (k , v ) {
593
+ break
594
+ }
595
+ }
596
+ }
597
+
518
598
func newStringIfaceMapAccessor (adapter Adapter , mapVal map [string ]any ) mapAccessor {
519
599
return & stringIfaceMapAccessor {
520
600
Adapter : adapter ,
@@ -557,6 +637,15 @@ func (a *stringIfaceMapAccessor) Iterator() traits.Iterator {
557
637
}
558
638
}
559
639
640
+ // Fold calls the FoldEntry method for each (key, value) pair in the map.
641
+ func (a * stringIfaceMapAccessor ) Fold (f traits.Folder ) {
642
+ for k , v := range a .mapVal {
643
+ if ! f .FoldEntry (k , v ) {
644
+ break
645
+ }
646
+ }
647
+ }
648
+
560
649
// protoMap is a specialized, separate implementation of the traits.Mapper interfaces tailored to
561
650
// accessing protoreflect.Map values.
562
651
type protoMap struct {
@@ -769,6 +858,13 @@ func (m *protoMap) Iterator() traits.Iterator {
769
858
}
770
859
}
771
860
861
+ // Fold calls the FoldEntry method for each (key, value) pair in the map.
862
+ func (m * protoMap ) Fold (f traits.Folder ) {
863
+ m .value .Range (func (k protoreflect.MapKey , v protoreflect.Value ) bool {
864
+ return f .FoldEntry (k .Interface (), v .Interface ())
865
+ })
866
+ }
867
+
772
868
// Size returns the number of entries in the protoreflect.Map.
773
869
func (m * protoMap ) Size () ref.Val {
774
870
return Int (m .value .Len ())
0 commit comments