...

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

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

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

View as plain text