legacy_extension.go (7691B)
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 "google.golang.org/protobuf/reflect/protoreflect" 16 "google.golang.org/protobuf/reflect/protoregistry" 17 "google.golang.org/protobuf/runtime/protoiface" 18 ) 19 20 func (xi *ExtensionInfo) initToLegacy() { 21 xd := xi.desc 22 var parent protoiface.MessageV1 23 messageName := xd.ContainingMessage().FullName() 24 if mt, _ := protoregistry.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.(protoiface.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() == protoreflect.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: protoreflect.FullName(xi.Name), 81 number: protoreflect.FieldNumber(xi.Field), 82 } 83 xi.desc = extensionTypeDescriptor{xd, xi} 84 return 85 } 86 87 // Resolve enum or message dependencies. 88 var ed protoreflect.EnumDescriptor 89 var md protoreflect.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 protoreflect.Enum: 98 ed = v.Descriptor() 99 case enumV1: 100 ed = LegacyLoadEnumDesc(t) 101 case protoreflect.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 protoreflect.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 = protoreflect.FullName(xi.Name) 118 xd.L1.Number = protoreflect.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 protoreflect.FullName 142 number protoreflect.FieldNumber 143 } 144 145 func (x placeholderExtension) ParentFile() protoreflect.FileDescriptor { return nil } 146 func (x placeholderExtension) Parent() protoreflect.Descriptor { return nil } 147 func (x placeholderExtension) Index() int { return 0 } 148 func (x placeholderExtension) Syntax() protoreflect.Syntax { return 0 } 149 func (x placeholderExtension) Name() protoreflect.Name { return x.name.Name() } 150 func (x placeholderExtension) FullName() protoreflect.FullName { return x.name } 151 func (x placeholderExtension) IsPlaceholder() bool { return true } 152 func (x placeholderExtension) Options() protoreflect.ProtoMessage { return descopts.Field } 153 func (x placeholderExtension) Number() protoreflect.FieldNumber { return x.number } 154 func (x placeholderExtension) Cardinality() protoreflect.Cardinality { return 0 } 155 func (x placeholderExtension) Kind() protoreflect.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() protoreflect.FieldDescriptor { return nil } 167 func (x placeholderExtension) MapValue() protoreflect.FieldDescriptor { return nil } 168 func (x placeholderExtension) HasDefault() bool { return false } 169 func (x placeholderExtension) Default() protoreflect.Value { return protoreflect.Value{} } 170 func (x placeholderExtension) DefaultEnumValue() protoreflect.EnumValueDescriptor { return nil } 171 func (x placeholderExtension) ContainingOneof() protoreflect.OneofDescriptor { return nil } 172 func (x placeholderExtension) ContainingMessage() protoreflect.MessageDescriptor { return nil } 173 func (x placeholderExtension) Enum() protoreflect.EnumDescriptor { return nil } 174 func (x placeholderExtension) Message() protoreflect.MessageDescriptor { return nil } 175 func (x placeholderExtension) ProtoType(protoreflect.FieldDescriptor) { return } 176 func (x placeholderExtension) ProtoInternal(pragma.DoNotImplement) { return }