blob: 16701b69d650ab4db2f7df0531575c78bc49df60 [file] [log] [blame]
Joe Tsaif0c01e42018-11-06 13:05:20 -08001// Copyright 2018 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 (
Joe Tsaif0c01e42018-11-06 13:05:20 -08008 "reflect"
Joe Tsai4fddeba2019-03-20 18:29:32 -07009 "sync"
Joe Tsaif0c01e42018-11-06 13:05:20 -080010
Joe Tsaif0c01e42018-11-06 13:05:20 -080011 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Joe Tsai4fddeba2019-03-20 18:29:32 -070012 piface "github.com/golang/protobuf/v2/runtime/protoiface"
Joe Tsaif0c01e42018-11-06 13:05:20 -080013)
14
15func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
16 f := makeLegacyExtensionMapFunc(t)
17 if f == nil {
18 return nil
19 }
20 return func(p *messageDataType) pref.KnownFields {
Joe Tsai6cf80c42018-12-01 04:57:09 -080021 if p.p.IsNil() {
22 return emptyExtensionFields{}
23 }
Joe Tsaif0c01e42018-11-06 13:05:20 -080024 return legacyExtensionFields{p.mi, f(p)}
25 }
26}
27
Joe Tsai50c16712019-04-16 01:18:50 -070028var extType = reflect.TypeOf(ExtensionFieldsV1{})
Joe Tsaif18ab532018-11-27 17:25:04 -080029
Joe Tsai50c16712019-04-16 01:18:50 -070030func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyExtensionMap {
31 fx, _ := t.FieldByName("XXX_extensions")
32 if fx.Type != extType {
33 fx, _ = t.FieldByName("XXX_InternalExtensions")
34 }
35 if fx.Type != extType {
Joe Tsaif18ab532018-11-27 17:25:04 -080036 return nil
37 }
Joe Tsai50c16712019-04-16 01:18:50 -070038
39 fieldOffset := offsetOf(fx)
40 return func(p *messageDataType) *legacyExtensionMap {
41 v := p.p.Apply(fieldOffset).AsValueOf(fx.Type).Interface()
42 return (*legacyExtensionMap)(v.(*ExtensionFieldsV1))
43 }
Joe Tsaif18ab532018-11-27 17:25:04 -080044}
45
Joe Tsaif0c01e42018-11-06 13:05:20 -080046type legacyExtensionFields struct {
47 mi *MessageType
Joe Tsai50c16712019-04-16 01:18:50 -070048 x *legacyExtensionMap
Joe Tsaif0c01e42018-11-06 13:05:20 -080049}
50
51func (p legacyExtensionFields) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -070052 p.x.Range(func(num pref.FieldNumber, _ ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -080053 if p.Has(pref.FieldNumber(num)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -080054 n++
55 }
56 return true
57 })
58 return n
59}
60
61func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
62 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080063 if x.Value == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080064 return false
65 }
Damien Neil4866b952019-03-13 17:36:42 -070066 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -080067 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -080068 return t.ValueOf(x.Value).List().Len() > 0
Joe Tsaif0c01e42018-11-06 13:05:20 -080069 }
70 return true
71}
72
73func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
74 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080075 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080076 return pref.Value{}
77 }
Damien Neil4866b952019-03-13 17:36:42 -070078 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -080079 if x.Value == nil {
80 // NOTE: x.Value is never nil for Lists since they are always populated
Joe Tsaif6d4a422018-11-19 14:26:06 -080081 // during ExtensionFieldTypes.Register.
Joe Tsaif0c01e42018-11-06 13:05:20 -080082 if t.Kind() == pref.MessageKind || t.Kind() == pref.GroupKind {
Joe Tsaif0c01e42018-11-06 13:05:20 -080083 return pref.Value{}
84 }
85 return t.Default()
86 }
Joe Tsaif18ab532018-11-27 17:25:04 -080087 return t.ValueOf(x.Value)
Joe Tsaif0c01e42018-11-06 13:05:20 -080088}
89
90func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
91 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080092 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080093 panic("no extension descriptor registered")
94 }
Damien Neil4866b952019-03-13 17:36:42 -070095 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -080096 x.Value = t.InterfaceOf(v)
Joe Tsaif0c01e42018-11-06 13:05:20 -080097 p.x.Set(n, x)
98}
99
100func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
101 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800102 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800103 return
104 }
Damien Neil4866b952019-03-13 17:36:42 -0700105 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800106 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -0800107 t.ValueOf(x.Value).List().Truncate(0)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800108 return
109 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800110 x.Value = nil
Joe Tsaif0c01e42018-11-06 13:05:20 -0800111 p.x.Set(n, x)
112}
113
Joe Tsai4ec39c72019-04-03 13:40:53 -0700114func (p legacyExtensionFields) WhichOneof(pref.Name) pref.FieldNumber {
115 return 0
116}
117
Joe Tsaif0c01e42018-11-06 13:05:20 -0800118func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700119 p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800120 if p.Has(n) {
121 return f(n, p.Get(n))
122 }
123 return true
124 })
125}
126
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800127func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
Damien Neil97e7f572018-12-07 14:28:33 -0800128 x := p.x.Get(n)
129 if x.Desc == nil {
130 panic("no extension descriptor registered")
131 }
Damien Neil4866b952019-03-13 17:36:42 -0700132 xt := extensionTypeFromDesc(x.Desc)
Joe Tsaid18bd312019-01-09 03:23:55 -0800133 return xt.New().Message()
Damien Neil97e7f572018-12-07 14:28:33 -0800134}
135
Joe Tsaif0c01e42018-11-06 13:05:20 -0800136func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
137 return legacyExtensionTypes(p)
138}
139
140type legacyExtensionTypes legacyExtensionFields
141
142func (p legacyExtensionTypes) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700143 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800144 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800145 n++
146 }
147 return true
148 })
149 return n
150}
151
152func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
Damien Neil8012b442019-01-18 09:32:24 -0800153 if p.mi.PBType.FullName() != t.ExtendedType().FullName() {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800154 panic("extended type mismatch")
155 }
Damien Neil8012b442019-01-18 09:32:24 -0800156 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800157 panic("invalid extension field number")
158 }
159 x := p.x.Get(t.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800160 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800161 panic("extension descriptor already registered")
162 }
Joe Tsaiafb455e2019-03-14 16:08:22 -0700163 x.Desc = extensionDescFromType(t)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800164 if t.Cardinality() == pref.Repeated {
165 // If the field is repeated, initialize the entry with an empty list
166 // so that future Get operations can return a mutable and concrete list.
Joe Tsaid18bd312019-01-09 03:23:55 -0800167 x.Value = t.InterfaceOf(t.New())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800168 }
Joe Tsaif0c01e42018-11-06 13:05:20 -0800169 p.x.Set(t.Number(), x)
170}
171
172func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
Damien Neil8012b442019-01-18 09:32:24 -0800173 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800174 return
175 }
176 x := p.x.Get(t.Number())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800177 if t.Cardinality() == pref.Repeated {
178 // Treat an empty repeated field as unpopulated.
Joe Tsaif18ab532018-11-27 17:25:04 -0800179 v := reflect.ValueOf(x.Value)
180 if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
181 x.Value = nil
Joe Tsaif6d4a422018-11-19 14:26:06 -0800182 }
183 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800184 if x.Value != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800185 panic("value for extension descriptor still populated")
186 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800187 x.Desc = nil
188 if len(x.Raw) == 0 {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800189 p.x.Clear(t.Number())
190 } else {
191 p.x.Set(t.Number(), x)
192 }
193}
194
195func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
196 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800197 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700198 return extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800199 }
200 return nil
201}
202
203func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700204 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800205 if x.Desc != nil && x.Desc.Name == string(s) {
Damien Neil4866b952019-03-13 17:36:42 -0700206 t = extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800207 return false
208 }
209 return true
210 })
211 return t
212}
213
214func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700215 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800216 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700217 if !f(extensionTypeFromDesc(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800218 return false
219 }
220 }
221 return true
222 })
223}
Damien Neil4866b952019-03-13 17:36:42 -0700224
Joe Tsai4fddeba2019-03-20 18:29:32 -0700225func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
226 if xt, ok := typ.(interface {
227 ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
228 }); ok {
Joe Tsaiafb455e2019-03-14 16:08:22 -0700229 if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
230 return desc
231 }
232 }
233 return legacyWrapper.ExtensionDescFromType(typ)
234}
235
Joe Tsai4fddeba2019-03-20 18:29:32 -0700236func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
Damien Neil4866b952019-03-13 17:36:42 -0700237 if desc.Type != nil {
238 return desc.Type
239 }
240 return legacyWrapper.ExtensionTypeFromDesc(desc)
241}
Joe Tsai4fddeba2019-03-20 18:29:32 -0700242
243type legacyExtensionFieldsIface = interface {
244 Len() int
245 Has(pref.FieldNumber) bool
246 Get(pref.FieldNumber) ExtensionFieldV1
247 Set(pref.FieldNumber, ExtensionFieldV1)
248 Clear(pref.FieldNumber)
249 Range(f func(pref.FieldNumber, ExtensionFieldV1) bool)
250
251 // HasInit and Locker are used by v1 GetExtension to provide
252 // an artificial degree of concurrent safety.
253 HasInit() bool
254 sync.Locker
255}
256
257type ExtensionFieldV1 struct {
Joe Tsai50c16712019-04-16 01:18:50 -0700258 // TODO: We should turn this into a type alias to an unnamed type,
259 // which means that v1 can have the same struct, and we no longer have to
260 // export this from the v2 API.
Joe Tsai4fddeba2019-03-20 18:29:32 -0700261
262 // When an extension is stored in a message using SetExtension
263 // only desc and value are set. When the message is marshaled
264 // Raw will be set to the encoded form of the message.
265 //
266 // When a message is unmarshaled and contains extensions, each
267 // extension will have only Raw set. When such an extension is
268 // accessed using GetExtension (or GetExtensions) desc and value
269 // will be set.
270 Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
271
272 // Value is a concrete value for the extension field. Let the type of
273 // Desc.ExtensionType be the "API type" and the type of Value be the
274 // "storage type". The API type and storage type are the same except:
275 // * for scalars (except []byte), where the API type uses *T,
276 // while the storage type uses T.
277 // * for repeated fields, where the API type uses []T,
278 // while the storage type uses *[]T.
279 //
280 // The reason for the divergence is so that the storage type more naturally
281 // matches what is expected of when retrieving the values through the
282 // protobuf reflection APIs.
283 //
284 // The Value may only be populated if Desc is also populated.
285 Value interface{} // TODO: switch to protoreflect.Value
286
287 // Raw is the raw encoded bytes for the extension field.
288 // It is possible for Raw to be populated irrespective of whether the
289 // other fields are populated.
Joe Tsai50c16712019-04-16 01:18:50 -0700290 Raw []byte // TODO: remove; let this be handled by XXX_unrecognized
Joe Tsai4fddeba2019-03-20 18:29:32 -0700291}
292
Joe Tsai50c16712019-04-16 01:18:50 -0700293type ExtensionFieldsV1 = map[int32]ExtensionFieldV1
Joe Tsai4fddeba2019-03-20 18:29:32 -0700294
Joe Tsai50c16712019-04-16 01:18:50 -0700295type legacyExtensionMap ExtensionFieldsV1
Joe Tsai4fddeba2019-03-20 18:29:32 -0700296
297func (m legacyExtensionMap) Len() int {
298 return len(m)
299}
300func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
301 _, ok := m[int32(n)]
302 return ok
303}
304func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
305 return m[int32(n)]
306}
307func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
308 if *m == nil {
309 *m = make(map[int32]ExtensionFieldV1)
310 }
311 (*m)[int32(n)] = x
312}
313func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
314 delete(*m, int32(n))
315}
316func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
317 for n, x := range m {
318 if !f(pref.FieldNumber(n), x) {
319 return
320 }
321 }
322}
323
Joe Tsai4fddeba2019-03-20 18:29:32 -0700324func (m legacyExtensionMap) HasInit() bool {
325 return m != nil
326}
Joe Tsai50c16712019-04-16 01:18:50 -0700327func (m legacyExtensionMap) Lock() {} // noop
328func (m legacyExtensionMap) Unlock() {} // noop