extension.go (4721B)
1 // Copyright 2019 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 "sync" 10 "sync/atomic" 11 12 "google.golang.org/protobuf/reflect/protoreflect" 13 "google.golang.org/protobuf/runtime/protoiface" 14 ) 15 16 // ExtensionInfo implements ExtensionType. 17 // 18 // This type contains a number of exported fields for legacy compatibility. 19 // The only non-deprecated use of this type is through the methods of the 20 // ExtensionType interface. 21 type ExtensionInfo struct { 22 // An ExtensionInfo may exist in several stages of initialization. 23 // 24 // extensionInfoUninitialized: Some or all of the legacy exported 25 // fields may be set, but none of the unexported fields have been 26 // initialized. This is the starting state for an ExtensionInfo 27 // in legacy generated code. 28 // 29 // extensionInfoDescInit: The desc field is set, but other unexported fields 30 // may not be initialized. Legacy exported fields may or may not be set. 31 // This is the starting state for an ExtensionInfo in newly generated code. 32 // 33 // extensionInfoFullInit: The ExtensionInfo is fully initialized. 34 // This state is only entered after lazy initialization is complete. 35 init uint32 36 mu sync.Mutex 37 38 goType reflect.Type 39 desc extensionTypeDescriptor 40 conv Converter 41 info *extensionFieldInfo // for fast-path method implementations 42 43 // ExtendedType is a typed nil-pointer to the parent message type that 44 // is being extended. It is possible for this to be unpopulated in v2 45 // since the message may no longer implement the MessageV1 interface. 46 // 47 // Deprecated: Use the ExtendedType method instead. 48 ExtendedType protoiface.MessageV1 49 50 // ExtensionType is the zero value of the extension type. 51 // 52 // For historical reasons, reflect.TypeOf(ExtensionType) and the 53 // type returned by InterfaceOf may not be identical. 54 // 55 // Deprecated: Use InterfaceOf(xt.Zero()) instead. 56 ExtensionType interface{} 57 58 // Field is the field number of the extension. 59 // 60 // Deprecated: Use the Descriptor().Number method instead. 61 Field int32 62 63 // Name is the fully qualified name of extension. 64 // 65 // Deprecated: Use the Descriptor().FullName method instead. 66 Name string 67 68 // Tag is the protobuf struct tag used in the v1 API. 69 // 70 // Deprecated: Do not use. 71 Tag string 72 73 // Filename is the proto filename in which the extension is defined. 74 // 75 // Deprecated: Use Descriptor().ParentFile().Path() instead. 76 Filename string 77 } 78 79 // Stages of initialization: See the ExtensionInfo.init field. 80 const ( 81 extensionInfoUninitialized = 0 82 extensionInfoDescInit = 1 83 extensionInfoFullInit = 2 84 ) 85 86 func InitExtensionInfo(xi *ExtensionInfo, xd protoreflect.ExtensionDescriptor, goType reflect.Type) { 87 xi.goType = goType 88 xi.desc = extensionTypeDescriptor{xd, xi} 89 xi.init = extensionInfoDescInit 90 } 91 92 func (xi *ExtensionInfo) New() protoreflect.Value { 93 return xi.lazyInit().New() 94 } 95 func (xi *ExtensionInfo) Zero() protoreflect.Value { 96 return xi.lazyInit().Zero() 97 } 98 func (xi *ExtensionInfo) ValueOf(v interface{}) protoreflect.Value { 99 return xi.lazyInit().PBValueOf(reflect.ValueOf(v)) 100 } 101 func (xi *ExtensionInfo) InterfaceOf(v protoreflect.Value) interface{} { 102 return xi.lazyInit().GoValueOf(v).Interface() 103 } 104 func (xi *ExtensionInfo) IsValidValue(v protoreflect.Value) bool { 105 return xi.lazyInit().IsValidPB(v) 106 } 107 func (xi *ExtensionInfo) IsValidInterface(v interface{}) bool { 108 return xi.lazyInit().IsValidGo(reflect.ValueOf(v)) 109 } 110 func (xi *ExtensionInfo) TypeDescriptor() protoreflect.ExtensionTypeDescriptor { 111 if atomic.LoadUint32(&xi.init) < extensionInfoDescInit { 112 xi.lazyInitSlow() 113 } 114 return &xi.desc 115 } 116 117 func (xi *ExtensionInfo) lazyInit() Converter { 118 if atomic.LoadUint32(&xi.init) < extensionInfoFullInit { 119 xi.lazyInitSlow() 120 } 121 return xi.conv 122 } 123 124 func (xi *ExtensionInfo) lazyInitSlow() { 125 xi.mu.Lock() 126 defer xi.mu.Unlock() 127 128 if xi.init == extensionInfoFullInit { 129 return 130 } 131 defer atomic.StoreUint32(&xi.init, extensionInfoFullInit) 132 133 if xi.desc.ExtensionDescriptor == nil { 134 xi.initFromLegacy() 135 } 136 if !xi.desc.ExtensionDescriptor.IsPlaceholder() { 137 if xi.ExtensionType == nil { 138 xi.initToLegacy() 139 } 140 xi.conv = NewConverter(xi.goType, xi.desc.ExtensionDescriptor) 141 xi.info = makeExtensionFieldInfo(xi.desc.ExtensionDescriptor) 142 xi.info.validation = newValidationInfo(xi.desc.ExtensionDescriptor, xi.goType) 143 } 144 } 145 146 type extensionTypeDescriptor struct { 147 protoreflect.ExtensionDescriptor 148 xi *ExtensionInfo 149 } 150 151 func (xtd *extensionTypeDescriptor) Type() protoreflect.ExtensionType { 152 return xtd.xi 153 } 154 func (xtd *extensionTypeDescriptor) Descriptor() protoreflect.ExtensionDescriptor { 155 return xtd.ExtensionDescriptor 156 }