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