xref: /aosp_15_r20/external/golang-protobuf/internal/impl/codec_map.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage impl
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"reflect"
9*1c12ee1eSDan Willemsen	"sort"
10*1c12ee1eSDan Willemsen
11*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/protowire"
12*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/genid"
13*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
14*1c12ee1eSDan Willemsen)
15*1c12ee1eSDan Willemsen
16*1c12ee1eSDan Willemsentype mapInfo struct {
17*1c12ee1eSDan Willemsen	goType     reflect.Type
18*1c12ee1eSDan Willemsen	keyWiretag uint64
19*1c12ee1eSDan Willemsen	valWiretag uint64
20*1c12ee1eSDan Willemsen	keyFuncs   valueCoderFuncs
21*1c12ee1eSDan Willemsen	valFuncs   valueCoderFuncs
22*1c12ee1eSDan Willemsen	keyZero    protoreflect.Value
23*1c12ee1eSDan Willemsen	keyKind    protoreflect.Kind
24*1c12ee1eSDan Willemsen	conv       *mapConverter
25*1c12ee1eSDan Willemsen}
26*1c12ee1eSDan Willemsen
27*1c12ee1eSDan Willemsenfunc encoderFuncsForMap(fd protoreflect.FieldDescriptor, ft reflect.Type) (valueMessage *MessageInfo, funcs pointerCoderFuncs) {
28*1c12ee1eSDan Willemsen	// TODO: Consider generating specialized map coders.
29*1c12ee1eSDan Willemsen	keyField := fd.MapKey()
30*1c12ee1eSDan Willemsen	valField := fd.MapValue()
31*1c12ee1eSDan Willemsen	keyWiretag := protowire.EncodeTag(1, wireTypes[keyField.Kind()])
32*1c12ee1eSDan Willemsen	valWiretag := protowire.EncodeTag(2, wireTypes[valField.Kind()])
33*1c12ee1eSDan Willemsen	keyFuncs := encoderFuncsForValue(keyField)
34*1c12ee1eSDan Willemsen	valFuncs := encoderFuncsForValue(valField)
35*1c12ee1eSDan Willemsen	conv := newMapConverter(ft, fd)
36*1c12ee1eSDan Willemsen
37*1c12ee1eSDan Willemsen	mapi := &mapInfo{
38*1c12ee1eSDan Willemsen		goType:     ft,
39*1c12ee1eSDan Willemsen		keyWiretag: keyWiretag,
40*1c12ee1eSDan Willemsen		valWiretag: valWiretag,
41*1c12ee1eSDan Willemsen		keyFuncs:   keyFuncs,
42*1c12ee1eSDan Willemsen		valFuncs:   valFuncs,
43*1c12ee1eSDan Willemsen		keyZero:    keyField.Default(),
44*1c12ee1eSDan Willemsen		keyKind:    keyField.Kind(),
45*1c12ee1eSDan Willemsen		conv:       conv,
46*1c12ee1eSDan Willemsen	}
47*1c12ee1eSDan Willemsen	if valField.Kind() == protoreflect.MessageKind {
48*1c12ee1eSDan Willemsen		valueMessage = getMessageInfo(ft.Elem())
49*1c12ee1eSDan Willemsen	}
50*1c12ee1eSDan Willemsen
51*1c12ee1eSDan Willemsen	funcs = pointerCoderFuncs{
52*1c12ee1eSDan Willemsen		size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
53*1c12ee1eSDan Willemsen			return sizeMap(p.AsValueOf(ft).Elem(), mapi, f, opts)
54*1c12ee1eSDan Willemsen		},
55*1c12ee1eSDan Willemsen		marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
56*1c12ee1eSDan Willemsen			return appendMap(b, p.AsValueOf(ft).Elem(), mapi, f, opts)
57*1c12ee1eSDan Willemsen		},
58*1c12ee1eSDan Willemsen		unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
59*1c12ee1eSDan Willemsen			mp := p.AsValueOf(ft)
60*1c12ee1eSDan Willemsen			if mp.Elem().IsNil() {
61*1c12ee1eSDan Willemsen				mp.Elem().Set(reflect.MakeMap(mapi.goType))
62*1c12ee1eSDan Willemsen			}
63*1c12ee1eSDan Willemsen			if f.mi == nil {
64*1c12ee1eSDan Willemsen				return consumeMap(b, mp.Elem(), wtyp, mapi, f, opts)
65*1c12ee1eSDan Willemsen			} else {
66*1c12ee1eSDan Willemsen				return consumeMapOfMessage(b, mp.Elem(), wtyp, mapi, f, opts)
67*1c12ee1eSDan Willemsen			}
68*1c12ee1eSDan Willemsen		},
69*1c12ee1eSDan Willemsen	}
70*1c12ee1eSDan Willemsen	switch valField.Kind() {
71*1c12ee1eSDan Willemsen	case protoreflect.MessageKind:
72*1c12ee1eSDan Willemsen		funcs.merge = mergeMapOfMessage
73*1c12ee1eSDan Willemsen	case protoreflect.BytesKind:
74*1c12ee1eSDan Willemsen		funcs.merge = mergeMapOfBytes
75*1c12ee1eSDan Willemsen	default:
76*1c12ee1eSDan Willemsen		funcs.merge = mergeMap
77*1c12ee1eSDan Willemsen	}
78*1c12ee1eSDan Willemsen	if valFuncs.isInit != nil {
79*1c12ee1eSDan Willemsen		funcs.isInit = func(p pointer, f *coderFieldInfo) error {
80*1c12ee1eSDan Willemsen			return isInitMap(p.AsValueOf(ft).Elem(), mapi, f)
81*1c12ee1eSDan Willemsen		}
82*1c12ee1eSDan Willemsen	}
83*1c12ee1eSDan Willemsen	return valueMessage, funcs
84*1c12ee1eSDan Willemsen}
85*1c12ee1eSDan Willemsen
86*1c12ee1eSDan Willemsenconst (
87*1c12ee1eSDan Willemsen	mapKeyTagSize = 1 // field 1, tag size 1.
88*1c12ee1eSDan Willemsen	mapValTagSize = 1 // field 2, tag size 2.
89*1c12ee1eSDan Willemsen)
90*1c12ee1eSDan Willemsen
91*1c12ee1eSDan Willemsenfunc sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) int {
92*1c12ee1eSDan Willemsen	if mapv.Len() == 0 {
93*1c12ee1eSDan Willemsen		return 0
94*1c12ee1eSDan Willemsen	}
95*1c12ee1eSDan Willemsen	n := 0
96*1c12ee1eSDan Willemsen	iter := mapRange(mapv)
97*1c12ee1eSDan Willemsen	for iter.Next() {
98*1c12ee1eSDan Willemsen		key := mapi.conv.keyConv.PBValueOf(iter.Key()).MapKey()
99*1c12ee1eSDan Willemsen		keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
100*1c12ee1eSDan Willemsen		var valSize int
101*1c12ee1eSDan Willemsen		value := mapi.conv.valConv.PBValueOf(iter.Value())
102*1c12ee1eSDan Willemsen		if f.mi == nil {
103*1c12ee1eSDan Willemsen			valSize = mapi.valFuncs.size(value, mapValTagSize, opts)
104*1c12ee1eSDan Willemsen		} else {
105*1c12ee1eSDan Willemsen			p := pointerOfValue(iter.Value())
106*1c12ee1eSDan Willemsen			valSize += mapValTagSize
107*1c12ee1eSDan Willemsen			valSize += protowire.SizeBytes(f.mi.sizePointer(p, opts))
108*1c12ee1eSDan Willemsen		}
109*1c12ee1eSDan Willemsen		n += f.tagsize + protowire.SizeBytes(keySize+valSize)
110*1c12ee1eSDan Willemsen	}
111*1c12ee1eSDan Willemsen	return n
112*1c12ee1eSDan Willemsen}
113*1c12ee1eSDan Willemsen
114*1c12ee1eSDan Willemsenfunc consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
115*1c12ee1eSDan Willemsen	if wtyp != protowire.BytesType {
116*1c12ee1eSDan Willemsen		return out, errUnknown
117*1c12ee1eSDan Willemsen	}
118*1c12ee1eSDan Willemsen	b, n := protowire.ConsumeBytes(b)
119*1c12ee1eSDan Willemsen	if n < 0 {
120*1c12ee1eSDan Willemsen		return out, errDecode
121*1c12ee1eSDan Willemsen	}
122*1c12ee1eSDan Willemsen	var (
123*1c12ee1eSDan Willemsen		key = mapi.keyZero
124*1c12ee1eSDan Willemsen		val = mapi.conv.valConv.New()
125*1c12ee1eSDan Willemsen	)
126*1c12ee1eSDan Willemsen	for len(b) > 0 {
127*1c12ee1eSDan Willemsen		num, wtyp, n := protowire.ConsumeTag(b)
128*1c12ee1eSDan Willemsen		if n < 0 {
129*1c12ee1eSDan Willemsen			return out, errDecode
130*1c12ee1eSDan Willemsen		}
131*1c12ee1eSDan Willemsen		if num > protowire.MaxValidNumber {
132*1c12ee1eSDan Willemsen			return out, errDecode
133*1c12ee1eSDan Willemsen		}
134*1c12ee1eSDan Willemsen		b = b[n:]
135*1c12ee1eSDan Willemsen		err := errUnknown
136*1c12ee1eSDan Willemsen		switch num {
137*1c12ee1eSDan Willemsen		case genid.MapEntry_Key_field_number:
138*1c12ee1eSDan Willemsen			var v protoreflect.Value
139*1c12ee1eSDan Willemsen			var o unmarshalOutput
140*1c12ee1eSDan Willemsen			v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
141*1c12ee1eSDan Willemsen			if err != nil {
142*1c12ee1eSDan Willemsen				break
143*1c12ee1eSDan Willemsen			}
144*1c12ee1eSDan Willemsen			key = v
145*1c12ee1eSDan Willemsen			n = o.n
146*1c12ee1eSDan Willemsen		case genid.MapEntry_Value_field_number:
147*1c12ee1eSDan Willemsen			var v protoreflect.Value
148*1c12ee1eSDan Willemsen			var o unmarshalOutput
149*1c12ee1eSDan Willemsen			v, o, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts)
150*1c12ee1eSDan Willemsen			if err != nil {
151*1c12ee1eSDan Willemsen				break
152*1c12ee1eSDan Willemsen			}
153*1c12ee1eSDan Willemsen			val = v
154*1c12ee1eSDan Willemsen			n = o.n
155*1c12ee1eSDan Willemsen		}
156*1c12ee1eSDan Willemsen		if err == errUnknown {
157*1c12ee1eSDan Willemsen			n = protowire.ConsumeFieldValue(num, wtyp, b)
158*1c12ee1eSDan Willemsen			if n < 0 {
159*1c12ee1eSDan Willemsen				return out, errDecode
160*1c12ee1eSDan Willemsen			}
161*1c12ee1eSDan Willemsen		} else if err != nil {
162*1c12ee1eSDan Willemsen			return out, err
163*1c12ee1eSDan Willemsen		}
164*1c12ee1eSDan Willemsen		b = b[n:]
165*1c12ee1eSDan Willemsen	}
166*1c12ee1eSDan Willemsen	mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), mapi.conv.valConv.GoValueOf(val))
167*1c12ee1eSDan Willemsen	out.n = n
168*1c12ee1eSDan Willemsen	return out, nil
169*1c12ee1eSDan Willemsen}
170*1c12ee1eSDan Willemsen
171*1c12ee1eSDan Willemsenfunc consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
172*1c12ee1eSDan Willemsen	if wtyp != protowire.BytesType {
173*1c12ee1eSDan Willemsen		return out, errUnknown
174*1c12ee1eSDan Willemsen	}
175*1c12ee1eSDan Willemsen	b, n := protowire.ConsumeBytes(b)
176*1c12ee1eSDan Willemsen	if n < 0 {
177*1c12ee1eSDan Willemsen		return out, errDecode
178*1c12ee1eSDan Willemsen	}
179*1c12ee1eSDan Willemsen	var (
180*1c12ee1eSDan Willemsen		key = mapi.keyZero
181*1c12ee1eSDan Willemsen		val = reflect.New(f.mi.GoReflectType.Elem())
182*1c12ee1eSDan Willemsen	)
183*1c12ee1eSDan Willemsen	for len(b) > 0 {
184*1c12ee1eSDan Willemsen		num, wtyp, n := protowire.ConsumeTag(b)
185*1c12ee1eSDan Willemsen		if n < 0 {
186*1c12ee1eSDan Willemsen			return out, errDecode
187*1c12ee1eSDan Willemsen		}
188*1c12ee1eSDan Willemsen		if num > protowire.MaxValidNumber {
189*1c12ee1eSDan Willemsen			return out, errDecode
190*1c12ee1eSDan Willemsen		}
191*1c12ee1eSDan Willemsen		b = b[n:]
192*1c12ee1eSDan Willemsen		err := errUnknown
193*1c12ee1eSDan Willemsen		switch num {
194*1c12ee1eSDan Willemsen		case 1:
195*1c12ee1eSDan Willemsen			var v protoreflect.Value
196*1c12ee1eSDan Willemsen			var o unmarshalOutput
197*1c12ee1eSDan Willemsen			v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
198*1c12ee1eSDan Willemsen			if err != nil {
199*1c12ee1eSDan Willemsen				break
200*1c12ee1eSDan Willemsen			}
201*1c12ee1eSDan Willemsen			key = v
202*1c12ee1eSDan Willemsen			n = o.n
203*1c12ee1eSDan Willemsen		case 2:
204*1c12ee1eSDan Willemsen			if wtyp != protowire.BytesType {
205*1c12ee1eSDan Willemsen				break
206*1c12ee1eSDan Willemsen			}
207*1c12ee1eSDan Willemsen			var v []byte
208*1c12ee1eSDan Willemsen			v, n = protowire.ConsumeBytes(b)
209*1c12ee1eSDan Willemsen			if n < 0 {
210*1c12ee1eSDan Willemsen				return out, errDecode
211*1c12ee1eSDan Willemsen			}
212*1c12ee1eSDan Willemsen			var o unmarshalOutput
213*1c12ee1eSDan Willemsen			o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts)
214*1c12ee1eSDan Willemsen			if o.initialized {
215*1c12ee1eSDan Willemsen				// Consider this map item initialized so long as we see
216*1c12ee1eSDan Willemsen				// an initialized value.
217*1c12ee1eSDan Willemsen				out.initialized = true
218*1c12ee1eSDan Willemsen			}
219*1c12ee1eSDan Willemsen		}
220*1c12ee1eSDan Willemsen		if err == errUnknown {
221*1c12ee1eSDan Willemsen			n = protowire.ConsumeFieldValue(num, wtyp, b)
222*1c12ee1eSDan Willemsen			if n < 0 {
223*1c12ee1eSDan Willemsen				return out, errDecode
224*1c12ee1eSDan Willemsen			}
225*1c12ee1eSDan Willemsen		} else if err != nil {
226*1c12ee1eSDan Willemsen			return out, err
227*1c12ee1eSDan Willemsen		}
228*1c12ee1eSDan Willemsen		b = b[n:]
229*1c12ee1eSDan Willemsen	}
230*1c12ee1eSDan Willemsen	mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), val)
231*1c12ee1eSDan Willemsen	out.n = n
232*1c12ee1eSDan Willemsen	return out, nil
233*1c12ee1eSDan Willemsen}
234*1c12ee1eSDan Willemsen
235*1c12ee1eSDan Willemsenfunc appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
236*1c12ee1eSDan Willemsen	if f.mi == nil {
237*1c12ee1eSDan Willemsen		key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
238*1c12ee1eSDan Willemsen		val := mapi.conv.valConv.PBValueOf(valrv)
239*1c12ee1eSDan Willemsen		size := 0
240*1c12ee1eSDan Willemsen		size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
241*1c12ee1eSDan Willemsen		size += mapi.valFuncs.size(val, mapValTagSize, opts)
242*1c12ee1eSDan Willemsen		b = protowire.AppendVarint(b, uint64(size))
243*1c12ee1eSDan Willemsen		b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
244*1c12ee1eSDan Willemsen		if err != nil {
245*1c12ee1eSDan Willemsen			return nil, err
246*1c12ee1eSDan Willemsen		}
247*1c12ee1eSDan Willemsen		return mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts)
248*1c12ee1eSDan Willemsen	} else {
249*1c12ee1eSDan Willemsen		key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
250*1c12ee1eSDan Willemsen		val := pointerOfValue(valrv)
251*1c12ee1eSDan Willemsen		valSize := f.mi.sizePointer(val, opts)
252*1c12ee1eSDan Willemsen		size := 0
253*1c12ee1eSDan Willemsen		size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
254*1c12ee1eSDan Willemsen		size += mapValTagSize + protowire.SizeBytes(valSize)
255*1c12ee1eSDan Willemsen		b = protowire.AppendVarint(b, uint64(size))
256*1c12ee1eSDan Willemsen		b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
257*1c12ee1eSDan Willemsen		if err != nil {
258*1c12ee1eSDan Willemsen			return nil, err
259*1c12ee1eSDan Willemsen		}
260*1c12ee1eSDan Willemsen		b = protowire.AppendVarint(b, mapi.valWiretag)
261*1c12ee1eSDan Willemsen		b = protowire.AppendVarint(b, uint64(valSize))
262*1c12ee1eSDan Willemsen		return f.mi.marshalAppendPointer(b, val, opts)
263*1c12ee1eSDan Willemsen	}
264*1c12ee1eSDan Willemsen}
265*1c12ee1eSDan Willemsen
266*1c12ee1eSDan Willemsenfunc appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
267*1c12ee1eSDan Willemsen	if mapv.Len() == 0 {
268*1c12ee1eSDan Willemsen		return b, nil
269*1c12ee1eSDan Willemsen	}
270*1c12ee1eSDan Willemsen	if opts.Deterministic() {
271*1c12ee1eSDan Willemsen		return appendMapDeterministic(b, mapv, mapi, f, opts)
272*1c12ee1eSDan Willemsen	}
273*1c12ee1eSDan Willemsen	iter := mapRange(mapv)
274*1c12ee1eSDan Willemsen	for iter.Next() {
275*1c12ee1eSDan Willemsen		var err error
276*1c12ee1eSDan Willemsen		b = protowire.AppendVarint(b, f.wiretag)
277*1c12ee1eSDan Willemsen		b, err = appendMapItem(b, iter.Key(), iter.Value(), mapi, f, opts)
278*1c12ee1eSDan Willemsen		if err != nil {
279*1c12ee1eSDan Willemsen			return b, err
280*1c12ee1eSDan Willemsen		}
281*1c12ee1eSDan Willemsen	}
282*1c12ee1eSDan Willemsen	return b, nil
283*1c12ee1eSDan Willemsen}
284*1c12ee1eSDan Willemsen
285*1c12ee1eSDan Willemsenfunc appendMapDeterministic(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
286*1c12ee1eSDan Willemsen	keys := mapv.MapKeys()
287*1c12ee1eSDan Willemsen	sort.Slice(keys, func(i, j int) bool {
288*1c12ee1eSDan Willemsen		switch keys[i].Kind() {
289*1c12ee1eSDan Willemsen		case reflect.Bool:
290*1c12ee1eSDan Willemsen			return !keys[i].Bool() && keys[j].Bool()
291*1c12ee1eSDan Willemsen		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
292*1c12ee1eSDan Willemsen			return keys[i].Int() < keys[j].Int()
293*1c12ee1eSDan Willemsen		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
294*1c12ee1eSDan Willemsen			return keys[i].Uint() < keys[j].Uint()
295*1c12ee1eSDan Willemsen		case reflect.Float32, reflect.Float64:
296*1c12ee1eSDan Willemsen			return keys[i].Float() < keys[j].Float()
297*1c12ee1eSDan Willemsen		case reflect.String:
298*1c12ee1eSDan Willemsen			return keys[i].String() < keys[j].String()
299*1c12ee1eSDan Willemsen		default:
300*1c12ee1eSDan Willemsen			panic("invalid kind: " + keys[i].Kind().String())
301*1c12ee1eSDan Willemsen		}
302*1c12ee1eSDan Willemsen	})
303*1c12ee1eSDan Willemsen	for _, key := range keys {
304*1c12ee1eSDan Willemsen		var err error
305*1c12ee1eSDan Willemsen		b = protowire.AppendVarint(b, f.wiretag)
306*1c12ee1eSDan Willemsen		b, err = appendMapItem(b, key, mapv.MapIndex(key), mapi, f, opts)
307*1c12ee1eSDan Willemsen		if err != nil {
308*1c12ee1eSDan Willemsen			return b, err
309*1c12ee1eSDan Willemsen		}
310*1c12ee1eSDan Willemsen	}
311*1c12ee1eSDan Willemsen	return b, nil
312*1c12ee1eSDan Willemsen}
313*1c12ee1eSDan Willemsen
314*1c12ee1eSDan Willemsenfunc isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error {
315*1c12ee1eSDan Willemsen	if mi := f.mi; mi != nil {
316*1c12ee1eSDan Willemsen		mi.init()
317*1c12ee1eSDan Willemsen		if !mi.needsInitCheck {
318*1c12ee1eSDan Willemsen			return nil
319*1c12ee1eSDan Willemsen		}
320*1c12ee1eSDan Willemsen		iter := mapRange(mapv)
321*1c12ee1eSDan Willemsen		for iter.Next() {
322*1c12ee1eSDan Willemsen			val := pointerOfValue(iter.Value())
323*1c12ee1eSDan Willemsen			if err := mi.checkInitializedPointer(val); err != nil {
324*1c12ee1eSDan Willemsen				return err
325*1c12ee1eSDan Willemsen			}
326*1c12ee1eSDan Willemsen		}
327*1c12ee1eSDan Willemsen	} else {
328*1c12ee1eSDan Willemsen		iter := mapRange(mapv)
329*1c12ee1eSDan Willemsen		for iter.Next() {
330*1c12ee1eSDan Willemsen			val := mapi.conv.valConv.PBValueOf(iter.Value())
331*1c12ee1eSDan Willemsen			if err := mapi.valFuncs.isInit(val); err != nil {
332*1c12ee1eSDan Willemsen				return err
333*1c12ee1eSDan Willemsen			}
334*1c12ee1eSDan Willemsen		}
335*1c12ee1eSDan Willemsen	}
336*1c12ee1eSDan Willemsen	return nil
337*1c12ee1eSDan Willemsen}
338*1c12ee1eSDan Willemsen
339*1c12ee1eSDan Willemsenfunc mergeMap(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
340*1c12ee1eSDan Willemsen	dstm := dst.AsValueOf(f.ft).Elem()
341*1c12ee1eSDan Willemsen	srcm := src.AsValueOf(f.ft).Elem()
342*1c12ee1eSDan Willemsen	if srcm.Len() == 0 {
343*1c12ee1eSDan Willemsen		return
344*1c12ee1eSDan Willemsen	}
345*1c12ee1eSDan Willemsen	if dstm.IsNil() {
346*1c12ee1eSDan Willemsen		dstm.Set(reflect.MakeMap(f.ft))
347*1c12ee1eSDan Willemsen	}
348*1c12ee1eSDan Willemsen	iter := mapRange(srcm)
349*1c12ee1eSDan Willemsen	for iter.Next() {
350*1c12ee1eSDan Willemsen		dstm.SetMapIndex(iter.Key(), iter.Value())
351*1c12ee1eSDan Willemsen	}
352*1c12ee1eSDan Willemsen}
353*1c12ee1eSDan Willemsen
354*1c12ee1eSDan Willemsenfunc mergeMapOfBytes(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
355*1c12ee1eSDan Willemsen	dstm := dst.AsValueOf(f.ft).Elem()
356*1c12ee1eSDan Willemsen	srcm := src.AsValueOf(f.ft).Elem()
357*1c12ee1eSDan Willemsen	if srcm.Len() == 0 {
358*1c12ee1eSDan Willemsen		return
359*1c12ee1eSDan Willemsen	}
360*1c12ee1eSDan Willemsen	if dstm.IsNil() {
361*1c12ee1eSDan Willemsen		dstm.Set(reflect.MakeMap(f.ft))
362*1c12ee1eSDan Willemsen	}
363*1c12ee1eSDan Willemsen	iter := mapRange(srcm)
364*1c12ee1eSDan Willemsen	for iter.Next() {
365*1c12ee1eSDan Willemsen		dstm.SetMapIndex(iter.Key(), reflect.ValueOf(append(emptyBuf[:], iter.Value().Bytes()...)))
366*1c12ee1eSDan Willemsen	}
367*1c12ee1eSDan Willemsen}
368*1c12ee1eSDan Willemsen
369*1c12ee1eSDan Willemsenfunc mergeMapOfMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
370*1c12ee1eSDan Willemsen	dstm := dst.AsValueOf(f.ft).Elem()
371*1c12ee1eSDan Willemsen	srcm := src.AsValueOf(f.ft).Elem()
372*1c12ee1eSDan Willemsen	if srcm.Len() == 0 {
373*1c12ee1eSDan Willemsen		return
374*1c12ee1eSDan Willemsen	}
375*1c12ee1eSDan Willemsen	if dstm.IsNil() {
376*1c12ee1eSDan Willemsen		dstm.Set(reflect.MakeMap(f.ft))
377*1c12ee1eSDan Willemsen	}
378*1c12ee1eSDan Willemsen	iter := mapRange(srcm)
379*1c12ee1eSDan Willemsen	for iter.Next() {
380*1c12ee1eSDan Willemsen		val := reflect.New(f.ft.Elem().Elem())
381*1c12ee1eSDan Willemsen		if f.mi != nil {
382*1c12ee1eSDan Willemsen			f.mi.mergePointer(pointerOfValue(val), pointerOfValue(iter.Value()), opts)
383*1c12ee1eSDan Willemsen		} else {
384*1c12ee1eSDan Willemsen			opts.Merge(asMessage(val), asMessage(iter.Value()))
385*1c12ee1eSDan Willemsen		}
386*1c12ee1eSDan Willemsen		dstm.SetMapIndex(iter.Key(), val)
387*1c12ee1eSDan Willemsen	}
388*1c12ee1eSDan Willemsen}
389