|
|
@@ -12,7 +12,6 @@ import (
|
|
|
"sync"
|
|
|
|
|
|
"google.golang.org/protobuf/internal/descfmt"
|
|
|
- "google.golang.org/protobuf/internal/value"
|
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
|
)
|
|
|
|
|
|
@@ -109,250 +108,7 @@ func (t *Message) Format(s fmt.State, r rune) {
|
|
|
descfmt.FormatDesc(s, r, t)
|
|
|
}
|
|
|
|
|
|
-// Extension is a protoreflect.ExtensionType which combines a
|
|
|
-// protoreflect.ExtensionDescriptor with a constructor function.
|
|
|
-//
|
|
|
-// ExtensionDescriptor must be populated, while NewEnum or NewMessage must
|
|
|
-// populated depending on the kind of the extension field.
|
|
|
-// Once constructed, the exported fields must not be modified.
|
|
|
-type Extension struct {
|
|
|
- protoreflect.ExtensionDescriptor
|
|
|
-
|
|
|
- // NewEnum constructs a new enum (see Enum.NewEnum).
|
|
|
- // This must be populated if and only if ExtensionDescriptor.Kind
|
|
|
- // is a protoreflect.EnumKind.
|
|
|
- NewEnum func(protoreflect.EnumNumber) protoreflect.Enum
|
|
|
-
|
|
|
- // NewMessage constructs a new message (see Enum.NewMessage).
|
|
|
- // This must be populated if and only if ExtensionDescriptor.Kind
|
|
|
- // is a protoreflect.MessageKind or protoreflect.GroupKind.
|
|
|
- NewMessage func() protoreflect.Message
|
|
|
-
|
|
|
- // TODO: Allow users to manually set new, valueOf, and interfaceOf.
|
|
|
- // This allows users to implement custom composite types (e.g., List) or
|
|
|
- // custom Go types for primitives (e.g., int32).
|
|
|
-
|
|
|
- once sync.Once
|
|
|
- goType reflect.Type
|
|
|
- new func() protoreflect.Value
|
|
|
- valueOf func(v interface{}) protoreflect.Value
|
|
|
- interfaceOf func(v protoreflect.Value) interface{}
|
|
|
-}
|
|
|
-
|
|
|
-func (t *Extension) New() protoreflect.Value {
|
|
|
- t.lazyInit()
|
|
|
- pv := t.new()
|
|
|
- v := t.interfaceOf(pv)
|
|
|
- if reflect.TypeOf(v) != t.goType {
|
|
|
- panic(fmt.Sprintf("invalid type: got %T, want %v", v, t.goType))
|
|
|
- }
|
|
|
- return pv
|
|
|
-}
|
|
|
-
|
|
|
-func (t *Extension) ValueOf(v interface{}) protoreflect.Value {
|
|
|
- t.lazyInit()
|
|
|
- if reflect.TypeOf(v) != t.goType {
|
|
|
- panic(fmt.Sprintf("invalid type: got %T, want %v", v, t.goType))
|
|
|
- }
|
|
|
- return t.valueOf(v)
|
|
|
-}
|
|
|
-
|
|
|
-func (t *Extension) InterfaceOf(v protoreflect.Value) interface{} {
|
|
|
- t.lazyInit()
|
|
|
- vi := t.interfaceOf(v)
|
|
|
- if reflect.TypeOf(vi) != t.goType {
|
|
|
- panic(fmt.Sprintf("invalid type: got %T, want %v", vi, t.goType))
|
|
|
- }
|
|
|
- return vi
|
|
|
-}
|
|
|
-
|
|
|
-// GoType is the type of the extension field.
|
|
|
-// The type is T for scalars and *[]T for lists (maps are not allowed).
|
|
|
-// The type T is determined as follows:
|
|
|
-//
|
|
|
-// +------------+-------------------------------------+
|
|
|
-// | Go type | Protobuf kind |
|
|
|
-// +------------+-------------------------------------+
|
|
|
-// | bool | BoolKind |
|
|
|
-// | int32 | Int32Kind, Sint32Kind, Sfixed32Kind |
|
|
|
-// | int64 | Int64Kind, Sint64Kind, Sfixed64Kind |
|
|
|
-// | uint32 | Uint32Kind, Fixed32Kind |
|
|
|
-// | uint64 | Uint64Kind, Fixed64Kind |
|
|
|
-// | float32 | FloatKind |
|
|
|
-// | float64 | DoubleKind |
|
|
|
-// | string | StringKind |
|
|
|
-// | []byte | BytesKind |
|
|
|
-// | E | EnumKind |
|
|
|
-// | M | MessageKind, GroupKind |
|
|
|
-// +------------+-------------------------------------+
|
|
|
-//
|
|
|
-// The type E is the concrete enum type returned by NewEnum,
|
|
|
-// which is often, but not required to be, a named int32 type.
|
|
|
-// The type M is the concrete message type returned by NewMessage,
|
|
|
-// which is often, but not required to be, a pointer to a named struct type.
|
|
|
-func (t *Extension) GoType() reflect.Type {
|
|
|
- t.lazyInit()
|
|
|
- return t.goType
|
|
|
-}
|
|
|
-
|
|
|
-func (t *Extension) Descriptor() protoreflect.ExtensionDescriptor {
|
|
|
- return t.ExtensionDescriptor
|
|
|
-}
|
|
|
-
|
|
|
-func (t *Extension) Format(s fmt.State, r rune) {
|
|
|
- descfmt.FormatDesc(s, r, t)
|
|
|
-}
|
|
|
-
|
|
|
-func (t *Extension) lazyInit() {
|
|
|
- t.once.Do(func() {
|
|
|
- switch t.Kind() {
|
|
|
- case protoreflect.EnumKind:
|
|
|
- if t.NewEnum == nil || t.NewMessage != nil {
|
|
|
- panic("NewEnum alone must be set")
|
|
|
- }
|
|
|
- e := t.NewEnum(0)
|
|
|
- if e.Descriptor() != t.Enum() {
|
|
|
- panic(fmt.Sprintf("mismatching enum descriptor: got %v, want %v", e.Descriptor(), t.Enum()))
|
|
|
- }
|
|
|
- t.goType = reflect.TypeOf(e)
|
|
|
- case protoreflect.MessageKind, protoreflect.GroupKind:
|
|
|
- if t.NewEnum != nil || t.NewMessage == nil {
|
|
|
- panic("NewMessage alone must be set")
|
|
|
- }
|
|
|
- m := t.NewMessage()
|
|
|
- if m.Descriptor() != t.Message() {
|
|
|
- panic(fmt.Sprintf("mismatching message descriptor: got %v, want %v", m.Descriptor(), t.Message()))
|
|
|
- }
|
|
|
- t.goType = reflect.TypeOf(m.Interface())
|
|
|
- default:
|
|
|
- if t.NewEnum != nil || t.NewMessage != nil {
|
|
|
- panic("neither NewEnum nor NewMessage may be set")
|
|
|
- }
|
|
|
- t.goType = goTypeForPBKind[t.Kind()]
|
|
|
- }
|
|
|
-
|
|
|
- switch t.Cardinality() {
|
|
|
- case protoreflect.Optional:
|
|
|
- switch t.Kind() {
|
|
|
- case protoreflect.EnumKind:
|
|
|
- t.new = func() protoreflect.Value {
|
|
|
- return t.Default()
|
|
|
- }
|
|
|
- t.valueOf = func(v interface{}) protoreflect.Value {
|
|
|
- ev := v.(protoreflect.Enum)
|
|
|
- return protoreflect.ValueOf(ev.Number())
|
|
|
- }
|
|
|
- t.interfaceOf = func(v protoreflect.Value) interface{} {
|
|
|
- return t.NewEnum(v.Enum())
|
|
|
- }
|
|
|
- case protoreflect.MessageKind, protoreflect.GroupKind:
|
|
|
- t.new = func() protoreflect.Value {
|
|
|
- return protoreflect.ValueOf(t.NewMessage())
|
|
|
- }
|
|
|
- t.valueOf = func(v interface{}) protoreflect.Value {
|
|
|
- mv := v.(protoreflect.ProtoMessage).ProtoReflect()
|
|
|
- return protoreflect.ValueOf(mv)
|
|
|
- }
|
|
|
- t.interfaceOf = func(v protoreflect.Value) interface{} {
|
|
|
- return v.Message().Interface()
|
|
|
- }
|
|
|
- default:
|
|
|
- t.new = func() protoreflect.Value {
|
|
|
- v := t.Default()
|
|
|
- if t.Kind() == protoreflect.BytesKind {
|
|
|
- // Copy default bytes to avoid aliasing the original.
|
|
|
- v = protoreflect.ValueOf(append([]byte(nil), v.Bytes()...))
|
|
|
- }
|
|
|
- return v
|
|
|
- }
|
|
|
- t.valueOf = func(v interface{}) protoreflect.Value {
|
|
|
- return protoreflect.ValueOf(v)
|
|
|
- }
|
|
|
- t.interfaceOf = func(v protoreflect.Value) interface{} {
|
|
|
- return v.Interface()
|
|
|
- }
|
|
|
- }
|
|
|
- case protoreflect.Repeated:
|
|
|
- var conv value.Converter
|
|
|
- elemType := t.goType
|
|
|
- switch t.Kind() {
|
|
|
- case protoreflect.EnumKind:
|
|
|
- conv = value.Converter{
|
|
|
- PBValueOf: func(v reflect.Value) protoreflect.Value {
|
|
|
- if v.Type() != elemType {
|
|
|
- panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), elemType))
|
|
|
- }
|
|
|
- e := v.Interface().(protoreflect.Enum)
|
|
|
- return protoreflect.ValueOf(e.Number())
|
|
|
- },
|
|
|
- GoValueOf: func(v protoreflect.Value) reflect.Value {
|
|
|
- rv := reflect.ValueOf(t.NewEnum(v.Enum()))
|
|
|
- if rv.Type() != elemType {
|
|
|
- panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), elemType))
|
|
|
- }
|
|
|
- return rv
|
|
|
- },
|
|
|
- NewEnum: t.NewEnum,
|
|
|
- }
|
|
|
- case protoreflect.MessageKind, protoreflect.GroupKind:
|
|
|
- conv = value.Converter{
|
|
|
- PBValueOf: func(v reflect.Value) protoreflect.Value {
|
|
|
- if v.Type() != elemType {
|
|
|
- panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), elemType))
|
|
|
- }
|
|
|
- m := v.Interface().(protoreflect.ProtoMessage).ProtoReflect()
|
|
|
- return protoreflect.ValueOf(m)
|
|
|
- },
|
|
|
- GoValueOf: func(v protoreflect.Value) reflect.Value {
|
|
|
- rv := reflect.ValueOf(v.Message().Interface())
|
|
|
- if rv.Type() != elemType {
|
|
|
- panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), elemType))
|
|
|
- }
|
|
|
- return rv
|
|
|
- },
|
|
|
- NewMessage: t.NewMessage,
|
|
|
- }
|
|
|
- default:
|
|
|
- conv = value.NewConverter(elemType, t.Kind())
|
|
|
- }
|
|
|
-
|
|
|
- t.goType = reflect.PtrTo(reflect.SliceOf(elemType))
|
|
|
- t.new = func() protoreflect.Value {
|
|
|
- v := reflect.New(t.goType.Elem()).Interface()
|
|
|
- return protoreflect.ValueOf(value.ListOf(v, conv))
|
|
|
- }
|
|
|
- t.valueOf = func(v interface{}) protoreflect.Value {
|
|
|
- return protoreflect.ValueOf(value.ListOf(v, conv))
|
|
|
- }
|
|
|
- t.interfaceOf = func(v protoreflect.Value) interface{} {
|
|
|
- return v.List().(value.Unwrapper).ProtoUnwrap()
|
|
|
- }
|
|
|
- default:
|
|
|
- panic(fmt.Sprintf("invalid cardinality: %v", t.Cardinality()))
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-var goTypeForPBKind = map[protoreflect.Kind]reflect.Type{
|
|
|
- protoreflect.BoolKind: reflect.TypeOf(bool(false)),
|
|
|
- protoreflect.Int32Kind: reflect.TypeOf(int32(0)),
|
|
|
- protoreflect.Sint32Kind: reflect.TypeOf(int32(0)),
|
|
|
- protoreflect.Sfixed32Kind: reflect.TypeOf(int32(0)),
|
|
|
- protoreflect.Int64Kind: reflect.TypeOf(int64(0)),
|
|
|
- protoreflect.Sint64Kind: reflect.TypeOf(int64(0)),
|
|
|
- protoreflect.Sfixed64Kind: reflect.TypeOf(int64(0)),
|
|
|
- protoreflect.Uint32Kind: reflect.TypeOf(uint32(0)),
|
|
|
- protoreflect.Fixed32Kind: reflect.TypeOf(uint32(0)),
|
|
|
- protoreflect.Uint64Kind: reflect.TypeOf(uint64(0)),
|
|
|
- protoreflect.Fixed64Kind: reflect.TypeOf(uint64(0)),
|
|
|
- protoreflect.FloatKind: reflect.TypeOf(float32(0)),
|
|
|
- protoreflect.DoubleKind: reflect.TypeOf(float64(0)),
|
|
|
- protoreflect.StringKind: reflect.TypeOf(string("")),
|
|
|
- protoreflect.BytesKind: reflect.TypeOf([]byte(nil)),
|
|
|
-}
|
|
|
-
|
|
|
var (
|
|
|
- _ protoreflect.EnumType = (*Enum)(nil)
|
|
|
- _ protoreflect.MessageType = (*Message)(nil)
|
|
|
- _ protoreflect.ExtensionType = (*Extension)(nil)
|
|
|
+ _ protoreflect.EnumType = (*Enum)(nil)
|
|
|
+ _ protoreflect.MessageType = (*Message)(nil)
|
|
|
)
|