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