123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- // Copyright 2024 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package impl
- import (
- "fmt"
- "reflect"
- "google.golang.org/protobuf/encoding/protowire"
- "google.golang.org/protobuf/internal/errors"
- "google.golang.org/protobuf/reflect/protoreflect"
- )
- func makeOpaqueMessageFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) (*MessageInfo, pointerCoderFuncs) {
- mi := getMessageInfo(ft)
- if mi == nil {
- panic(fmt.Sprintf("invalid field: %v: unsupported message type %v", fd.FullName(), ft))
- }
- switch fd.Kind() {
- case protoreflect.MessageKind:
- return mi, pointerCoderFuncs{
- size: sizeOpaqueMessage,
- marshal: appendOpaqueMessage,
- unmarshal: consumeOpaqueMessage,
- isInit: isInitOpaqueMessage,
- merge: mergeOpaqueMessage,
- }
- case protoreflect.GroupKind:
- return mi, pointerCoderFuncs{
- size: sizeOpaqueGroup,
- marshal: appendOpaqueGroup,
- unmarshal: consumeOpaqueGroup,
- isInit: isInitOpaqueMessage,
- merge: mergeOpaqueMessage,
- }
- }
- panic("unexpected field kind")
- }
- func sizeOpaqueMessage(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
- return protowire.SizeBytes(f.mi.sizePointer(p.AtomicGetPointer(), opts)) + f.tagsize
- }
- func appendOpaqueMessage(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
- mp := p.AtomicGetPointer()
- calculatedSize := f.mi.sizePointer(mp, opts)
- b = protowire.AppendVarint(b, f.wiretag)
- b = protowire.AppendVarint(b, uint64(calculatedSize))
- before := len(b)
- b, err := f.mi.marshalAppendPointer(b, mp, opts)
- if measuredSize := len(b) - before; calculatedSize != measuredSize && err == nil {
- return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize)
- }
- return b, err
- }
- func consumeOpaqueMessage(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
- if wtyp != protowire.BytesType {
- return out, errUnknown
- }
- v, n := protowire.ConsumeBytes(b)
- if n < 0 {
- return out, errDecode
- }
- mp := p.AtomicGetPointer()
- if mp.IsNil() {
- mp = p.AtomicSetPointerIfNil(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
- }
- o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
- if err != nil {
- return out, err
- }
- out.n = n
- out.initialized = o.initialized
- return out, nil
- }
- func isInitOpaqueMessage(p pointer, f *coderFieldInfo) error {
- mp := p.AtomicGetPointer()
- if mp.IsNil() {
- return nil
- }
- return f.mi.checkInitializedPointer(mp)
- }
- func mergeOpaqueMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
- dstmp := dst.AtomicGetPointer()
- if dstmp.IsNil() {
- dstmp = dst.AtomicSetPointerIfNil(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
- }
- f.mi.mergePointer(dstmp, src.AtomicGetPointer(), opts)
- }
- func sizeOpaqueGroup(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
- return 2*f.tagsize + f.mi.sizePointer(p.AtomicGetPointer(), opts)
- }
- func appendOpaqueGroup(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
- b = protowire.AppendVarint(b, f.wiretag) // start group
- b, err := f.mi.marshalAppendPointer(b, p.AtomicGetPointer(), opts)
- b = protowire.AppendVarint(b, f.wiretag+1) // end group
- return b, err
- }
- func consumeOpaqueGroup(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
- if wtyp != protowire.StartGroupType {
- return out, errUnknown
- }
- mp := p.AtomicGetPointer()
- if mp.IsNil() {
- mp = p.AtomicSetPointerIfNil(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
- }
- o, e := f.mi.unmarshalPointer(b, mp, f.num, opts)
- return o, e
- }
- func makeOpaqueRepeatedMessageFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) (*MessageInfo, pointerCoderFuncs) {
- if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
- panic(fmt.Sprintf("invalid field: %v: unsupported type for opaque repeated message: %v", fd.FullName(), ft))
- }
- mt := ft.Elem().Elem() // *[]*T -> *T
- mi := getMessageInfo(mt)
- if mi == nil {
- panic(fmt.Sprintf("invalid field: %v: unsupported message type %v", fd.FullName(), mt))
- }
- switch fd.Kind() {
- case protoreflect.MessageKind:
- return mi, pointerCoderFuncs{
- size: sizeOpaqueMessageSlice,
- marshal: appendOpaqueMessageSlice,
- unmarshal: consumeOpaqueMessageSlice,
- isInit: isInitOpaqueMessageSlice,
- merge: mergeOpaqueMessageSlice,
- }
- case protoreflect.GroupKind:
- return mi, pointerCoderFuncs{
- size: sizeOpaqueGroupSlice,
- marshal: appendOpaqueGroupSlice,
- unmarshal: consumeOpaqueGroupSlice,
- isInit: isInitOpaqueMessageSlice,
- merge: mergeOpaqueMessageSlice,
- }
- }
- panic("unexpected field kind")
- }
- func sizeOpaqueMessageSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
- s := p.AtomicGetPointer().PointerSlice()
- n := 0
- for _, v := range s {
- n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize
- }
- return n
- }
- func appendOpaqueMessageSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
- s := p.AtomicGetPointer().PointerSlice()
- var err error
- for _, v := range s {
- b = protowire.AppendVarint(b, f.wiretag)
- siz := f.mi.sizePointer(v, opts)
- b = protowire.AppendVarint(b, uint64(siz))
- before := len(b)
- b, err = f.mi.marshalAppendPointer(b, v, opts)
- if err != nil {
- return b, err
- }
- if measuredSize := len(b) - before; siz != measuredSize {
- return nil, errors.MismatchedSizeCalculation(siz, measuredSize)
- }
- }
- return b, nil
- }
- func consumeOpaqueMessageSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
- if wtyp != protowire.BytesType {
- return out, errUnknown
- }
- v, n := protowire.ConsumeBytes(b)
- if n < 0 {
- return out, errDecode
- }
- mp := pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))
- o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
- if err != nil {
- return out, err
- }
- sp := p.AtomicGetPointer()
- if sp.IsNil() {
- sp = p.AtomicSetPointerIfNil(pointerOfValue(reflect.New(f.ft.Elem())))
- }
- sp.AppendPointerSlice(mp)
- out.n = n
- out.initialized = o.initialized
- return out, nil
- }
- func isInitOpaqueMessageSlice(p pointer, f *coderFieldInfo) error {
- sp := p.AtomicGetPointer()
- if sp.IsNil() {
- return nil
- }
- s := sp.PointerSlice()
- for _, v := range s {
- if err := f.mi.checkInitializedPointer(v); err != nil {
- return err
- }
- }
- return nil
- }
- func mergeOpaqueMessageSlice(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
- ds := dst.AtomicGetPointer()
- if ds.IsNil() {
- ds = dst.AtomicSetPointerIfNil(pointerOfValue(reflect.New(f.ft.Elem())))
- }
- for _, sp := range src.AtomicGetPointer().PointerSlice() {
- dm := pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))
- f.mi.mergePointer(dm, sp, opts)
- ds.AppendPointerSlice(dm)
- }
- }
- func sizeOpaqueGroupSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
- s := p.AtomicGetPointer().PointerSlice()
- n := 0
- for _, v := range s {
- n += 2*f.tagsize + f.mi.sizePointer(v, opts)
- }
- return n
- }
- func appendOpaqueGroupSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
- s := p.AtomicGetPointer().PointerSlice()
- var err error
- for _, v := range s {
- b = protowire.AppendVarint(b, f.wiretag) // start group
- b, err = f.mi.marshalAppendPointer(b, v, opts)
- if err != nil {
- return b, err
- }
- b = protowire.AppendVarint(b, f.wiretag+1) // end group
- }
- return b, nil
- }
- func consumeOpaqueGroupSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
- if wtyp != protowire.StartGroupType {
- return out, errUnknown
- }
- mp := pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))
- out, err = f.mi.unmarshalPointer(b, mp, f.num, opts)
- if err != nil {
- return out, err
- }
- sp := p.AtomicGetPointer()
- if sp.IsNil() {
- sp = p.AtomicSetPointerIfNil(pointerOfValue(reflect.New(f.ft.Elem())))
- }
- sp.AppendPointerSlice(mp)
- return out, err
- }
|