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 "fmt" 9*1c12ee1eSDan Willemsen "reflect" 10*1c12ee1eSDan Willemsen "sync" 11*1c12ee1eSDan Willemsen 12*1c12ee1eSDan Willemsen "google.golang.org/protobuf/encoding/protowire" 13*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/errors" 14*1c12ee1eSDan Willemsen "google.golang.org/protobuf/proto" 15*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoreflect" 16*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoregistry" 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/runtime/protoiface" 18*1c12ee1eSDan Willemsen) 19*1c12ee1eSDan Willemsen 20*1c12ee1eSDan Willemsentype errInvalidUTF8 struct{} 21*1c12ee1eSDan Willemsen 22*1c12ee1eSDan Willemsenfunc (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" } 23*1c12ee1eSDan Willemsenfunc (errInvalidUTF8) InvalidUTF8() bool { return true } 24*1c12ee1eSDan Willemsenfunc (errInvalidUTF8) Unwrap() error { return errors.Error } 25*1c12ee1eSDan Willemsen 26*1c12ee1eSDan Willemsen// initOneofFieldCoders initializes the fast-path functions for the fields in a oneof. 27*1c12ee1eSDan Willemsen// 28*1c12ee1eSDan Willemsen// For size, marshal, and isInit operations, functions are set only on the first field 29*1c12ee1eSDan Willemsen// in the oneof. The functions are called when the oneof is non-nil, and will dispatch 30*1c12ee1eSDan Willemsen// to the appropriate field-specific function as necessary. 31*1c12ee1eSDan Willemsen// 32*1c12ee1eSDan Willemsen// The unmarshal function is set on each field individually as usual. 33*1c12ee1eSDan Willemsenfunc (mi *MessageInfo) initOneofFieldCoders(od protoreflect.OneofDescriptor, si structInfo) { 34*1c12ee1eSDan Willemsen fs := si.oneofsByName[od.Name()] 35*1c12ee1eSDan Willemsen ft := fs.Type 36*1c12ee1eSDan Willemsen oneofFields := make(map[reflect.Type]*coderFieldInfo) 37*1c12ee1eSDan Willemsen needIsInit := false 38*1c12ee1eSDan Willemsen fields := od.Fields() 39*1c12ee1eSDan Willemsen for i, lim := 0, fields.Len(); i < lim; i++ { 40*1c12ee1eSDan Willemsen fd := od.Fields().Get(i) 41*1c12ee1eSDan Willemsen num := fd.Number() 42*1c12ee1eSDan Willemsen // Make a copy of the original coderFieldInfo for use in unmarshaling. 43*1c12ee1eSDan Willemsen // 44*1c12ee1eSDan Willemsen // oneofFields[oneofType].funcs.marshal is the field-specific marshal function. 45*1c12ee1eSDan Willemsen // 46*1c12ee1eSDan Willemsen // mi.coderFields[num].marshal is set on only the first field in the oneof, 47*1c12ee1eSDan Willemsen // and dispatches to the field-specific marshaler in oneofFields. 48*1c12ee1eSDan Willemsen cf := *mi.coderFields[num] 49*1c12ee1eSDan Willemsen ot := si.oneofWrappersByNumber[num] 50*1c12ee1eSDan Willemsen cf.ft = ot.Field(0).Type 51*1c12ee1eSDan Willemsen cf.mi, cf.funcs = fieldCoder(fd, cf.ft) 52*1c12ee1eSDan Willemsen oneofFields[ot] = &cf 53*1c12ee1eSDan Willemsen if cf.funcs.isInit != nil { 54*1c12ee1eSDan Willemsen needIsInit = true 55*1c12ee1eSDan Willemsen } 56*1c12ee1eSDan Willemsen mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 57*1c12ee1eSDan Willemsen var vw reflect.Value // pointer to wrapper type 58*1c12ee1eSDan Willemsen vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind 59*1c12ee1eSDan Willemsen if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot { 60*1c12ee1eSDan Willemsen vw = vi.Elem() 61*1c12ee1eSDan Willemsen } else { 62*1c12ee1eSDan Willemsen vw = reflect.New(ot) 63*1c12ee1eSDan Willemsen } 64*1c12ee1eSDan Willemsen out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts) 65*1c12ee1eSDan Willemsen if err != nil { 66*1c12ee1eSDan Willemsen return out, err 67*1c12ee1eSDan Willemsen } 68*1c12ee1eSDan Willemsen vi.Set(vw) 69*1c12ee1eSDan Willemsen return out, nil 70*1c12ee1eSDan Willemsen } 71*1c12ee1eSDan Willemsen } 72*1c12ee1eSDan Willemsen getInfo := func(p pointer) (pointer, *coderFieldInfo) { 73*1c12ee1eSDan Willemsen v := p.AsValueOf(ft).Elem() 74*1c12ee1eSDan Willemsen if v.IsNil() { 75*1c12ee1eSDan Willemsen return pointer{}, nil 76*1c12ee1eSDan Willemsen } 77*1c12ee1eSDan Willemsen v = v.Elem() // interface -> *struct 78*1c12ee1eSDan Willemsen if v.IsNil() { 79*1c12ee1eSDan Willemsen return pointer{}, nil 80*1c12ee1eSDan Willemsen } 81*1c12ee1eSDan Willemsen return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()] 82*1c12ee1eSDan Willemsen } 83*1c12ee1eSDan Willemsen first := mi.coderFields[od.Fields().Get(0).Number()] 84*1c12ee1eSDan Willemsen first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int { 85*1c12ee1eSDan Willemsen p, info := getInfo(p) 86*1c12ee1eSDan Willemsen if info == nil || info.funcs.size == nil { 87*1c12ee1eSDan Willemsen return 0 88*1c12ee1eSDan Willemsen } 89*1c12ee1eSDan Willemsen return info.funcs.size(p, info, opts) 90*1c12ee1eSDan Willemsen } 91*1c12ee1eSDan Willemsen first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) { 92*1c12ee1eSDan Willemsen p, info := getInfo(p) 93*1c12ee1eSDan Willemsen if info == nil || info.funcs.marshal == nil { 94*1c12ee1eSDan Willemsen return b, nil 95*1c12ee1eSDan Willemsen } 96*1c12ee1eSDan Willemsen return info.funcs.marshal(b, p, info, opts) 97*1c12ee1eSDan Willemsen } 98*1c12ee1eSDan Willemsen first.funcs.merge = func(dst, src pointer, _ *coderFieldInfo, opts mergeOptions) { 99*1c12ee1eSDan Willemsen srcp, srcinfo := getInfo(src) 100*1c12ee1eSDan Willemsen if srcinfo == nil || srcinfo.funcs.merge == nil { 101*1c12ee1eSDan Willemsen return 102*1c12ee1eSDan Willemsen } 103*1c12ee1eSDan Willemsen dstp, dstinfo := getInfo(dst) 104*1c12ee1eSDan Willemsen if dstinfo != srcinfo { 105*1c12ee1eSDan Willemsen dst.AsValueOf(ft).Elem().Set(reflect.New(src.AsValueOf(ft).Elem().Elem().Elem().Type())) 106*1c12ee1eSDan Willemsen dstp = pointerOfValue(dst.AsValueOf(ft).Elem().Elem()).Apply(zeroOffset) 107*1c12ee1eSDan Willemsen } 108*1c12ee1eSDan Willemsen srcinfo.funcs.merge(dstp, srcp, srcinfo, opts) 109*1c12ee1eSDan Willemsen } 110*1c12ee1eSDan Willemsen if needIsInit { 111*1c12ee1eSDan Willemsen first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error { 112*1c12ee1eSDan Willemsen p, info := getInfo(p) 113*1c12ee1eSDan Willemsen if info == nil || info.funcs.isInit == nil { 114*1c12ee1eSDan Willemsen return nil 115*1c12ee1eSDan Willemsen } 116*1c12ee1eSDan Willemsen return info.funcs.isInit(p, info) 117*1c12ee1eSDan Willemsen } 118*1c12ee1eSDan Willemsen } 119*1c12ee1eSDan Willemsen} 120*1c12ee1eSDan Willemsen 121*1c12ee1eSDan Willemsenfunc makeWeakMessageFieldCoder(fd protoreflect.FieldDescriptor) pointerCoderFuncs { 122*1c12ee1eSDan Willemsen var once sync.Once 123*1c12ee1eSDan Willemsen var messageType protoreflect.MessageType 124*1c12ee1eSDan Willemsen lazyInit := func() { 125*1c12ee1eSDan Willemsen once.Do(func() { 126*1c12ee1eSDan Willemsen messageName := fd.Message().FullName() 127*1c12ee1eSDan Willemsen messageType, _ = protoregistry.GlobalTypes.FindMessageByName(messageName) 128*1c12ee1eSDan Willemsen }) 129*1c12ee1eSDan Willemsen } 130*1c12ee1eSDan Willemsen 131*1c12ee1eSDan Willemsen return pointerCoderFuncs{ 132*1c12ee1eSDan Willemsen size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 133*1c12ee1eSDan Willemsen m, ok := p.WeakFields().get(f.num) 134*1c12ee1eSDan Willemsen if !ok { 135*1c12ee1eSDan Willemsen return 0 136*1c12ee1eSDan Willemsen } 137*1c12ee1eSDan Willemsen lazyInit() 138*1c12ee1eSDan Willemsen if messageType == nil { 139*1c12ee1eSDan Willemsen panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) 140*1c12ee1eSDan Willemsen } 141*1c12ee1eSDan Willemsen return sizeMessage(m, f.tagsize, opts) 142*1c12ee1eSDan Willemsen }, 143*1c12ee1eSDan Willemsen marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 144*1c12ee1eSDan Willemsen m, ok := p.WeakFields().get(f.num) 145*1c12ee1eSDan Willemsen if !ok { 146*1c12ee1eSDan Willemsen return b, nil 147*1c12ee1eSDan Willemsen } 148*1c12ee1eSDan Willemsen lazyInit() 149*1c12ee1eSDan Willemsen if messageType == nil { 150*1c12ee1eSDan Willemsen panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) 151*1c12ee1eSDan Willemsen } 152*1c12ee1eSDan Willemsen return appendMessage(b, m, f.wiretag, opts) 153*1c12ee1eSDan Willemsen }, 154*1c12ee1eSDan Willemsen unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 155*1c12ee1eSDan Willemsen fs := p.WeakFields() 156*1c12ee1eSDan Willemsen m, ok := fs.get(f.num) 157*1c12ee1eSDan Willemsen if !ok { 158*1c12ee1eSDan Willemsen lazyInit() 159*1c12ee1eSDan Willemsen if messageType == nil { 160*1c12ee1eSDan Willemsen return unmarshalOutput{}, errUnknown 161*1c12ee1eSDan Willemsen } 162*1c12ee1eSDan Willemsen m = messageType.New().Interface() 163*1c12ee1eSDan Willemsen fs.set(f.num, m) 164*1c12ee1eSDan Willemsen } 165*1c12ee1eSDan Willemsen return consumeMessage(b, m, wtyp, opts) 166*1c12ee1eSDan Willemsen }, 167*1c12ee1eSDan Willemsen isInit: func(p pointer, f *coderFieldInfo) error { 168*1c12ee1eSDan Willemsen m, ok := p.WeakFields().get(f.num) 169*1c12ee1eSDan Willemsen if !ok { 170*1c12ee1eSDan Willemsen return nil 171*1c12ee1eSDan Willemsen } 172*1c12ee1eSDan Willemsen return proto.CheckInitialized(m) 173*1c12ee1eSDan Willemsen }, 174*1c12ee1eSDan Willemsen merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { 175*1c12ee1eSDan Willemsen sm, ok := src.WeakFields().get(f.num) 176*1c12ee1eSDan Willemsen if !ok { 177*1c12ee1eSDan Willemsen return 178*1c12ee1eSDan Willemsen } 179*1c12ee1eSDan Willemsen dm, ok := dst.WeakFields().get(f.num) 180*1c12ee1eSDan Willemsen if !ok { 181*1c12ee1eSDan Willemsen lazyInit() 182*1c12ee1eSDan Willemsen if messageType == nil { 183*1c12ee1eSDan Willemsen panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) 184*1c12ee1eSDan Willemsen } 185*1c12ee1eSDan Willemsen dm = messageType.New().Interface() 186*1c12ee1eSDan Willemsen dst.WeakFields().set(f.num, dm) 187*1c12ee1eSDan Willemsen } 188*1c12ee1eSDan Willemsen opts.Merge(dm, sm) 189*1c12ee1eSDan Willemsen }, 190*1c12ee1eSDan Willemsen } 191*1c12ee1eSDan Willemsen} 192*1c12ee1eSDan Willemsen 193*1c12ee1eSDan Willemsenfunc makeMessageFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 194*1c12ee1eSDan Willemsen if mi := getMessageInfo(ft); mi != nil { 195*1c12ee1eSDan Willemsen funcs := pointerCoderFuncs{ 196*1c12ee1eSDan Willemsen size: sizeMessageInfo, 197*1c12ee1eSDan Willemsen marshal: appendMessageInfo, 198*1c12ee1eSDan Willemsen unmarshal: consumeMessageInfo, 199*1c12ee1eSDan Willemsen merge: mergeMessage, 200*1c12ee1eSDan Willemsen } 201*1c12ee1eSDan Willemsen if needsInitCheck(mi.Desc) { 202*1c12ee1eSDan Willemsen funcs.isInit = isInitMessageInfo 203*1c12ee1eSDan Willemsen } 204*1c12ee1eSDan Willemsen return funcs 205*1c12ee1eSDan Willemsen } else { 206*1c12ee1eSDan Willemsen return pointerCoderFuncs{ 207*1c12ee1eSDan Willemsen size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 208*1c12ee1eSDan Willemsen m := asMessage(p.AsValueOf(ft).Elem()) 209*1c12ee1eSDan Willemsen return sizeMessage(m, f.tagsize, opts) 210*1c12ee1eSDan Willemsen }, 211*1c12ee1eSDan Willemsen marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 212*1c12ee1eSDan Willemsen m := asMessage(p.AsValueOf(ft).Elem()) 213*1c12ee1eSDan Willemsen return appendMessage(b, m, f.wiretag, opts) 214*1c12ee1eSDan Willemsen }, 215*1c12ee1eSDan Willemsen unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 216*1c12ee1eSDan Willemsen mp := p.AsValueOf(ft).Elem() 217*1c12ee1eSDan Willemsen if mp.IsNil() { 218*1c12ee1eSDan Willemsen mp.Set(reflect.New(ft.Elem())) 219*1c12ee1eSDan Willemsen } 220*1c12ee1eSDan Willemsen return consumeMessage(b, asMessage(mp), wtyp, opts) 221*1c12ee1eSDan Willemsen }, 222*1c12ee1eSDan Willemsen isInit: func(p pointer, f *coderFieldInfo) error { 223*1c12ee1eSDan Willemsen m := asMessage(p.AsValueOf(ft).Elem()) 224*1c12ee1eSDan Willemsen return proto.CheckInitialized(m) 225*1c12ee1eSDan Willemsen }, 226*1c12ee1eSDan Willemsen merge: mergeMessage, 227*1c12ee1eSDan Willemsen } 228*1c12ee1eSDan Willemsen } 229*1c12ee1eSDan Willemsen} 230*1c12ee1eSDan Willemsen 231*1c12ee1eSDan Willemsenfunc sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { 232*1c12ee1eSDan Willemsen return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize 233*1c12ee1eSDan Willemsen} 234*1c12ee1eSDan Willemsen 235*1c12ee1eSDan Willemsenfunc appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 236*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, f.wiretag) 237*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts))) 238*1c12ee1eSDan Willemsen return f.mi.marshalAppendPointer(b, p.Elem(), opts) 239*1c12ee1eSDan Willemsen} 240*1c12ee1eSDan Willemsen 241*1c12ee1eSDan Willemsenfunc consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 242*1c12ee1eSDan Willemsen if wtyp != protowire.BytesType { 243*1c12ee1eSDan Willemsen return out, errUnknown 244*1c12ee1eSDan Willemsen } 245*1c12ee1eSDan Willemsen v, n := protowire.ConsumeBytes(b) 246*1c12ee1eSDan Willemsen if n < 0 { 247*1c12ee1eSDan Willemsen return out, errDecode 248*1c12ee1eSDan Willemsen } 249*1c12ee1eSDan Willemsen if p.Elem().IsNil() { 250*1c12ee1eSDan Willemsen p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) 251*1c12ee1eSDan Willemsen } 252*1c12ee1eSDan Willemsen o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts) 253*1c12ee1eSDan Willemsen if err != nil { 254*1c12ee1eSDan Willemsen return out, err 255*1c12ee1eSDan Willemsen } 256*1c12ee1eSDan Willemsen out.n = n 257*1c12ee1eSDan Willemsen out.initialized = o.initialized 258*1c12ee1eSDan Willemsen return out, nil 259*1c12ee1eSDan Willemsen} 260*1c12ee1eSDan Willemsen 261*1c12ee1eSDan Willemsenfunc isInitMessageInfo(p pointer, f *coderFieldInfo) error { 262*1c12ee1eSDan Willemsen return f.mi.checkInitializedPointer(p.Elem()) 263*1c12ee1eSDan Willemsen} 264*1c12ee1eSDan Willemsen 265*1c12ee1eSDan Willemsenfunc sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int { 266*1c12ee1eSDan Willemsen return protowire.SizeBytes(proto.Size(m)) + tagsize 267*1c12ee1eSDan Willemsen} 268*1c12ee1eSDan Willemsen 269*1c12ee1eSDan Willemsenfunc appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { 270*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag) 271*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, uint64(proto.Size(m))) 272*1c12ee1eSDan Willemsen return opts.Options().MarshalAppend(b, m) 273*1c12ee1eSDan Willemsen} 274*1c12ee1eSDan Willemsen 275*1c12ee1eSDan Willemsenfunc consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 276*1c12ee1eSDan Willemsen if wtyp != protowire.BytesType { 277*1c12ee1eSDan Willemsen return out, errUnknown 278*1c12ee1eSDan Willemsen } 279*1c12ee1eSDan Willemsen v, n := protowire.ConsumeBytes(b) 280*1c12ee1eSDan Willemsen if n < 0 { 281*1c12ee1eSDan Willemsen return out, errDecode 282*1c12ee1eSDan Willemsen } 283*1c12ee1eSDan Willemsen o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{ 284*1c12ee1eSDan Willemsen Buf: v, 285*1c12ee1eSDan Willemsen Message: m.ProtoReflect(), 286*1c12ee1eSDan Willemsen }) 287*1c12ee1eSDan Willemsen if err != nil { 288*1c12ee1eSDan Willemsen return out, err 289*1c12ee1eSDan Willemsen } 290*1c12ee1eSDan Willemsen out.n = n 291*1c12ee1eSDan Willemsen out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0 292*1c12ee1eSDan Willemsen return out, nil 293*1c12ee1eSDan Willemsen} 294*1c12ee1eSDan Willemsen 295*1c12ee1eSDan Willemsenfunc sizeMessageValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { 296*1c12ee1eSDan Willemsen m := v.Message().Interface() 297*1c12ee1eSDan Willemsen return sizeMessage(m, tagsize, opts) 298*1c12ee1eSDan Willemsen} 299*1c12ee1eSDan Willemsen 300*1c12ee1eSDan Willemsenfunc appendMessageValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 301*1c12ee1eSDan Willemsen m := v.Message().Interface() 302*1c12ee1eSDan Willemsen return appendMessage(b, m, wiretag, opts) 303*1c12ee1eSDan Willemsen} 304*1c12ee1eSDan Willemsen 305*1c12ee1eSDan Willemsenfunc consumeMessageValue(b []byte, v protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (protoreflect.Value, unmarshalOutput, error) { 306*1c12ee1eSDan Willemsen m := v.Message().Interface() 307*1c12ee1eSDan Willemsen out, err := consumeMessage(b, m, wtyp, opts) 308*1c12ee1eSDan Willemsen return v, out, err 309*1c12ee1eSDan Willemsen} 310*1c12ee1eSDan Willemsen 311*1c12ee1eSDan Willemsenfunc isInitMessageValue(v protoreflect.Value) error { 312*1c12ee1eSDan Willemsen m := v.Message().Interface() 313*1c12ee1eSDan Willemsen return proto.CheckInitialized(m) 314*1c12ee1eSDan Willemsen} 315*1c12ee1eSDan Willemsen 316*1c12ee1eSDan Willemsenvar coderMessageValue = valueCoderFuncs{ 317*1c12ee1eSDan Willemsen size: sizeMessageValue, 318*1c12ee1eSDan Willemsen marshal: appendMessageValue, 319*1c12ee1eSDan Willemsen unmarshal: consumeMessageValue, 320*1c12ee1eSDan Willemsen isInit: isInitMessageValue, 321*1c12ee1eSDan Willemsen merge: mergeMessageValue, 322*1c12ee1eSDan Willemsen} 323*1c12ee1eSDan Willemsen 324*1c12ee1eSDan Willemsenfunc sizeGroupValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { 325*1c12ee1eSDan Willemsen m := v.Message().Interface() 326*1c12ee1eSDan Willemsen return sizeGroup(m, tagsize, opts) 327*1c12ee1eSDan Willemsen} 328*1c12ee1eSDan Willemsen 329*1c12ee1eSDan Willemsenfunc appendGroupValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 330*1c12ee1eSDan Willemsen m := v.Message().Interface() 331*1c12ee1eSDan Willemsen return appendGroup(b, m, wiretag, opts) 332*1c12ee1eSDan Willemsen} 333*1c12ee1eSDan Willemsen 334*1c12ee1eSDan Willemsenfunc consumeGroupValue(b []byte, v protoreflect.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (protoreflect.Value, unmarshalOutput, error) { 335*1c12ee1eSDan Willemsen m := v.Message().Interface() 336*1c12ee1eSDan Willemsen out, err := consumeGroup(b, m, num, wtyp, opts) 337*1c12ee1eSDan Willemsen return v, out, err 338*1c12ee1eSDan Willemsen} 339*1c12ee1eSDan Willemsen 340*1c12ee1eSDan Willemsenvar coderGroupValue = valueCoderFuncs{ 341*1c12ee1eSDan Willemsen size: sizeGroupValue, 342*1c12ee1eSDan Willemsen marshal: appendGroupValue, 343*1c12ee1eSDan Willemsen unmarshal: consumeGroupValue, 344*1c12ee1eSDan Willemsen isInit: isInitMessageValue, 345*1c12ee1eSDan Willemsen merge: mergeMessageValue, 346*1c12ee1eSDan Willemsen} 347*1c12ee1eSDan Willemsen 348*1c12ee1eSDan Willemsenfunc makeGroupFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 349*1c12ee1eSDan Willemsen num := fd.Number() 350*1c12ee1eSDan Willemsen if mi := getMessageInfo(ft); mi != nil { 351*1c12ee1eSDan Willemsen funcs := pointerCoderFuncs{ 352*1c12ee1eSDan Willemsen size: sizeGroupType, 353*1c12ee1eSDan Willemsen marshal: appendGroupType, 354*1c12ee1eSDan Willemsen unmarshal: consumeGroupType, 355*1c12ee1eSDan Willemsen merge: mergeMessage, 356*1c12ee1eSDan Willemsen } 357*1c12ee1eSDan Willemsen if needsInitCheck(mi.Desc) { 358*1c12ee1eSDan Willemsen funcs.isInit = isInitMessageInfo 359*1c12ee1eSDan Willemsen } 360*1c12ee1eSDan Willemsen return funcs 361*1c12ee1eSDan Willemsen } else { 362*1c12ee1eSDan Willemsen return pointerCoderFuncs{ 363*1c12ee1eSDan Willemsen size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 364*1c12ee1eSDan Willemsen m := asMessage(p.AsValueOf(ft).Elem()) 365*1c12ee1eSDan Willemsen return sizeGroup(m, f.tagsize, opts) 366*1c12ee1eSDan Willemsen }, 367*1c12ee1eSDan Willemsen marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 368*1c12ee1eSDan Willemsen m := asMessage(p.AsValueOf(ft).Elem()) 369*1c12ee1eSDan Willemsen return appendGroup(b, m, f.wiretag, opts) 370*1c12ee1eSDan Willemsen }, 371*1c12ee1eSDan Willemsen unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 372*1c12ee1eSDan Willemsen mp := p.AsValueOf(ft).Elem() 373*1c12ee1eSDan Willemsen if mp.IsNil() { 374*1c12ee1eSDan Willemsen mp.Set(reflect.New(ft.Elem())) 375*1c12ee1eSDan Willemsen } 376*1c12ee1eSDan Willemsen return consumeGroup(b, asMessage(mp), num, wtyp, opts) 377*1c12ee1eSDan Willemsen }, 378*1c12ee1eSDan Willemsen isInit: func(p pointer, f *coderFieldInfo) error { 379*1c12ee1eSDan Willemsen m := asMessage(p.AsValueOf(ft).Elem()) 380*1c12ee1eSDan Willemsen return proto.CheckInitialized(m) 381*1c12ee1eSDan Willemsen }, 382*1c12ee1eSDan Willemsen merge: mergeMessage, 383*1c12ee1eSDan Willemsen } 384*1c12ee1eSDan Willemsen } 385*1c12ee1eSDan Willemsen} 386*1c12ee1eSDan Willemsen 387*1c12ee1eSDan Willemsenfunc sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int { 388*1c12ee1eSDan Willemsen return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts) 389*1c12ee1eSDan Willemsen} 390*1c12ee1eSDan Willemsen 391*1c12ee1eSDan Willemsenfunc appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 392*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, f.wiretag) // start group 393*1c12ee1eSDan Willemsen b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts) 394*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, f.wiretag+1) // end group 395*1c12ee1eSDan Willemsen return b, err 396*1c12ee1eSDan Willemsen} 397*1c12ee1eSDan Willemsen 398*1c12ee1eSDan Willemsenfunc consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 399*1c12ee1eSDan Willemsen if wtyp != protowire.StartGroupType { 400*1c12ee1eSDan Willemsen return out, errUnknown 401*1c12ee1eSDan Willemsen } 402*1c12ee1eSDan Willemsen if p.Elem().IsNil() { 403*1c12ee1eSDan Willemsen p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) 404*1c12ee1eSDan Willemsen } 405*1c12ee1eSDan Willemsen return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts) 406*1c12ee1eSDan Willemsen} 407*1c12ee1eSDan Willemsen 408*1c12ee1eSDan Willemsenfunc sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int { 409*1c12ee1eSDan Willemsen return 2*tagsize + proto.Size(m) 410*1c12ee1eSDan Willemsen} 411*1c12ee1eSDan Willemsen 412*1c12ee1eSDan Willemsenfunc appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { 413*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag) // start group 414*1c12ee1eSDan Willemsen b, err := opts.Options().MarshalAppend(b, m) 415*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag+1) // end group 416*1c12ee1eSDan Willemsen return b, err 417*1c12ee1eSDan Willemsen} 418*1c12ee1eSDan Willemsen 419*1c12ee1eSDan Willemsenfunc consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 420*1c12ee1eSDan Willemsen if wtyp != protowire.StartGroupType { 421*1c12ee1eSDan Willemsen return out, errUnknown 422*1c12ee1eSDan Willemsen } 423*1c12ee1eSDan Willemsen b, n := protowire.ConsumeGroup(num, b) 424*1c12ee1eSDan Willemsen if n < 0 { 425*1c12ee1eSDan Willemsen return out, errDecode 426*1c12ee1eSDan Willemsen } 427*1c12ee1eSDan Willemsen o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{ 428*1c12ee1eSDan Willemsen Buf: b, 429*1c12ee1eSDan Willemsen Message: m.ProtoReflect(), 430*1c12ee1eSDan Willemsen }) 431*1c12ee1eSDan Willemsen if err != nil { 432*1c12ee1eSDan Willemsen return out, err 433*1c12ee1eSDan Willemsen } 434*1c12ee1eSDan Willemsen out.n = n 435*1c12ee1eSDan Willemsen out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0 436*1c12ee1eSDan Willemsen return out, nil 437*1c12ee1eSDan Willemsen} 438*1c12ee1eSDan Willemsen 439*1c12ee1eSDan Willemsenfunc makeMessageSliceFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 440*1c12ee1eSDan Willemsen if mi := getMessageInfo(ft); mi != nil { 441*1c12ee1eSDan Willemsen funcs := pointerCoderFuncs{ 442*1c12ee1eSDan Willemsen size: sizeMessageSliceInfo, 443*1c12ee1eSDan Willemsen marshal: appendMessageSliceInfo, 444*1c12ee1eSDan Willemsen unmarshal: consumeMessageSliceInfo, 445*1c12ee1eSDan Willemsen merge: mergeMessageSlice, 446*1c12ee1eSDan Willemsen } 447*1c12ee1eSDan Willemsen if needsInitCheck(mi.Desc) { 448*1c12ee1eSDan Willemsen funcs.isInit = isInitMessageSliceInfo 449*1c12ee1eSDan Willemsen } 450*1c12ee1eSDan Willemsen return funcs 451*1c12ee1eSDan Willemsen } 452*1c12ee1eSDan Willemsen return pointerCoderFuncs{ 453*1c12ee1eSDan Willemsen size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 454*1c12ee1eSDan Willemsen return sizeMessageSlice(p, ft, f.tagsize, opts) 455*1c12ee1eSDan Willemsen }, 456*1c12ee1eSDan Willemsen marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 457*1c12ee1eSDan Willemsen return appendMessageSlice(b, p, f.wiretag, ft, opts) 458*1c12ee1eSDan Willemsen }, 459*1c12ee1eSDan Willemsen unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 460*1c12ee1eSDan Willemsen return consumeMessageSlice(b, p, ft, wtyp, opts) 461*1c12ee1eSDan Willemsen }, 462*1c12ee1eSDan Willemsen isInit: func(p pointer, f *coderFieldInfo) error { 463*1c12ee1eSDan Willemsen return isInitMessageSlice(p, ft) 464*1c12ee1eSDan Willemsen }, 465*1c12ee1eSDan Willemsen merge: mergeMessageSlice, 466*1c12ee1eSDan Willemsen } 467*1c12ee1eSDan Willemsen} 468*1c12ee1eSDan Willemsen 469*1c12ee1eSDan Willemsenfunc sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { 470*1c12ee1eSDan Willemsen s := p.PointerSlice() 471*1c12ee1eSDan Willemsen n := 0 472*1c12ee1eSDan Willemsen for _, v := range s { 473*1c12ee1eSDan Willemsen n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize 474*1c12ee1eSDan Willemsen } 475*1c12ee1eSDan Willemsen return n 476*1c12ee1eSDan Willemsen} 477*1c12ee1eSDan Willemsen 478*1c12ee1eSDan Willemsenfunc appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 479*1c12ee1eSDan Willemsen s := p.PointerSlice() 480*1c12ee1eSDan Willemsen var err error 481*1c12ee1eSDan Willemsen for _, v := range s { 482*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, f.wiretag) 483*1c12ee1eSDan Willemsen siz := f.mi.sizePointer(v, opts) 484*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, uint64(siz)) 485*1c12ee1eSDan Willemsen b, err = f.mi.marshalAppendPointer(b, v, opts) 486*1c12ee1eSDan Willemsen if err != nil { 487*1c12ee1eSDan Willemsen return b, err 488*1c12ee1eSDan Willemsen } 489*1c12ee1eSDan Willemsen } 490*1c12ee1eSDan Willemsen return b, nil 491*1c12ee1eSDan Willemsen} 492*1c12ee1eSDan Willemsen 493*1c12ee1eSDan Willemsenfunc consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 494*1c12ee1eSDan Willemsen if wtyp != protowire.BytesType { 495*1c12ee1eSDan Willemsen return out, errUnknown 496*1c12ee1eSDan Willemsen } 497*1c12ee1eSDan Willemsen v, n := protowire.ConsumeBytes(b) 498*1c12ee1eSDan Willemsen if n < 0 { 499*1c12ee1eSDan Willemsen return out, errDecode 500*1c12ee1eSDan Willemsen } 501*1c12ee1eSDan Willemsen m := reflect.New(f.mi.GoReflectType.Elem()).Interface() 502*1c12ee1eSDan Willemsen mp := pointerOfIface(m) 503*1c12ee1eSDan Willemsen o, err := f.mi.unmarshalPointer(v, mp, 0, opts) 504*1c12ee1eSDan Willemsen if err != nil { 505*1c12ee1eSDan Willemsen return out, err 506*1c12ee1eSDan Willemsen } 507*1c12ee1eSDan Willemsen p.AppendPointerSlice(mp) 508*1c12ee1eSDan Willemsen out.n = n 509*1c12ee1eSDan Willemsen out.initialized = o.initialized 510*1c12ee1eSDan Willemsen return out, nil 511*1c12ee1eSDan Willemsen} 512*1c12ee1eSDan Willemsen 513*1c12ee1eSDan Willemsenfunc isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error { 514*1c12ee1eSDan Willemsen s := p.PointerSlice() 515*1c12ee1eSDan Willemsen for _, v := range s { 516*1c12ee1eSDan Willemsen if err := f.mi.checkInitializedPointer(v); err != nil { 517*1c12ee1eSDan Willemsen return err 518*1c12ee1eSDan Willemsen } 519*1c12ee1eSDan Willemsen } 520*1c12ee1eSDan Willemsen return nil 521*1c12ee1eSDan Willemsen} 522*1c12ee1eSDan Willemsen 523*1c12ee1eSDan Willemsenfunc sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int { 524*1c12ee1eSDan Willemsen s := p.PointerSlice() 525*1c12ee1eSDan Willemsen n := 0 526*1c12ee1eSDan Willemsen for _, v := range s { 527*1c12ee1eSDan Willemsen m := asMessage(v.AsValueOf(goType.Elem())) 528*1c12ee1eSDan Willemsen n += protowire.SizeBytes(proto.Size(m)) + tagsize 529*1c12ee1eSDan Willemsen } 530*1c12ee1eSDan Willemsen return n 531*1c12ee1eSDan Willemsen} 532*1c12ee1eSDan Willemsen 533*1c12ee1eSDan Willemsenfunc appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) { 534*1c12ee1eSDan Willemsen s := p.PointerSlice() 535*1c12ee1eSDan Willemsen var err error 536*1c12ee1eSDan Willemsen for _, v := range s { 537*1c12ee1eSDan Willemsen m := asMessage(v.AsValueOf(goType.Elem())) 538*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag) 539*1c12ee1eSDan Willemsen siz := proto.Size(m) 540*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, uint64(siz)) 541*1c12ee1eSDan Willemsen b, err = opts.Options().MarshalAppend(b, m) 542*1c12ee1eSDan Willemsen if err != nil { 543*1c12ee1eSDan Willemsen return b, err 544*1c12ee1eSDan Willemsen } 545*1c12ee1eSDan Willemsen } 546*1c12ee1eSDan Willemsen return b, nil 547*1c12ee1eSDan Willemsen} 548*1c12ee1eSDan Willemsen 549*1c12ee1eSDan Willemsenfunc consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 550*1c12ee1eSDan Willemsen if wtyp != protowire.BytesType { 551*1c12ee1eSDan Willemsen return out, errUnknown 552*1c12ee1eSDan Willemsen } 553*1c12ee1eSDan Willemsen v, n := protowire.ConsumeBytes(b) 554*1c12ee1eSDan Willemsen if n < 0 { 555*1c12ee1eSDan Willemsen return out, errDecode 556*1c12ee1eSDan Willemsen } 557*1c12ee1eSDan Willemsen mp := reflect.New(goType.Elem()) 558*1c12ee1eSDan Willemsen o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{ 559*1c12ee1eSDan Willemsen Buf: v, 560*1c12ee1eSDan Willemsen Message: asMessage(mp).ProtoReflect(), 561*1c12ee1eSDan Willemsen }) 562*1c12ee1eSDan Willemsen if err != nil { 563*1c12ee1eSDan Willemsen return out, err 564*1c12ee1eSDan Willemsen } 565*1c12ee1eSDan Willemsen p.AppendPointerSlice(pointerOfValue(mp)) 566*1c12ee1eSDan Willemsen out.n = n 567*1c12ee1eSDan Willemsen out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0 568*1c12ee1eSDan Willemsen return out, nil 569*1c12ee1eSDan Willemsen} 570*1c12ee1eSDan Willemsen 571*1c12ee1eSDan Willemsenfunc isInitMessageSlice(p pointer, goType reflect.Type) error { 572*1c12ee1eSDan Willemsen s := p.PointerSlice() 573*1c12ee1eSDan Willemsen for _, v := range s { 574*1c12ee1eSDan Willemsen m := asMessage(v.AsValueOf(goType.Elem())) 575*1c12ee1eSDan Willemsen if err := proto.CheckInitialized(m); err != nil { 576*1c12ee1eSDan Willemsen return err 577*1c12ee1eSDan Willemsen } 578*1c12ee1eSDan Willemsen } 579*1c12ee1eSDan Willemsen return nil 580*1c12ee1eSDan Willemsen} 581*1c12ee1eSDan Willemsen 582*1c12ee1eSDan Willemsen// Slices of messages 583*1c12ee1eSDan Willemsen 584*1c12ee1eSDan Willemsenfunc sizeMessageSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int { 585*1c12ee1eSDan Willemsen list := listv.List() 586*1c12ee1eSDan Willemsen n := 0 587*1c12ee1eSDan Willemsen for i, llen := 0, list.Len(); i < llen; i++ { 588*1c12ee1eSDan Willemsen m := list.Get(i).Message().Interface() 589*1c12ee1eSDan Willemsen n += protowire.SizeBytes(proto.Size(m)) + tagsize 590*1c12ee1eSDan Willemsen } 591*1c12ee1eSDan Willemsen return n 592*1c12ee1eSDan Willemsen} 593*1c12ee1eSDan Willemsen 594*1c12ee1eSDan Willemsenfunc appendMessageSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 595*1c12ee1eSDan Willemsen list := listv.List() 596*1c12ee1eSDan Willemsen mopts := opts.Options() 597*1c12ee1eSDan Willemsen for i, llen := 0, list.Len(); i < llen; i++ { 598*1c12ee1eSDan Willemsen m := list.Get(i).Message().Interface() 599*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag) 600*1c12ee1eSDan Willemsen siz := proto.Size(m) 601*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, uint64(siz)) 602*1c12ee1eSDan Willemsen var err error 603*1c12ee1eSDan Willemsen b, err = mopts.MarshalAppend(b, m) 604*1c12ee1eSDan Willemsen if err != nil { 605*1c12ee1eSDan Willemsen return b, err 606*1c12ee1eSDan Willemsen } 607*1c12ee1eSDan Willemsen } 608*1c12ee1eSDan Willemsen return b, nil 609*1c12ee1eSDan Willemsen} 610*1c12ee1eSDan Willemsen 611*1c12ee1eSDan Willemsenfunc consumeMessageSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { 612*1c12ee1eSDan Willemsen list := listv.List() 613*1c12ee1eSDan Willemsen if wtyp != protowire.BytesType { 614*1c12ee1eSDan Willemsen return protoreflect.Value{}, out, errUnknown 615*1c12ee1eSDan Willemsen } 616*1c12ee1eSDan Willemsen v, n := protowire.ConsumeBytes(b) 617*1c12ee1eSDan Willemsen if n < 0 { 618*1c12ee1eSDan Willemsen return protoreflect.Value{}, out, errDecode 619*1c12ee1eSDan Willemsen } 620*1c12ee1eSDan Willemsen m := list.NewElement() 621*1c12ee1eSDan Willemsen o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{ 622*1c12ee1eSDan Willemsen Buf: v, 623*1c12ee1eSDan Willemsen Message: m.Message(), 624*1c12ee1eSDan Willemsen }) 625*1c12ee1eSDan Willemsen if err != nil { 626*1c12ee1eSDan Willemsen return protoreflect.Value{}, out, err 627*1c12ee1eSDan Willemsen } 628*1c12ee1eSDan Willemsen list.Append(m) 629*1c12ee1eSDan Willemsen out.n = n 630*1c12ee1eSDan Willemsen out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0 631*1c12ee1eSDan Willemsen return listv, out, nil 632*1c12ee1eSDan Willemsen} 633*1c12ee1eSDan Willemsen 634*1c12ee1eSDan Willemsenfunc isInitMessageSliceValue(listv protoreflect.Value) error { 635*1c12ee1eSDan Willemsen list := listv.List() 636*1c12ee1eSDan Willemsen for i, llen := 0, list.Len(); i < llen; i++ { 637*1c12ee1eSDan Willemsen m := list.Get(i).Message().Interface() 638*1c12ee1eSDan Willemsen if err := proto.CheckInitialized(m); err != nil { 639*1c12ee1eSDan Willemsen return err 640*1c12ee1eSDan Willemsen } 641*1c12ee1eSDan Willemsen } 642*1c12ee1eSDan Willemsen return nil 643*1c12ee1eSDan Willemsen} 644*1c12ee1eSDan Willemsen 645*1c12ee1eSDan Willemsenvar coderMessageSliceValue = valueCoderFuncs{ 646*1c12ee1eSDan Willemsen size: sizeMessageSliceValue, 647*1c12ee1eSDan Willemsen marshal: appendMessageSliceValue, 648*1c12ee1eSDan Willemsen unmarshal: consumeMessageSliceValue, 649*1c12ee1eSDan Willemsen isInit: isInitMessageSliceValue, 650*1c12ee1eSDan Willemsen merge: mergeMessageListValue, 651*1c12ee1eSDan Willemsen} 652*1c12ee1eSDan Willemsen 653*1c12ee1eSDan Willemsenfunc sizeGroupSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int { 654*1c12ee1eSDan Willemsen list := listv.List() 655*1c12ee1eSDan Willemsen n := 0 656*1c12ee1eSDan Willemsen for i, llen := 0, list.Len(); i < llen; i++ { 657*1c12ee1eSDan Willemsen m := list.Get(i).Message().Interface() 658*1c12ee1eSDan Willemsen n += 2*tagsize + proto.Size(m) 659*1c12ee1eSDan Willemsen } 660*1c12ee1eSDan Willemsen return n 661*1c12ee1eSDan Willemsen} 662*1c12ee1eSDan Willemsen 663*1c12ee1eSDan Willemsenfunc appendGroupSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 664*1c12ee1eSDan Willemsen list := listv.List() 665*1c12ee1eSDan Willemsen mopts := opts.Options() 666*1c12ee1eSDan Willemsen for i, llen := 0, list.Len(); i < llen; i++ { 667*1c12ee1eSDan Willemsen m := list.Get(i).Message().Interface() 668*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag) // start group 669*1c12ee1eSDan Willemsen var err error 670*1c12ee1eSDan Willemsen b, err = mopts.MarshalAppend(b, m) 671*1c12ee1eSDan Willemsen if err != nil { 672*1c12ee1eSDan Willemsen return b, err 673*1c12ee1eSDan Willemsen } 674*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag+1) // end group 675*1c12ee1eSDan Willemsen } 676*1c12ee1eSDan Willemsen return b, nil 677*1c12ee1eSDan Willemsen} 678*1c12ee1eSDan Willemsen 679*1c12ee1eSDan Willemsenfunc consumeGroupSliceValue(b []byte, listv protoreflect.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { 680*1c12ee1eSDan Willemsen list := listv.List() 681*1c12ee1eSDan Willemsen if wtyp != protowire.StartGroupType { 682*1c12ee1eSDan Willemsen return protoreflect.Value{}, out, errUnknown 683*1c12ee1eSDan Willemsen } 684*1c12ee1eSDan Willemsen b, n := protowire.ConsumeGroup(num, b) 685*1c12ee1eSDan Willemsen if n < 0 { 686*1c12ee1eSDan Willemsen return protoreflect.Value{}, out, errDecode 687*1c12ee1eSDan Willemsen } 688*1c12ee1eSDan Willemsen m := list.NewElement() 689*1c12ee1eSDan Willemsen o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{ 690*1c12ee1eSDan Willemsen Buf: b, 691*1c12ee1eSDan Willemsen Message: m.Message(), 692*1c12ee1eSDan Willemsen }) 693*1c12ee1eSDan Willemsen if err != nil { 694*1c12ee1eSDan Willemsen return protoreflect.Value{}, out, err 695*1c12ee1eSDan Willemsen } 696*1c12ee1eSDan Willemsen list.Append(m) 697*1c12ee1eSDan Willemsen out.n = n 698*1c12ee1eSDan Willemsen out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0 699*1c12ee1eSDan Willemsen return listv, out, nil 700*1c12ee1eSDan Willemsen} 701*1c12ee1eSDan Willemsen 702*1c12ee1eSDan Willemsenvar coderGroupSliceValue = valueCoderFuncs{ 703*1c12ee1eSDan Willemsen size: sizeGroupSliceValue, 704*1c12ee1eSDan Willemsen marshal: appendGroupSliceValue, 705*1c12ee1eSDan Willemsen unmarshal: consumeGroupSliceValue, 706*1c12ee1eSDan Willemsen isInit: isInitMessageSliceValue, 707*1c12ee1eSDan Willemsen merge: mergeMessageListValue, 708*1c12ee1eSDan Willemsen} 709*1c12ee1eSDan Willemsen 710*1c12ee1eSDan Willemsenfunc makeGroupSliceFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 711*1c12ee1eSDan Willemsen num := fd.Number() 712*1c12ee1eSDan Willemsen if mi := getMessageInfo(ft); mi != nil { 713*1c12ee1eSDan Willemsen funcs := pointerCoderFuncs{ 714*1c12ee1eSDan Willemsen size: sizeGroupSliceInfo, 715*1c12ee1eSDan Willemsen marshal: appendGroupSliceInfo, 716*1c12ee1eSDan Willemsen unmarshal: consumeGroupSliceInfo, 717*1c12ee1eSDan Willemsen merge: mergeMessageSlice, 718*1c12ee1eSDan Willemsen } 719*1c12ee1eSDan Willemsen if needsInitCheck(mi.Desc) { 720*1c12ee1eSDan Willemsen funcs.isInit = isInitMessageSliceInfo 721*1c12ee1eSDan Willemsen } 722*1c12ee1eSDan Willemsen return funcs 723*1c12ee1eSDan Willemsen } 724*1c12ee1eSDan Willemsen return pointerCoderFuncs{ 725*1c12ee1eSDan Willemsen size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 726*1c12ee1eSDan Willemsen return sizeGroupSlice(p, ft, f.tagsize, opts) 727*1c12ee1eSDan Willemsen }, 728*1c12ee1eSDan Willemsen marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 729*1c12ee1eSDan Willemsen return appendGroupSlice(b, p, f.wiretag, ft, opts) 730*1c12ee1eSDan Willemsen }, 731*1c12ee1eSDan Willemsen unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 732*1c12ee1eSDan Willemsen return consumeGroupSlice(b, p, num, wtyp, ft, opts) 733*1c12ee1eSDan Willemsen }, 734*1c12ee1eSDan Willemsen isInit: func(p pointer, f *coderFieldInfo) error { 735*1c12ee1eSDan Willemsen return isInitMessageSlice(p, ft) 736*1c12ee1eSDan Willemsen }, 737*1c12ee1eSDan Willemsen merge: mergeMessageSlice, 738*1c12ee1eSDan Willemsen } 739*1c12ee1eSDan Willemsen} 740*1c12ee1eSDan Willemsen 741*1c12ee1eSDan Willemsenfunc sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int { 742*1c12ee1eSDan Willemsen s := p.PointerSlice() 743*1c12ee1eSDan Willemsen n := 0 744*1c12ee1eSDan Willemsen for _, v := range s { 745*1c12ee1eSDan Willemsen m := asMessage(v.AsValueOf(messageType.Elem())) 746*1c12ee1eSDan Willemsen n += 2*tagsize + proto.Size(m) 747*1c12ee1eSDan Willemsen } 748*1c12ee1eSDan Willemsen return n 749*1c12ee1eSDan Willemsen} 750*1c12ee1eSDan Willemsen 751*1c12ee1eSDan Willemsenfunc appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) { 752*1c12ee1eSDan Willemsen s := p.PointerSlice() 753*1c12ee1eSDan Willemsen var err error 754*1c12ee1eSDan Willemsen for _, v := range s { 755*1c12ee1eSDan Willemsen m := asMessage(v.AsValueOf(messageType.Elem())) 756*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag) // start group 757*1c12ee1eSDan Willemsen b, err = opts.Options().MarshalAppend(b, m) 758*1c12ee1eSDan Willemsen if err != nil { 759*1c12ee1eSDan Willemsen return b, err 760*1c12ee1eSDan Willemsen } 761*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, wiretag+1) // end group 762*1c12ee1eSDan Willemsen } 763*1c12ee1eSDan Willemsen return b, nil 764*1c12ee1eSDan Willemsen} 765*1c12ee1eSDan Willemsen 766*1c12ee1eSDan Willemsenfunc consumeGroupSlice(b []byte, p pointer, num protowire.Number, wtyp protowire.Type, goType reflect.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 767*1c12ee1eSDan Willemsen if wtyp != protowire.StartGroupType { 768*1c12ee1eSDan Willemsen return out, errUnknown 769*1c12ee1eSDan Willemsen } 770*1c12ee1eSDan Willemsen b, n := protowire.ConsumeGroup(num, b) 771*1c12ee1eSDan Willemsen if n < 0 { 772*1c12ee1eSDan Willemsen return out, errDecode 773*1c12ee1eSDan Willemsen } 774*1c12ee1eSDan Willemsen mp := reflect.New(goType.Elem()) 775*1c12ee1eSDan Willemsen o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{ 776*1c12ee1eSDan Willemsen Buf: b, 777*1c12ee1eSDan Willemsen Message: asMessage(mp).ProtoReflect(), 778*1c12ee1eSDan Willemsen }) 779*1c12ee1eSDan Willemsen if err != nil { 780*1c12ee1eSDan Willemsen return out, err 781*1c12ee1eSDan Willemsen } 782*1c12ee1eSDan Willemsen p.AppendPointerSlice(pointerOfValue(mp)) 783*1c12ee1eSDan Willemsen out.n = n 784*1c12ee1eSDan Willemsen out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0 785*1c12ee1eSDan Willemsen return out, nil 786*1c12ee1eSDan Willemsen} 787*1c12ee1eSDan Willemsen 788*1c12ee1eSDan Willemsenfunc sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { 789*1c12ee1eSDan Willemsen s := p.PointerSlice() 790*1c12ee1eSDan Willemsen n := 0 791*1c12ee1eSDan Willemsen for _, v := range s { 792*1c12ee1eSDan Willemsen n += 2*f.tagsize + f.mi.sizePointer(v, opts) 793*1c12ee1eSDan Willemsen } 794*1c12ee1eSDan Willemsen return n 795*1c12ee1eSDan Willemsen} 796*1c12ee1eSDan Willemsen 797*1c12ee1eSDan Willemsenfunc appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 798*1c12ee1eSDan Willemsen s := p.PointerSlice() 799*1c12ee1eSDan Willemsen var err error 800*1c12ee1eSDan Willemsen for _, v := range s { 801*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, f.wiretag) // start group 802*1c12ee1eSDan Willemsen b, err = f.mi.marshalAppendPointer(b, v, opts) 803*1c12ee1eSDan Willemsen if err != nil { 804*1c12ee1eSDan Willemsen return b, err 805*1c12ee1eSDan Willemsen } 806*1c12ee1eSDan Willemsen b = protowire.AppendVarint(b, f.wiretag+1) // end group 807*1c12ee1eSDan Willemsen } 808*1c12ee1eSDan Willemsen return b, nil 809*1c12ee1eSDan Willemsen} 810*1c12ee1eSDan Willemsen 811*1c12ee1eSDan Willemsenfunc consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 812*1c12ee1eSDan Willemsen if wtyp != protowire.StartGroupType { 813*1c12ee1eSDan Willemsen return unmarshalOutput{}, errUnknown 814*1c12ee1eSDan Willemsen } 815*1c12ee1eSDan Willemsen m := reflect.New(f.mi.GoReflectType.Elem()).Interface() 816*1c12ee1eSDan Willemsen mp := pointerOfIface(m) 817*1c12ee1eSDan Willemsen out, err := f.mi.unmarshalPointer(b, mp, f.num, opts) 818*1c12ee1eSDan Willemsen if err != nil { 819*1c12ee1eSDan Willemsen return out, err 820*1c12ee1eSDan Willemsen } 821*1c12ee1eSDan Willemsen p.AppendPointerSlice(mp) 822*1c12ee1eSDan Willemsen return out, nil 823*1c12ee1eSDan Willemsen} 824*1c12ee1eSDan Willemsen 825*1c12ee1eSDan Willemsenfunc asMessage(v reflect.Value) protoreflect.ProtoMessage { 826*1c12ee1eSDan Willemsen if m, ok := v.Interface().(protoreflect.ProtoMessage); ok { 827*1c12ee1eSDan Willemsen return m 828*1c12ee1eSDan Willemsen } 829*1c12ee1eSDan Willemsen return legacyWrapMessage(v).Interface() 830*1c12ee1eSDan Willemsen} 831