blob: 424ee3f2868d55edfa7136e86668187567024ee9 [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 Tsaif0c01e42018-11-06 13:05:20 -0800122func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700123 p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800124 if p.Has(n) {
125 return f(n, p.Get(n))
126 }
127 return true
128 })
129}
130
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800131func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
Damien Neil97e7f572018-12-07 14:28:33 -0800132 x := p.x.Get(n)
133 if x.Desc == nil {
134 panic("no extension descriptor registered")
135 }
Damien Neil4866b952019-03-13 17:36:42 -0700136 xt := extensionTypeFromDesc(x.Desc)
Joe Tsaid18bd312019-01-09 03:23:55 -0800137 return xt.New().Message()
Damien Neil97e7f572018-12-07 14:28:33 -0800138}
139
Joe Tsaif0c01e42018-11-06 13:05:20 -0800140func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
141 return legacyExtensionTypes(p)
142}
143
144type legacyExtensionTypes legacyExtensionFields
145
146func (p legacyExtensionTypes) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700147 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800148 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800149 n++
150 }
151 return true
152 })
153 return n
154}
155
156func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
Damien Neil8012b442019-01-18 09:32:24 -0800157 if p.mi.PBType.FullName() != t.ExtendedType().FullName() {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800158 panic("extended type mismatch")
159 }
Damien Neil8012b442019-01-18 09:32:24 -0800160 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800161 panic("invalid extension field number")
162 }
163 x := p.x.Get(t.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800164 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800165 panic("extension descriptor already registered")
166 }
Joe Tsaiafb455e2019-03-14 16:08:22 -0700167 x.Desc = extensionDescFromType(t)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800168 if t.Cardinality() == pref.Repeated {
169 // If the field is repeated, initialize the entry with an empty list
170 // so that future Get operations can return a mutable and concrete list.
Joe Tsaid18bd312019-01-09 03:23:55 -0800171 x.Value = t.InterfaceOf(t.New())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800172 }
Joe Tsaif0c01e42018-11-06 13:05:20 -0800173 p.x.Set(t.Number(), x)
174}
175
176func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
Damien Neil8012b442019-01-18 09:32:24 -0800177 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800178 return
179 }
180 x := p.x.Get(t.Number())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800181 if t.Cardinality() == pref.Repeated {
182 // Treat an empty repeated field as unpopulated.
Joe Tsaif18ab532018-11-27 17:25:04 -0800183 v := reflect.ValueOf(x.Value)
184 if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
185 x.Value = nil
Joe Tsaif6d4a422018-11-19 14:26:06 -0800186 }
187 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800188 if x.Value != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800189 panic("value for extension descriptor still populated")
190 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800191 x.Desc = nil
192 if len(x.Raw) == 0 {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800193 p.x.Clear(t.Number())
194 } else {
195 p.x.Set(t.Number(), x)
196 }
197}
198
199func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
200 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800201 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700202 return extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800203 }
204 return nil
205}
206
207func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700208 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800209 if x.Desc != nil && x.Desc.Name == string(s) {
Damien Neil4866b952019-03-13 17:36:42 -0700210 t = extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800211 return false
212 }
213 return true
214 })
215 return t
216}
217
218func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700219 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800220 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700221 if !f(extensionTypeFromDesc(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800222 return false
223 }
224 }
225 return true
226 })
227}
Damien Neil4866b952019-03-13 17:36:42 -0700228
Joe Tsai4fddeba2019-03-20 18:29:32 -0700229func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
230 if xt, ok := typ.(interface {
231 ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
232 }); ok {
Joe Tsaiafb455e2019-03-14 16:08:22 -0700233 if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
234 return desc
235 }
236 }
237 return legacyWrapper.ExtensionDescFromType(typ)
238}
239
Joe Tsai4fddeba2019-03-20 18:29:32 -0700240func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
Damien Neil4866b952019-03-13 17:36:42 -0700241 if desc.Type != nil {
242 return desc.Type
243 }
244 return legacyWrapper.ExtensionTypeFromDesc(desc)
245}
Joe Tsai4fddeba2019-03-20 18:29:32 -0700246
247type legacyExtensionFieldsIface = interface {
248 Len() int
249 Has(pref.FieldNumber) bool
250 Get(pref.FieldNumber) ExtensionFieldV1
251 Set(pref.FieldNumber, ExtensionFieldV1)
252 Clear(pref.FieldNumber)
253 Range(f func(pref.FieldNumber, ExtensionFieldV1) bool)
254
255 // HasInit and Locker are used by v1 GetExtension to provide
256 // an artificial degree of concurrent safety.
257 HasInit() bool
258 sync.Locker
259}
260
261type ExtensionFieldV1 struct {
262 // TODO: Unexport these fields when v1 no longer interacts with the
263 // extension data structures directly.
264
265 // When an extension is stored in a message using SetExtension
266 // only desc and value are set. When the message is marshaled
267 // Raw will be set to the encoded form of the message.
268 //
269 // When a message is unmarshaled and contains extensions, each
270 // extension will have only Raw set. When such an extension is
271 // accessed using GetExtension (or GetExtensions) desc and value
272 // will be set.
273 Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
274
275 // Value is a concrete value for the extension field. Let the type of
276 // Desc.ExtensionType be the "API type" and the type of Value be the
277 // "storage type". The API type and storage type are the same except:
278 // * for scalars (except []byte), where the API type uses *T,
279 // while the storage type uses T.
280 // * for repeated fields, where the API type uses []T,
281 // while the storage type uses *[]T.
282 //
283 // The reason for the divergence is so that the storage type more naturally
284 // matches what is expected of when retrieving the values through the
285 // protobuf reflection APIs.
286 //
287 // The Value may only be populated if Desc is also populated.
288 Value interface{} // TODO: switch to protoreflect.Value
289
290 // Raw is the raw encoded bytes for the extension field.
291 // It is possible for Raw to be populated irrespective of whether the
292 // other fields are populated.
293 Raw []byte // TODO: switch to protoreflect.RawFields
294}
295
296type ExtensionFieldsV1 legacyExtensionSyncMap
297type legacyExtensionSyncMap struct {
298 p *struct {
299 mu sync.Mutex
300 m legacyExtensionMap
301 }
302}
303
304func (m legacyExtensionSyncMap) Len() int {
305 if m.p == nil {
306 return 0
307 }
308 return m.p.m.Len()
309}
310func (m legacyExtensionSyncMap) Has(n pref.FieldNumber) bool {
311 if m.p == nil {
312 return false
313 }
314 return m.p.m.Has(n)
315}
316func (m legacyExtensionSyncMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
317 if m.p == nil {
318 return ExtensionFieldV1{}
319 }
320 return m.p.m.Get(n)
321}
322func (m *legacyExtensionSyncMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
323 if m.p == nil {
324 m.p = new(struct {
325 mu sync.Mutex
326 m legacyExtensionMap
327 })
328 }
329 m.p.m.Set(n, x)
330}
331func (m legacyExtensionSyncMap) Clear(n pref.FieldNumber) {
332 if m.p == nil {
333 return
334 }
335 m.p.m.Clear(n)
336}
337func (m legacyExtensionSyncMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
338 if m.p == nil {
339 return
340 }
341 m.p.m.Range(f)
342}
343
344func (m legacyExtensionSyncMap) HasInit() bool {
345 return m.p != nil
346}
347func (m legacyExtensionSyncMap) Lock() {
348 m.p.mu.Lock()
349}
350func (m legacyExtensionSyncMap) Unlock() {
351 m.p.mu.Unlock()
352}
353
354type legacyExtensionMap map[int32]ExtensionFieldV1
355
356func (m legacyExtensionMap) Len() int {
357 return len(m)
358}
359func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
360 _, ok := m[int32(n)]
361 return ok
362}
363func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
364 return m[int32(n)]
365}
366func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
367 if *m == nil {
368 *m = make(map[int32]ExtensionFieldV1)
369 }
370 (*m)[int32(n)] = x
371}
372func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
373 delete(*m, int32(n))
374}
375func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
376 for n, x := range m {
377 if !f(pref.FieldNumber(n), x) {
378 return
379 }
380 }
381}
382
383var legacyExtensionLock sync.Mutex
384
385func (m legacyExtensionMap) HasInit() bool {
386 return m != nil
387}
388func (m legacyExtensionMap) Lock() {
389 if !m.HasInit() {
390 panic("cannot lock an uninitialized map")
391 }
392 legacyExtensionLock.Lock()
393}
394func (m legacyExtensionMap) Unlock() {
395 legacyExtensionLock.Unlock()
396}