vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go
changeset 256 6d9efbef00a9
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
       
     1 // Copyright 2018 The Go Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style
       
     3 // license that can be found in the LICENSE file.
       
     4 
       
     5 package impl
       
     6 
       
     7 import (
       
     8 	"reflect"
       
     9 
       
    10 	"google.golang.org/protobuf/internal/descopts"
       
    11 	"google.golang.org/protobuf/internal/encoding/messageset"
       
    12 	ptag "google.golang.org/protobuf/internal/encoding/tag"
       
    13 	"google.golang.org/protobuf/internal/filedesc"
       
    14 	"google.golang.org/protobuf/internal/pragma"
       
    15 	pref "google.golang.org/protobuf/reflect/protoreflect"
       
    16 	preg "google.golang.org/protobuf/reflect/protoregistry"
       
    17 	piface "google.golang.org/protobuf/runtime/protoiface"
       
    18 )
       
    19 
       
    20 func (xi *ExtensionInfo) initToLegacy() {
       
    21 	xd := xi.desc
       
    22 	var parent piface.MessageV1
       
    23 	messageName := xd.ContainingMessage().FullName()
       
    24 	if mt, _ := preg.GlobalTypes.FindMessageByName(messageName); mt != nil {
       
    25 		// Create a new parent message and unwrap it if possible.
       
    26 		mv := mt.New().Interface()
       
    27 		t := reflect.TypeOf(mv)
       
    28 		if mv, ok := mv.(unwrapper); ok {
       
    29 			t = reflect.TypeOf(mv.protoUnwrap())
       
    30 		}
       
    31 
       
    32 		// Check whether the message implements the legacy v1 Message interface.
       
    33 		mz := reflect.Zero(t).Interface()
       
    34 		if mz, ok := mz.(piface.MessageV1); ok {
       
    35 			parent = mz
       
    36 		}
       
    37 	}
       
    38 
       
    39 	// Determine the v1 extension type, which is unfortunately not the same as
       
    40 	// the v2 ExtensionType.GoType.
       
    41 	extType := xi.goType
       
    42 	switch extType.Kind() {
       
    43 	case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
       
    44 		extType = reflect.PtrTo(extType) // T -> *T for singular scalar fields
       
    45 	}
       
    46 
       
    47 	// Reconstruct the legacy enum full name.
       
    48 	var enumName string
       
    49 	if xd.Kind() == pref.EnumKind {
       
    50 		enumName = legacyEnumName(xd.Enum())
       
    51 	}
       
    52 
       
    53 	// Derive the proto file that the extension was declared within.
       
    54 	var filename string
       
    55 	if fd := xd.ParentFile(); fd != nil {
       
    56 		filename = fd.Path()
       
    57 	}
       
    58 
       
    59 	// For MessageSet extensions, the name used is the parent message.
       
    60 	name := xd.FullName()
       
    61 	if messageset.IsMessageSetExtension(xd) {
       
    62 		name = name.Parent()
       
    63 	}
       
    64 
       
    65 	xi.ExtendedType = parent
       
    66 	xi.ExtensionType = reflect.Zero(extType).Interface()
       
    67 	xi.Field = int32(xd.Number())
       
    68 	xi.Name = string(name)
       
    69 	xi.Tag = ptag.Marshal(xd, enumName)
       
    70 	xi.Filename = filename
       
    71 }
       
    72 
       
    73 // initFromLegacy initializes an ExtensionInfo from
       
    74 // the contents of the deprecated exported fields of the type.
       
    75 func (xi *ExtensionInfo) initFromLegacy() {
       
    76 	// The v1 API returns "type incomplete" descriptors where only the
       
    77 	// field number is specified. In such a case, use a placeholder.
       
    78 	if xi.ExtendedType == nil || xi.ExtensionType == nil {
       
    79 		xd := placeholderExtension{
       
    80 			name:   pref.FullName(xi.Name),
       
    81 			number: pref.FieldNumber(xi.Field),
       
    82 		}
       
    83 		xi.desc = extensionTypeDescriptor{xd, xi}
       
    84 		return
       
    85 	}
       
    86 
       
    87 	// Resolve enum or message dependencies.
       
    88 	var ed pref.EnumDescriptor
       
    89 	var md pref.MessageDescriptor
       
    90 	t := reflect.TypeOf(xi.ExtensionType)
       
    91 	isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct
       
    92 	isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
       
    93 	if isOptional || isRepeated {
       
    94 		t = t.Elem()
       
    95 	}
       
    96 	switch v := reflect.Zero(t).Interface().(type) {
       
    97 	case pref.Enum:
       
    98 		ed = v.Descriptor()
       
    99 	case enumV1:
       
   100 		ed = LegacyLoadEnumDesc(t)
       
   101 	case pref.ProtoMessage:
       
   102 		md = v.ProtoReflect().Descriptor()
       
   103 	case messageV1:
       
   104 		md = LegacyLoadMessageDesc(t)
       
   105 	}
       
   106 
       
   107 	// Derive basic field information from the struct tag.
       
   108 	var evs pref.EnumValueDescriptors
       
   109 	if ed != nil {
       
   110 		evs = ed.Values()
       
   111 	}
       
   112 	fd := ptag.Unmarshal(xi.Tag, t, evs).(*filedesc.Field)
       
   113 
       
   114 	// Construct a v2 ExtensionType.
       
   115 	xd := &filedesc.Extension{L2: new(filedesc.ExtensionL2)}
       
   116 	xd.L0.ParentFile = filedesc.SurrogateProto2
       
   117 	xd.L0.FullName = pref.FullName(xi.Name)
       
   118 	xd.L1.Number = pref.FieldNumber(xi.Field)
       
   119 	xd.L1.Cardinality = fd.L1.Cardinality
       
   120 	xd.L1.Kind = fd.L1.Kind
       
   121 	xd.L2.IsPacked = fd.L1.IsPacked
       
   122 	xd.L2.Default = fd.L1.Default
       
   123 	xd.L1.Extendee = Export{}.MessageDescriptorOf(xi.ExtendedType)
       
   124 	xd.L2.Enum = ed
       
   125 	xd.L2.Message = md
       
   126 
       
   127 	// Derive real extension field name for MessageSets.
       
   128 	if messageset.IsMessageSet(xd.L1.Extendee) && md.FullName() == xd.L0.FullName {
       
   129 		xd.L0.FullName = xd.L0.FullName.Append(messageset.ExtensionName)
       
   130 	}
       
   131 
       
   132 	tt := reflect.TypeOf(xi.ExtensionType)
       
   133 	if isOptional {
       
   134 		tt = tt.Elem()
       
   135 	}
       
   136 	xi.goType = tt
       
   137 	xi.desc = extensionTypeDescriptor{xd, xi}
       
   138 }
       
   139 
       
   140 type placeholderExtension struct {
       
   141 	name   pref.FullName
       
   142 	number pref.FieldNumber
       
   143 }
       
   144 
       
   145 func (x placeholderExtension) ParentFile() pref.FileDescriptor            { return nil }
       
   146 func (x placeholderExtension) Parent() pref.Descriptor                    { return nil }
       
   147 func (x placeholderExtension) Index() int                                 { return 0 }
       
   148 func (x placeholderExtension) Syntax() pref.Syntax                        { return 0 }
       
   149 func (x placeholderExtension) Name() pref.Name                            { return x.name.Name() }
       
   150 func (x placeholderExtension) FullName() pref.FullName                    { return x.name }
       
   151 func (x placeholderExtension) IsPlaceholder() bool                        { return true }
       
   152 func (x placeholderExtension) Options() pref.ProtoMessage                 { return descopts.Field }
       
   153 func (x placeholderExtension) Number() pref.FieldNumber                   { return x.number }
       
   154 func (x placeholderExtension) Cardinality() pref.Cardinality              { return 0 }
       
   155 func (x placeholderExtension) Kind() pref.Kind                            { return 0 }
       
   156 func (x placeholderExtension) HasJSONName() bool                          { return false }
       
   157 func (x placeholderExtension) JSONName() string                           { return "[" + string(x.name) + "]" }
       
   158 func (x placeholderExtension) TextName() string                           { return "[" + string(x.name) + "]" }
       
   159 func (x placeholderExtension) HasPresence() bool                          { return false }
       
   160 func (x placeholderExtension) HasOptionalKeyword() bool                   { return false }
       
   161 func (x placeholderExtension) IsExtension() bool                          { return true }
       
   162 func (x placeholderExtension) IsWeak() bool                               { return false }
       
   163 func (x placeholderExtension) IsPacked() bool                             { return false }
       
   164 func (x placeholderExtension) IsList() bool                               { return false }
       
   165 func (x placeholderExtension) IsMap() bool                                { return false }
       
   166 func (x placeholderExtension) MapKey() pref.FieldDescriptor               { return nil }
       
   167 func (x placeholderExtension) MapValue() pref.FieldDescriptor             { return nil }
       
   168 func (x placeholderExtension) HasDefault() bool                           { return false }
       
   169 func (x placeholderExtension) Default() pref.Value                        { return pref.Value{} }
       
   170 func (x placeholderExtension) DefaultEnumValue() pref.EnumValueDescriptor { return nil }
       
   171 func (x placeholderExtension) ContainingOneof() pref.OneofDescriptor      { return nil }
       
   172 func (x placeholderExtension) ContainingMessage() pref.MessageDescriptor  { return nil }
       
   173 func (x placeholderExtension) Enum() pref.EnumDescriptor                  { return nil }
       
   174 func (x placeholderExtension) Message() pref.MessageDescriptor            { return nil }
       
   175 func (x placeholderExtension) ProtoType(pref.FieldDescriptor)             { return }
       
   176 func (x placeholderExtension) ProtoInternal(pragma.DoNotImplement)        { return }