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