blob: ba9be0d5ce95391defb44e12d5a2f9b54b134a04 [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 Tsaif18ab532018-11-27 17:25:04 -080028var (
Joe Tsai4fddeba2019-03-20 18:29:32 -070029 extTypeA = reflect.TypeOf(map[int32]ExtensionFieldV1(nil))
30 extTypeB = reflect.TypeOf(ExtensionFieldsV1{})
Joe Tsaif18ab532018-11-27 17:25:04 -080031)
32
Joe Tsai4fddeba2019-03-20 18:29:32 -070033func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) legacyExtensionFieldsIface {
Joe Tsaif18ab532018-11-27 17:25:04 -080034 fx1, _ := t.FieldByName("XXX_extensions")
35 fx2, _ := t.FieldByName("XXX_InternalExtensions")
36 switch {
37 case fx1.Type == extTypeA:
38 fieldOffset := offsetOf(fx1)
Joe Tsai4fddeba2019-03-20 18:29:32 -070039 return func(p *messageDataType) legacyExtensionFieldsIface {
Joe Tsai6cf80c42018-12-01 04:57:09 -080040 v := p.p.Apply(fieldOffset).AsValueOf(fx1.Type).Interface()
Joe Tsai4fddeba2019-03-20 18:29:32 -070041 return Export{}.ExtensionFieldsOf(v)
Joe Tsaif18ab532018-11-27 17:25:04 -080042 }
43 case fx2.Type == extTypeB:
44 fieldOffset := offsetOf(fx2)
Joe Tsai4fddeba2019-03-20 18:29:32 -070045 return func(p *messageDataType) legacyExtensionFieldsIface {
Joe Tsai6cf80c42018-12-01 04:57:09 -080046 v := p.p.Apply(fieldOffset).AsValueOf(fx2.Type).Interface()
Joe Tsai4fddeba2019-03-20 18:29:32 -070047 return Export{}.ExtensionFieldsOf(v)
Joe Tsaif18ab532018-11-27 17:25:04 -080048 }
49 default:
50 return nil
51 }
52}
53
Joe Tsaif0c01e42018-11-06 13:05:20 -080054type legacyExtensionFields struct {
55 mi *MessageType
Joe Tsai4fddeba2019-03-20 18:29:32 -070056 x legacyExtensionFieldsIface
Joe Tsaif0c01e42018-11-06 13:05:20 -080057}
58
59func (p legacyExtensionFields) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -070060 p.x.Range(func(num pref.FieldNumber, _ ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -080061 if p.Has(pref.FieldNumber(num)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -080062 n++
63 }
64 return true
65 })
66 return n
67}
68
69func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
70 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080071 if x.Value == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080072 return false
73 }
Damien Neil4866b952019-03-13 17:36:42 -070074 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -080075 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -080076 return t.ValueOf(x.Value).List().Len() > 0
Joe Tsaif0c01e42018-11-06 13:05:20 -080077 }
78 return true
79}
80
81func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
82 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080083 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080084 return pref.Value{}
85 }
Damien Neil4866b952019-03-13 17:36:42 -070086 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -080087 if x.Value == nil {
88 // NOTE: x.Value is never nil for Lists since they are always populated
Joe Tsaif6d4a422018-11-19 14:26:06 -080089 // during ExtensionFieldTypes.Register.
Joe Tsaif0c01e42018-11-06 13:05:20 -080090 if t.Kind() == pref.MessageKind || t.Kind() == pref.GroupKind {
Joe Tsaif0c01e42018-11-06 13:05:20 -080091 return pref.Value{}
92 }
93 return t.Default()
94 }
Joe Tsaif18ab532018-11-27 17:25:04 -080095 return t.ValueOf(x.Value)
Joe Tsaif0c01e42018-11-06 13:05:20 -080096}
97
98func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
99 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800100 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800101 panic("no extension descriptor registered")
102 }
Damien Neil4866b952019-03-13 17:36:42 -0700103 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -0800104 x.Value = t.InterfaceOf(v)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800105 p.x.Set(n, x)
106}
107
108func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
109 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800110 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800111 return
112 }
Damien Neil4866b952019-03-13 17:36:42 -0700113 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800114 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -0800115 t.ValueOf(x.Value).List().Truncate(0)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800116 return
117 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800118 x.Value = nil
Joe Tsaif0c01e42018-11-06 13:05:20 -0800119 p.x.Set(n, x)
120}
121
Joe Tsai4ec39c72019-04-03 13:40:53 -0700122func (p legacyExtensionFields) WhichOneof(pref.Name) pref.FieldNumber {
123 return 0
124}
125
Joe Tsaif0c01e42018-11-06 13:05:20 -0800126func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700127 p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800128 if p.Has(n) {
129 return f(n, p.Get(n))
130 }
131 return true
132 })
133}
134
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800135func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
Damien Neil97e7f572018-12-07 14:28:33 -0800136 x := p.x.Get(n)
137 if x.Desc == nil {
138 panic("no extension descriptor registered")
139 }
Damien Neil4866b952019-03-13 17:36:42 -0700140 xt := extensionTypeFromDesc(x.Desc)
Joe Tsaid18bd312019-01-09 03:23:55 -0800141 return xt.New().Message()
Damien Neil97e7f572018-12-07 14:28:33 -0800142}
143
Joe Tsaif0c01e42018-11-06 13:05:20 -0800144func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
145 return legacyExtensionTypes(p)
146}
147
148type legacyExtensionTypes legacyExtensionFields
149
150func (p legacyExtensionTypes) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700151 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800152 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800153 n++
154 }
155 return true
156 })
157 return n
158}
159
160func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
Damien Neil8012b442019-01-18 09:32:24 -0800161 if p.mi.PBType.FullName() != t.ExtendedType().FullName() {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800162 panic("extended type mismatch")
163 }
Damien Neil8012b442019-01-18 09:32:24 -0800164 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800165 panic("invalid extension field number")
166 }
167 x := p.x.Get(t.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800168 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800169 panic("extension descriptor already registered")
170 }
Joe Tsaiafb455e2019-03-14 16:08:22 -0700171 x.Desc = extensionDescFromType(t)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800172 if t.Cardinality() == pref.Repeated {
173 // If the field is repeated, initialize the entry with an empty list
174 // so that future Get operations can return a mutable and concrete list.
Joe Tsaid18bd312019-01-09 03:23:55 -0800175 x.Value = t.InterfaceOf(t.New())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800176 }
Joe Tsaif0c01e42018-11-06 13:05:20 -0800177 p.x.Set(t.Number(), x)
178}
179
180func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
Damien Neil8012b442019-01-18 09:32:24 -0800181 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800182 return
183 }
184 x := p.x.Get(t.Number())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800185 if t.Cardinality() == pref.Repeated {
186 // Treat an empty repeated field as unpopulated.
Joe Tsaif18ab532018-11-27 17:25:04 -0800187 v := reflect.ValueOf(x.Value)
188 if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
189 x.Value = nil
Joe Tsaif6d4a422018-11-19 14:26:06 -0800190 }
191 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800192 if x.Value != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800193 panic("value for extension descriptor still populated")
194 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800195 x.Desc = nil
196 if len(x.Raw) == 0 {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800197 p.x.Clear(t.Number())
198 } else {
199 p.x.Set(t.Number(), x)
200 }
201}
202
203func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
204 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800205 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700206 return extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800207 }
208 return nil
209}
210
211func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700212 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800213 if x.Desc != nil && x.Desc.Name == string(s) {
Damien Neil4866b952019-03-13 17:36:42 -0700214 t = extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800215 return false
216 }
217 return true
218 })
219 return t
220}
221
222func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700223 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800224 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700225 if !f(extensionTypeFromDesc(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800226 return false
227 }
228 }
229 return true
230 })
231}
Damien Neil4866b952019-03-13 17:36:42 -0700232
Joe Tsai4fddeba2019-03-20 18:29:32 -0700233func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
234 if xt, ok := typ.(interface {
235 ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
236 }); ok {
Joe Tsaiafb455e2019-03-14 16:08:22 -0700237 if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
238 return desc
239 }
240 }
241 return legacyWrapper.ExtensionDescFromType(typ)
242}
243
Joe Tsai4fddeba2019-03-20 18:29:32 -0700244func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
Damien Neil4866b952019-03-13 17:36:42 -0700245 if desc.Type != nil {
246 return desc.Type
247 }
248 return legacyWrapper.ExtensionTypeFromDesc(desc)
249}
Joe Tsai4fddeba2019-03-20 18:29:32 -0700250
251type legacyExtensionFieldsIface = interface {
252 Len() int
253 Has(pref.FieldNumber) bool
254 Get(pref.FieldNumber) ExtensionFieldV1
255 Set(pref.FieldNumber, ExtensionFieldV1)
256 Clear(pref.FieldNumber)
257 Range(f func(pref.FieldNumber, ExtensionFieldV1) bool)
258
259 // HasInit and Locker are used by v1 GetExtension to provide
260 // an artificial degree of concurrent safety.
261 HasInit() bool
262 sync.Locker
263}
264
265type ExtensionFieldV1 struct {
266 // TODO: Unexport these fields when v1 no longer interacts with the
267 // extension data structures directly.
268
269 // When an extension is stored in a message using SetExtension
270 // only desc and value are set. When the message is marshaled
271 // Raw will be set to the encoded form of the message.
272 //
273 // When a message is unmarshaled and contains extensions, each
274 // extension will have only Raw set. When such an extension is
275 // accessed using GetExtension (or GetExtensions) desc and value
276 // will be set.
277 Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
278
279 // Value is a concrete value for the extension field. Let the type of
280 // Desc.ExtensionType be the "API type" and the type of Value be the
281 // "storage type". The API type and storage type are the same except:
282 // * for scalars (except []byte), where the API type uses *T,
283 // while the storage type uses T.
284 // * for repeated fields, where the API type uses []T,
285 // while the storage type uses *[]T.
286 //
287 // The reason for the divergence is so that the storage type more naturally
288 // matches what is expected of when retrieving the values through the
289 // protobuf reflection APIs.
290 //
291 // The Value may only be populated if Desc is also populated.
292 Value interface{} // TODO: switch to protoreflect.Value
293
294 // Raw is the raw encoded bytes for the extension field.
295 // It is possible for Raw to be populated irrespective of whether the
296 // other fields are populated.
297 Raw []byte // TODO: switch to protoreflect.RawFields
298}
299
300type ExtensionFieldsV1 legacyExtensionSyncMap
301type legacyExtensionSyncMap struct {
302 p *struct {
303 mu sync.Mutex
304 m legacyExtensionMap
305 }
306}
307
308func (m legacyExtensionSyncMap) Len() int {
309 if m.p == nil {
310 return 0
311 }
312 return m.p.m.Len()
313}
314func (m legacyExtensionSyncMap) Has(n pref.FieldNumber) bool {
315 if m.p == nil {
316 return false
317 }
318 return m.p.m.Has(n)
319}
320func (m legacyExtensionSyncMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
321 if m.p == nil {
322 return ExtensionFieldV1{}
323 }
324 return m.p.m.Get(n)
325}
326func (m *legacyExtensionSyncMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
327 if m.p == nil {
328 m.p = new(struct {
329 mu sync.Mutex
330 m legacyExtensionMap
331 })
332 }
333 m.p.m.Set(n, x)
334}
335func (m legacyExtensionSyncMap) Clear(n pref.FieldNumber) {
336 if m.p == nil {
337 return
338 }
339 m.p.m.Clear(n)
340}
341func (m legacyExtensionSyncMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
342 if m.p == nil {
343 return
344 }
345 m.p.m.Range(f)
346}
347
348func (m legacyExtensionSyncMap) HasInit() bool {
349 return m.p != nil
350}
351func (m legacyExtensionSyncMap) Lock() {
352 m.p.mu.Lock()
353}
354func (m legacyExtensionSyncMap) Unlock() {
355 m.p.mu.Unlock()
356}
357
358type legacyExtensionMap map[int32]ExtensionFieldV1
359
360func (m legacyExtensionMap) Len() int {
361 return len(m)
362}
363func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
364 _, ok := m[int32(n)]
365 return ok
366}
367func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
368 return m[int32(n)]
369}
370func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
371 if *m == nil {
372 *m = make(map[int32]ExtensionFieldV1)
373 }
374 (*m)[int32(n)] = x
375}
376func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
377 delete(*m, int32(n))
378}
379func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
380 for n, x := range m {
381 if !f(pref.FieldNumber(n), x) {
382 return
383 }
384 }
385}
386
387var legacyExtensionLock sync.Mutex
388
389func (m legacyExtensionMap) HasInit() bool {
390 return m != nil
391}
392func (m legacyExtensionMap) Lock() {
393 if !m.HasInit() {
394 panic("cannot lock an uninitialized map")
395 }
396 legacyExtensionLock.Lock()
397}
398func (m legacyExtensionMap) Unlock() {
399 legacyExtensionLock.Unlock()
400}