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