blob: 723bdb018ce645cdfa55c84bf151c95dc5812667 [file] [log] [blame]
Damien Neilf1e905b2019-08-08 15:45:59 -07001// 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
5package impl
6
7import (
8 "reflect"
9 "sync"
10 "sync/atomic"
11
12 pref "google.golang.org/protobuf/reflect/protoreflect"
13 piface "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.
21type 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 //
Joe Tsaifd4c6052019-09-16 13:30:15 -070029 // 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.
Damien Neilf1e905b2019-08-08 15:45:59 -070032 //
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
Damien Neilf1e905b2019-08-08 15:45:59 -070038 goType reflect.Type
Joe Tsaifd4c6052019-09-16 13:30:15 -070039 desc extensionTypeDescriptor
Damien Neilf1e905b2019-08-08 15:45:59 -070040 conv Converter
41
Damien Neilf1e905b2019-08-08 15:45:59 -070042 // ExtendedType is a typed nil-pointer to the parent message type that
43 // is being extended. It is possible for this to be unpopulated in v2
44 // since the message may no longer implement the MessageV1 interface.
45 //
46 // Deprecated: Use the ExtendedType method instead.
47 ExtendedType piface.MessageV1
48
49 // ExtensionType is zero value of the extension type.
50 //
51 // For historical reasons, reflect.TypeOf(ExtensionType) and Type.GoType
52 // may not be identical:
53 // * for scalars (except []byte), where ExtensionType uses *T,
54 // while Type.GoType uses T.
55 // * for repeated fields, where ExtensionType uses []T,
56 // while Type.GoType uses *[]T.
57 //
58 // Deprecated: Use the GoType method instead.
59 ExtensionType interface{}
60
61 // Field is the field number of the extension.
62 //
63 // Deprecated: Use the Descriptor().Number method instead.
64 Field int32
65
66 // Name is the fully qualified name of extension.
67 //
68 // Deprecated: Use the Descriptor().FullName method instead.
69 Name string
70
71 // Tag is the protobuf struct tag used in the v1 API.
72 //
73 // Deprecated: Do not use.
74 Tag string
75
76 // Filename is the proto filename in which the extension is defined.
77 //
78 // Deprecated: Use Descriptor().ParentFile().Path() instead.
79 Filename string
80}
81
82// Stages of initialization: See the ExtensionInfo.init field.
83const (
84 extensionInfoUninitialized = 0
85 extensionInfoDescInit = 1
86 extensionInfoFullInit = 2
87)
88
89func InitExtensionInfo(xi *ExtensionInfo, xd pref.ExtensionDescriptor, goType reflect.Type) {
Damien Neilf1e905b2019-08-08 15:45:59 -070090 xi.goType = goType
Joe Tsaifd4c6052019-09-16 13:30:15 -070091 xi.desc = extensionTypeDescriptor{xd, xi}
Damien Neilf1e905b2019-08-08 15:45:59 -070092 xi.init = extensionInfoDescInit
93}
94
95func (xi *ExtensionInfo) New() pref.Value {
96 return xi.lazyInit().New()
97}
98func (xi *ExtensionInfo) Zero() pref.Value {
99 return xi.lazyInit().Zero()
100}
101func (xi *ExtensionInfo) ValueOf(v interface{}) pref.Value {
102 return xi.lazyInit().PBValueOf(reflect.ValueOf(v))
103}
104func (xi *ExtensionInfo) InterfaceOf(v pref.Value) interface{} {
105 return xi.lazyInit().GoValueOf(v).Interface()
106}
Damien Neil835b2712019-08-29 14:08:28 -0700107func (xi *ExtensionInfo) IsValidValue(v pref.Value) bool {
108 return xi.lazyInit().IsValidPB(v)
109}
110func (xi *ExtensionInfo) IsValidInterface(v interface{}) bool {
111 return xi.lazyInit().IsValidGo(reflect.ValueOf(v))
112}
Damien Neilf1e905b2019-08-08 15:45:59 -0700113func (xi *ExtensionInfo) GoType() reflect.Type {
114 xi.lazyInit()
115 return xi.goType
116}
Damien Neil79bfdbe2019-08-28 11:08:22 -0700117func (xi *ExtensionInfo) TypeDescriptor() pref.ExtensionTypeDescriptor {
Joe Tsaifd4c6052019-09-16 13:30:15 -0700118 if atomic.LoadUint32(&xi.init) < extensionInfoDescInit {
Damien Neilf1e905b2019-08-08 15:45:59 -0700119 xi.lazyInitSlow()
120 }
Joe Tsaifd4c6052019-09-16 13:30:15 -0700121 return &xi.desc
Damien Neilf1e905b2019-08-08 15:45:59 -0700122}
123
124func (xi *ExtensionInfo) lazyInit() Converter {
Joe Tsaifd4c6052019-09-16 13:30:15 -0700125 if atomic.LoadUint32(&xi.init) < extensionInfoFullInit {
Damien Neilf1e905b2019-08-08 15:45:59 -0700126 xi.lazyInitSlow()
127 }
128 return xi.conv
129}
130
131func (xi *ExtensionInfo) lazyInitSlow() {
132 xi.mu.Lock()
133 defer xi.mu.Unlock()
134
135 if xi.init == extensionInfoFullInit {
136 return
137 }
Joe Tsai2df47c92019-09-09 16:52:28 -0700138 defer atomic.StoreUint32(&xi.init, extensionInfoFullInit)
Damien Neilf1e905b2019-08-08 15:45:59 -0700139
Joe Tsaifd4c6052019-09-16 13:30:15 -0700140 if xi.desc.ExtensionDescriptor == nil {
Damien Neilf1e905b2019-08-08 15:45:59 -0700141 xi.initFromLegacy()
Damien Neilf1e905b2019-08-08 15:45:59 -0700142 }
Joe Tsaibee62522019-09-05 17:25:15 -0700143 if !xi.desc.ExtensionDescriptor.IsPlaceholder() {
144 if xi.ExtensionType == nil {
145 xi.initToLegacy()
146 }
147 xi.conv = NewConverter(xi.goType, xi.desc)
Damien Neilf1e905b2019-08-08 15:45:59 -0700148 }
Damien Neilf1e905b2019-08-08 15:45:59 -0700149}
150
151type extensionTypeDescriptor struct {
152 pref.ExtensionDescriptor
153 xi *ExtensionInfo
154}
155
156func (xtd *extensionTypeDescriptor) Type() pref.ExtensionType {
157 return xtd.xi
158}
159func (xtd *extensionTypeDescriptor) Descriptor() pref.ExtensionDescriptor {
160 return xtd.ExtensionDescriptor
161}