package impl
import (
"fmt"
"reflect"
"sort"
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/internal/order"
"google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
)
func (mi *MessageInfo ) makeOpaqueCoderMethods (t reflect .Type , si opaqueStructInfo ) {
mi .sizecacheOffset = si .sizecacheOffset
mi .unknownOffset = si .unknownOffset
mi .unknownPtrKind = si .unknownType .Kind () == reflect .Ptr
mi .extensionOffset = si .extensionOffset
mi .lazyOffset = si .lazyOffset
mi .presenceOffset = si .presenceOffset
mi .coderFields = make (map [protowire .Number ]*coderFieldInfo )
fields := mi .Desc .Fields ()
for i := 0 ; i < fields .Len (); i ++ {
fd := fields .Get (i )
fs := si .fieldsByNumber [fd .Number ()]
if fd .ContainingOneof () != nil && !fd .ContainingOneof ().IsSynthetic () {
fs = si .oneofsByName [fd .ContainingOneof ().Name ()]
}
ft := fs .Type
var wiretag uint64
if !fd .IsPacked () {
wiretag = protowire .EncodeTag (fd .Number (), wireTypes [fd .Kind ()])
} else {
wiretag = protowire .EncodeTag (fd .Number (), protowire .BytesType )
}
var fieldOffset offset
var funcs pointerCoderFuncs
var childMessage *MessageInfo
switch {
case fd .ContainingOneof () != nil && !fd .ContainingOneof ().IsSynthetic ():
fieldOffset = offsetOf (fs )
case fd .Message () != nil && !fd .IsMap ():
fieldOffset = offsetOf (fs )
if fd .IsList () {
childMessage , funcs = makeOpaqueRepeatedMessageFieldCoder (fd , ft )
} else {
childMessage , funcs = makeOpaqueMessageFieldCoder (fd , ft )
}
default :
fieldOffset = offsetOf (fs )
childMessage , funcs = fieldCoder (fd , ft )
}
cf := &coderFieldInfo {
num : fd .Number (),
offset : fieldOffset ,
wiretag : wiretag ,
ft : ft ,
tagsize : protowire .SizeVarint (wiretag ),
funcs : funcs ,
mi : childMessage ,
validation : newFieldValidationInfo (mi , si .structInfo , fd , ft ),
isPointer : (fd .Cardinality () == protoreflect .Repeated ||
fd .Kind () == protoreflect .MessageKind ||
fd .Kind () == protoreflect .GroupKind ),
isRequired : fd .Cardinality () == protoreflect .Required ,
presenceIndex : noPresence ,
}
var hasPresence bool
hasPresence , cf .isLazy = filedesc .UsePresenceForField (fd )
if hasPresence {
cf .presenceIndex , mi .presenceSize = presenceIndex (mi .Desc , fd )
}
mi .orderedCoderFields = append (mi .orderedCoderFields , cf )
mi .coderFields [cf .num ] = cf
}
for i , oneofs := 0 , mi .Desc .Oneofs (); i < oneofs .Len (); i ++ {
if od := oneofs .Get (i ); !od .IsSynthetic () {
mi .initOneofFieldCoders (od , si .structInfo )
}
}
if messageset .IsMessageSet (mi .Desc ) {
if !mi .extensionOffset .IsValid () {
panic (fmt .Sprintf ("%v: MessageSet with no extensions field" , mi .Desc .FullName ()))
}
if !mi .unknownOffset .IsValid () {
panic (fmt .Sprintf ("%v: MessageSet with no unknown field" , mi .Desc .FullName ()))
}
mi .isMessageSet = true
}
sort .Slice (mi .orderedCoderFields , func (i , j int ) bool {
return mi .orderedCoderFields [i ].num < mi .orderedCoderFields [j ].num
})
var maxDense protoreflect .FieldNumber
for _ , cf := range mi .orderedCoderFields {
if cf .num >= 16 && cf .num >= 2 *maxDense {
break
}
maxDense = cf .num
}
mi .denseCoderFields = make ([]*coderFieldInfo , maxDense +1 )
for _ , cf := range mi .orderedCoderFields {
if int (cf .num ) > len (mi .denseCoderFields ) {
break
}
mi .denseCoderFields [cf .num ] = cf
}
if mi .Desc .Oneofs ().Len () > 0 {
sort .Slice (mi .orderedCoderFields , func (i , j int ) bool {
fi := fields .ByNumber (mi .orderedCoderFields [i ].num )
fj := fields .ByNumber (mi .orderedCoderFields [j ].num )
return order .LegacyFieldOrder (fi , fj )
})
}
mi .needsInitCheck = needsInitCheck (mi .Desc )
if mi .methods .Marshal == nil && mi .methods .Size == nil {
mi .methods .Flags |= piface .SupportMarshalDeterministic
mi .methods .Marshal = mi .marshal
mi .methods .Size = mi .size
}
if mi .methods .Unmarshal == nil {
mi .methods .Flags |= piface .SupportUnmarshalDiscardUnknown
mi .methods .Unmarshal = mi .unmarshal
}
if mi .methods .CheckInitialized == nil {
mi .methods .CheckInitialized = mi .checkInitialized
}
if mi .methods .Merge == nil {
mi .methods .Merge = mi .merge
}
if mi .methods .Equal == nil {
mi .methods .Equal = equal
}
}
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 .