blob: 44885a761f6c683e4f5f895aad89761005ab8ddb [file] [log] [blame]
Damien Neilc37adef2019-04-01 13:49:56 -07001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package impl
6
7import (
Damien Neilf2427c02019-12-20 09:43:20 -08008 "errors"
Damien Neilc37adef2019-04-01 13:49:56 -07009 "reflect"
Damien Neil3e42b662019-12-17 11:39:17 -080010 "sort"
Damien Neilc37adef2019-04-01 13:49:56 -070011
Joe Tsaicd108d02020-02-14 18:08:02 -080012 "google.golang.org/protobuf/encoding/protowire"
Joe Tsaie0b77db2020-05-26 11:21:59 -070013 "google.golang.org/protobuf/internal/genid"
Damien Neilc37adef2019-04-01 13:49:56 -070014 pref "google.golang.org/protobuf/reflect/protoreflect"
15)
16
Damien Neile91877d2019-06-27 10:54:42 -070017type mapInfo struct {
Damien Neil316febd2020-02-09 12:26:50 -080018 goType reflect.Type
19 keyWiretag uint64
20 valWiretag uint64
21 keyFuncs valueCoderFuncs
22 valFuncs valueCoderFuncs
23 keyZero pref.Value
24 keyKind pref.Kind
25 conv *mapConverter
Damien Neile91877d2019-06-27 10:54:42 -070026}
27
Damien Neil316febd2020-02-09 12:26:50 -080028func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (valueMessage *MessageInfo, funcs pointerCoderFuncs) {
Damien Neilc37adef2019-04-01 13:49:56 -070029 // TODO: Consider generating specialized map coders.
30 keyField := fd.MapKey()
31 valField := fd.MapValue()
Joe Tsaicd108d02020-02-14 18:08:02 -080032 keyWiretag := protowire.EncodeTag(1, wireTypes[keyField.Kind()])
33 valWiretag := protowire.EncodeTag(2, wireTypes[valField.Kind()])
Damien Neil4b3a82f2019-09-04 19:07:00 -070034 keyFuncs := encoderFuncsForValue(keyField)
35 valFuncs := encoderFuncsForValue(valField)
Damien Neil3e42b662019-12-17 11:39:17 -080036 conv := newMapConverter(ft, fd)
Damien Neilc37adef2019-04-01 13:49:56 -070037
Damien Neile91877d2019-06-27 10:54:42 -070038 mapi := &mapInfo{
39 goType: ft,
40 keyWiretag: keyWiretag,
41 valWiretag: valWiretag,
42 keyFuncs: keyFuncs,
43 valFuncs: valFuncs,
Damien Neil68b81c32019-08-22 11:41:32 -070044 keyZero: keyField.Default(),
45 keyKind: keyField.Kind(),
Damien Neil3e42b662019-12-17 11:39:17 -080046 conv: conv,
47 }
48 if valField.Kind() == pref.MessageKind {
Damien Neil316febd2020-02-09 12:26:50 -080049 valueMessage = getMessageInfo(ft.Elem())
Damien Neile91877d2019-06-27 10:54:42 -070050 }
51
Damien Neil5322bdb2019-04-09 15:57:05 -070052 funcs = pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -080053 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
54 return sizeMap(p.AsValueOf(ft).Elem(), mapi, f, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070055 },
Damien Neil316febd2020-02-09 12:26:50 -080056 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
57 return appendMap(b, p.AsValueOf(ft).Elem(), mapi, f, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070058 },
Joe Tsaicd108d02020-02-14 18:08:02 -080059 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neil68b81c32019-08-22 11:41:32 -070060 mp := p.AsValueOf(ft)
61 if mp.Elem().IsNil() {
62 mp.Elem().Set(reflect.MakeMap(mapi.goType))
63 }
Damien Neil316febd2020-02-09 12:26:50 -080064 if f.mi == nil {
65 return consumeMap(b, mp.Elem(), wtyp, mapi, f, opts)
Damien Neil3e42b662019-12-17 11:39:17 -080066 } else {
Damien Neil316febd2020-02-09 12:26:50 -080067 return consumeMapOfMessage(b, mp.Elem(), wtyp, mapi, f, opts)
Damien Neil3e42b662019-12-17 11:39:17 -080068 }
Damien Neile91877d2019-06-27 10:54:42 -070069 },
Damien Neilc37adef2019-04-01 13:49:56 -070070 }
Damien Neile8e88752020-02-11 11:25:16 -080071 switch valField.Kind() {
72 case pref.MessageKind:
73 funcs.merge = mergeMapOfMessage
74 case pref.BytesKind:
75 funcs.merge = mergeMapOfBytes
76 default:
77 funcs.merge = mergeMap
78 }
Damien Neil5322bdb2019-04-09 15:57:05 -070079 if valFuncs.isInit != nil {
Damien Neil316febd2020-02-09 12:26:50 -080080 funcs.isInit = func(p pointer, f *coderFieldInfo) error {
81 return isInitMap(p.AsValueOf(ft).Elem(), mapi, f)
Damien Neil5322bdb2019-04-09 15:57:05 -070082 }
83 }
Damien Neil316febd2020-02-09 12:26:50 -080084 return valueMessage, funcs
Damien Neilc37adef2019-04-01 13:49:56 -070085}
86
87const (
88 mapKeyTagSize = 1 // field 1, tag size 1.
89 mapValTagSize = 1 // field 2, tag size 2.
90)
91
Damien Neil316febd2020-02-09 12:26:50 -080092func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) int {
Damien Neil68b81c32019-08-22 11:41:32 -070093 if mapv.Len() == 0 {
94 return 0
Damien Neile91877d2019-06-27 10:54:42 -070095 }
Damien Neil68b81c32019-08-22 11:41:32 -070096 n := 0
Damien Neil3e42b662019-12-17 11:39:17 -080097 iter := mapRange(mapv)
98 for iter.Next() {
99 key := mapi.conv.keyConv.PBValueOf(iter.Key()).MapKey()
100 keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
101 var valSize int
102 value := mapi.conv.valConv.PBValueOf(iter.Value())
Damien Neil316febd2020-02-09 12:26:50 -0800103 if f.mi == nil {
Damien Neil3e42b662019-12-17 11:39:17 -0800104 valSize = mapi.valFuncs.size(value, mapValTagSize, opts)
105 } else {
106 p := pointerOfValue(iter.Value())
107 valSize += mapValTagSize
Joe Tsaicd108d02020-02-14 18:08:02 -0800108 valSize += protowire.SizeBytes(f.mi.sizePointer(p, opts))
Damien Neil3e42b662019-12-17 11:39:17 -0800109 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800110 n += f.tagsize + protowire.SizeBytes(keySize+valSize)
Damien Neil3e42b662019-12-17 11:39:17 -0800111 }
Damien Neil68b81c32019-08-22 11:41:32 -0700112 return n
113}
Damien Neile91877d2019-06-27 10:54:42 -0700114
Joe Tsaicd108d02020-02-14 18:08:02 -0800115func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
116 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800117 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700118 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800119 b, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700120 if n < 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800121 return out, protowire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700122 }
123 var (
124 key = mapi.keyZero
Damien Neil3e42b662019-12-17 11:39:17 -0800125 val = mapi.conv.valConv.New()
Damien Neile91877d2019-06-27 10:54:42 -0700126 )
Damien Neile91877d2019-06-27 10:54:42 -0700127 for len(b) > 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800128 num, wtyp, n := protowire.ConsumeTag(b)
Damien Neile91877d2019-06-27 10:54:42 -0700129 if n < 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800130 return out, protowire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700131 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800132 if num > protowire.MaxValidNumber {
Damien Neilf0831e82020-01-21 14:25:12 -0800133 return out, errors.New("invalid field number")
Damien Neilf2427c02019-12-20 09:43:20 -0800134 }
Damien Neile91877d2019-06-27 10:54:42 -0700135 b = b[n:]
136 err := errUnknown
137 switch num {
Joe Tsaie0b77db2020-05-26 11:21:59 -0700138 case genid.MapEntry_Key_field_number:
Damien Neil68b81c32019-08-22 11:41:32 -0700139 var v pref.Value
Damien Neilf0831e82020-01-21 14:25:12 -0800140 var o unmarshalOutput
141 v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700142 if err != nil {
143 break
144 }
145 key = v
Damien Neilf0831e82020-01-21 14:25:12 -0800146 n = o.n
Joe Tsaie0b77db2020-05-26 11:21:59 -0700147 case genid.MapEntry_Value_field_number:
Damien Neil68b81c32019-08-22 11:41:32 -0700148 var v pref.Value
Damien Neilf0831e82020-01-21 14:25:12 -0800149 var o unmarshalOutput
150 v, o, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700151 if err != nil {
152 break
153 }
154 val = v
Damien Neilf0831e82020-01-21 14:25:12 -0800155 n = o.n
Damien Neile91877d2019-06-27 10:54:42 -0700156 }
157 if err == errUnknown {
Joe Tsaicd108d02020-02-14 18:08:02 -0800158 n = protowire.ConsumeFieldValue(num, wtyp, b)
Damien Neile91877d2019-06-27 10:54:42 -0700159 if n < 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800160 return out, protowire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700161 }
162 } else if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800163 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700164 }
165 b = b[n:]
166 }
Damien Neil3e42b662019-12-17 11:39:17 -0800167 mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), mapi.conv.valConv.GoValueOf(val))
Damien Neilf0831e82020-01-21 14:25:12 -0800168 out.n = n
169 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700170}
171
Joe Tsaicd108d02020-02-14 18:08:02 -0800172func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
173 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800174 return out, errUnknown
Damien Neil3e42b662019-12-17 11:39:17 -0800175 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800176 b, n := protowire.ConsumeBytes(b)
Damien Neil3e42b662019-12-17 11:39:17 -0800177 if n < 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800178 return out, protowire.ParseError(n)
Damien Neil3e42b662019-12-17 11:39:17 -0800179 }
180 var (
181 key = mapi.keyZero
Damien Neil316febd2020-02-09 12:26:50 -0800182 val = reflect.New(f.mi.GoReflectType.Elem())
Damien Neil3e42b662019-12-17 11:39:17 -0800183 )
184 for len(b) > 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800185 num, wtyp, n := protowire.ConsumeTag(b)
Damien Neil3e42b662019-12-17 11:39:17 -0800186 if n < 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800187 return out, protowire.ParseError(n)
Damien Neil3e42b662019-12-17 11:39:17 -0800188 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800189 if num > protowire.MaxValidNumber {
Damien Neilf0831e82020-01-21 14:25:12 -0800190 return out, errors.New("invalid field number")
Damien Neilf2427c02019-12-20 09:43:20 -0800191 }
Damien Neil3e42b662019-12-17 11:39:17 -0800192 b = b[n:]
193 err := errUnknown
194 switch num {
195 case 1:
196 var v pref.Value
Damien Neilf0831e82020-01-21 14:25:12 -0800197 var o unmarshalOutput
198 v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
Damien Neil3e42b662019-12-17 11:39:17 -0800199 if err != nil {
200 break
201 }
202 key = v
Damien Neilf0831e82020-01-21 14:25:12 -0800203 n = o.n
Damien Neil3e42b662019-12-17 11:39:17 -0800204 case 2:
Joe Tsaicd108d02020-02-14 18:08:02 -0800205 if wtyp != protowire.BytesType {
Damien Neil3e42b662019-12-17 11:39:17 -0800206 break
207 }
Damien Neil7e690b52019-12-18 09:35:01 -0800208 var v []byte
Joe Tsaicd108d02020-02-14 18:08:02 -0800209 v, n = protowire.ConsumeBytes(b)
Damien Neil3e42b662019-12-17 11:39:17 -0800210 if n < 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800211 return out, protowire.ParseError(n)
Damien Neil3e42b662019-12-17 11:39:17 -0800212 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800213 var o unmarshalOutput
Damien Neil316febd2020-02-09 12:26:50 -0800214 o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts)
Damien Neilc600d6c2020-01-21 15:00:33 -0800215 if o.initialized {
216 // Consider this map item initialized so long as we see
217 // an initialized value.
218 out.initialized = true
219 }
Damien Neil3e42b662019-12-17 11:39:17 -0800220 }
221 if err == errUnknown {
Joe Tsaicd108d02020-02-14 18:08:02 -0800222 n = protowire.ConsumeFieldValue(num, wtyp, b)
Damien Neil3e42b662019-12-17 11:39:17 -0800223 if n < 0 {
Joe Tsaicd108d02020-02-14 18:08:02 -0800224 return out, protowire.ParseError(n)
Damien Neil3e42b662019-12-17 11:39:17 -0800225 }
226 } else if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800227 return out, err
Damien Neil3e42b662019-12-17 11:39:17 -0800228 }
229 b = b[n:]
230 }
231 mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), val)
Damien Neilf0831e82020-01-21 14:25:12 -0800232 out.n = n
233 return out, nil
Damien Neil3e42b662019-12-17 11:39:17 -0800234}
235
Damien Neil316febd2020-02-09 12:26:50 -0800236func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
237 if f.mi == nil {
Damien Neil3e42b662019-12-17 11:39:17 -0800238 key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
239 val := mapi.conv.valConv.PBValueOf(valrv)
240 size := 0
241 size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
242 size += mapi.valFuncs.size(val, mapValTagSize, opts)
Joe Tsaicd108d02020-02-14 18:08:02 -0800243 b = protowire.AppendVarint(b, uint64(size))
Damien Neil3e42b662019-12-17 11:39:17 -0800244 b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
245 if err != nil {
246 return nil, err
247 }
248 return mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts)
249 } else {
250 key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
251 val := pointerOfValue(valrv)
Damien Neil316febd2020-02-09 12:26:50 -0800252 valSize := f.mi.sizePointer(val, opts)
Damien Neil3e42b662019-12-17 11:39:17 -0800253 size := 0
254 size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
Joe Tsaicd108d02020-02-14 18:08:02 -0800255 size += mapValTagSize + protowire.SizeBytes(valSize)
256 b = protowire.AppendVarint(b, uint64(size))
Damien Neil3e42b662019-12-17 11:39:17 -0800257 b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
258 if err != nil {
259 return nil, err
260 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800261 b = protowire.AppendVarint(b, mapi.valWiretag)
262 b = protowire.AppendVarint(b, uint64(valSize))
Damien Neil316febd2020-02-09 12:26:50 -0800263 return f.mi.marshalAppendPointer(b, val, opts)
Damien Neil3e42b662019-12-17 11:39:17 -0800264 }
265}
266
Damien Neil316febd2020-02-09 12:26:50 -0800267func appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700268 if mapv.Len() == 0 {
269 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700270 }
Damien Neil68b81c32019-08-22 11:41:32 -0700271 if opts.Deterministic() {
Damien Neil316febd2020-02-09 12:26:50 -0800272 return appendMapDeterministic(b, mapv, mapi, f, opts)
Damien Neil68b81c32019-08-22 11:41:32 -0700273 }
Damien Neil3e42b662019-12-17 11:39:17 -0800274 iter := mapRange(mapv)
275 for iter.Next() {
276 var err error
Joe Tsaicd108d02020-02-14 18:08:02 -0800277 b = protowire.AppendVarint(b, f.wiretag)
Damien Neil316febd2020-02-09 12:26:50 -0800278 b, err = appendMapItem(b, iter.Key(), iter.Value(), mapi, f, opts)
Damien Neil3e42b662019-12-17 11:39:17 -0800279 if err != nil {
280 return b, err
281 }
282 }
283 return b, nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700284}
285
Damien Neil316febd2020-02-09 12:26:50 -0800286func appendMapDeterministic(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil3e42b662019-12-17 11:39:17 -0800287 keys := mapv.MapKeys()
288 sort.Slice(keys, func(i, j int) bool {
289 switch keys[i].Kind() {
290 case reflect.Bool:
291 return !keys[i].Bool() && keys[j].Bool()
292 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
293 return keys[i].Int() < keys[j].Int()
294 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
295 return keys[i].Uint() < keys[j].Uint()
296 case reflect.Float32, reflect.Float64:
297 return keys[i].Float() < keys[j].Float()
298 case reflect.String:
299 return keys[i].String() < keys[j].String()
300 default:
301 panic("invalid kind: " + keys[i].Kind().String())
302 }
Damien Neil68b81c32019-08-22 11:41:32 -0700303 })
Damien Neil3e42b662019-12-17 11:39:17 -0800304 for _, key := range keys {
305 var err error
Joe Tsaicd108d02020-02-14 18:08:02 -0800306 b = protowire.AppendVarint(b, f.wiretag)
Damien Neil316febd2020-02-09 12:26:50 -0800307 b, err = appendMapItem(b, key, mapv.MapIndex(key), mapi, f, opts)
Damien Neil3e42b662019-12-17 11:39:17 -0800308 if err != nil {
309 return b, err
310 }
311 }
312 return b, nil
313}
314
Damien Neil316febd2020-02-09 12:26:50 -0800315func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error {
316 if mi := f.mi; mi != nil {
Damien Neil3e42b662019-12-17 11:39:17 -0800317 mi.init()
318 if !mi.needsInitCheck {
319 return nil
320 }
321 iter := mapRange(mapv)
322 for iter.Next() {
323 val := pointerOfValue(iter.Value())
Joe Tsaif26a9e72020-02-20 10:05:37 -0800324 if err := mi.checkInitializedPointer(val); err != nil {
Damien Neil3e42b662019-12-17 11:39:17 -0800325 return err
326 }
327 }
328 } else {
329 iter := mapRange(mapv)
330 for iter.Next() {
331 val := mapi.conv.valConv.PBValueOf(iter.Value())
332 if err := mapi.valFuncs.isInit(val); err != nil {
333 return err
334 }
335 }
336 }
337 return nil
Damien Neilc37adef2019-04-01 13:49:56 -0700338}
Damien Neile8e88752020-02-11 11:25:16 -0800339
340func mergeMap(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
341 dstm := dst.AsValueOf(f.ft).Elem()
342 srcm := src.AsValueOf(f.ft).Elem()
343 if srcm.Len() == 0 {
344 return
345 }
346 if dstm.IsNil() {
347 dstm.Set(reflect.MakeMap(f.ft))
348 }
349 iter := mapRange(srcm)
350 for iter.Next() {
351 dstm.SetMapIndex(iter.Key(), iter.Value())
352 }
353}
354
355func mergeMapOfBytes(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
356 dstm := dst.AsValueOf(f.ft).Elem()
357 srcm := src.AsValueOf(f.ft).Elem()
358 if srcm.Len() == 0 {
359 return
360 }
361 if dstm.IsNil() {
362 dstm.Set(reflect.MakeMap(f.ft))
363 }
364 iter := mapRange(srcm)
365 for iter.Next() {
366 dstm.SetMapIndex(iter.Key(), reflect.ValueOf(append(emptyBuf[:], iter.Value().Bytes()...)))
367 }
368}
369
370func mergeMapOfMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
371 dstm := dst.AsValueOf(f.ft).Elem()
372 srcm := src.AsValueOf(f.ft).Elem()
373 if srcm.Len() == 0 {
374 return
375 }
376 if dstm.IsNil() {
377 dstm.Set(reflect.MakeMap(f.ft))
378 }
379 iter := mapRange(srcm)
380 for iter.Next() {
381 val := reflect.New(f.ft.Elem().Elem())
382 if f.mi != nil {
383 f.mi.mergePointer(pointerOfValue(val), pointerOfValue(iter.Value()), opts)
384 } else {
385 opts.Merge(asMessage(val), asMessage(iter.Value()))
386 }
387 dstm.SetMapIndex(iter.Key(), val)
388 }
389}