...

Source file src/google.golang.org/protobuf/internal/impl/legacy_extension.go

Documentation: google.golang.org/protobuf/internal/impl

     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 }
   177  

View as plain text