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 )
b , err := f .mi .marshalAppendPointer (b , p .AtomicGetPointer (), opts )
b = protowire .AppendVarint (b , f .wiretag +1 )
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 ()
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 )
b , err = f .mi .marshalAppendPointer (b , v , opts )
if err != nil {
return b , err
}
b = protowire .AppendVarint (b , f .wiretag +1 )
}
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
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .