blob: f011192e8db2ae010aa08f401ca5b771b1ece040 [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 Tsai40b83d62019-05-16 11:45:52 -07009 "sync"
10 "sync/atomic"
Joe Tsaif0c01e42018-11-06 13:05:20 -080011
Damien Neile89e6242019-05-13 23:55:40 -070012 pref "google.golang.org/protobuf/reflect/protoreflect"
13 piface "google.golang.org/protobuf/runtime/protoiface"
Joe Tsaif0c01e42018-11-06 13:05:20 -080014)
15
16func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
17 f := makeLegacyExtensionMapFunc(t)
18 if f == nil {
19 return nil
20 }
21 return func(p *messageDataType) pref.KnownFields {
Joe Tsai6cf80c42018-12-01 04:57:09 -080022 if p.p.IsNil() {
23 return emptyExtensionFields{}
24 }
Joe Tsaif0c01e42018-11-06 13:05:20 -080025 return legacyExtensionFields{p.mi, f(p)}
26 }
27}
28
Joe Tsai00e50dc2019-04-16 12:39:41 -070029var extType = reflect.TypeOf(map[int32]ExtensionFieldV1{})
Joe Tsaif18ab532018-11-27 17:25:04 -080030
Joe Tsai50c16712019-04-16 01:18:50 -070031func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyExtensionMap {
32 fx, _ := t.FieldByName("XXX_extensions")
33 if fx.Type != extType {
34 fx, _ = t.FieldByName("XXX_InternalExtensions")
35 }
36 if fx.Type != extType {
Joe Tsaif18ab532018-11-27 17:25:04 -080037 return nil
38 }
Joe Tsai50c16712019-04-16 01:18:50 -070039
40 fieldOffset := offsetOf(fx)
41 return func(p *messageDataType) *legacyExtensionMap {
42 v := p.p.Apply(fieldOffset).AsValueOf(fx.Type).Interface()
Joe Tsai00e50dc2019-04-16 12:39:41 -070043 return (*legacyExtensionMap)(v.(*map[int32]ExtensionFieldV1))
Joe Tsai50c16712019-04-16 01:18:50 -070044 }
Joe Tsaif18ab532018-11-27 17:25:04 -080045}
46
Joe Tsaif0c01e42018-11-06 13:05:20 -080047type legacyExtensionFields struct {
48 mi *MessageType
Joe Tsai50c16712019-04-16 01:18:50 -070049 x *legacyExtensionMap
Joe Tsaif0c01e42018-11-06 13:05:20 -080050}
51
52func (p legacyExtensionFields) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -070053 p.x.Range(func(num pref.FieldNumber, _ ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -080054 if p.Has(pref.FieldNumber(num)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -080055 n++
56 }
57 return true
58 })
59 return n
60}
61
62func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
63 x := p.x.Get(n)
Joe Tsai40b83d62019-05-16 11:45:52 -070064 if !x.HasValue() {
Joe Tsaif0c01e42018-11-06 13:05:20 -080065 return false
66 }
Damien Neil4866b952019-03-13 17:36:42 -070067 t := extensionTypeFromDesc(x.Desc)
Joe Tsai0fc49f82019-05-01 12:29:25 -070068 d := t.Descriptor()
Joe Tsaiac31a352019-05-13 14:32:56 -070069 if d.IsList() {
Joe Tsai40b83d62019-05-16 11:45:52 -070070 return t.ValueOf(x.GetValue()).List().Len() > 0
Joe Tsaif0c01e42018-11-06 13:05:20 -080071 }
72 return true
73}
74
75func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
76 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080077 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080078 return pref.Value{}
79 }
Damien Neil4866b952019-03-13 17:36:42 -070080 t := extensionTypeFromDesc(x.Desc)
Joe Tsai0fc49f82019-05-01 12:29:25 -070081 d := t.Descriptor()
Joe Tsai40b83d62019-05-16 11:45:52 -070082 if !x.HasValue() {
Joe Tsaif18ab532018-11-27 17:25:04 -080083 // NOTE: x.Value is never nil for Lists since they are always populated
Joe Tsaif6d4a422018-11-19 14:26:06 -080084 // during ExtensionFieldTypes.Register.
Joe Tsai0fc49f82019-05-01 12:29:25 -070085 if d.Kind() == pref.MessageKind || d.Kind() == pref.GroupKind {
Joe Tsaif0c01e42018-11-06 13:05:20 -080086 return pref.Value{}
87 }
Joe Tsai0fc49f82019-05-01 12:29:25 -070088 return d.Default()
Joe Tsaif0c01e42018-11-06 13:05:20 -080089 }
Joe Tsai40b83d62019-05-16 11:45:52 -070090 return t.ValueOf(x.GetValue())
Joe Tsaif0c01e42018-11-06 13:05:20 -080091}
92
93func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
94 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080095 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080096 panic("no extension descriptor registered")
97 }
Damien Neil4866b952019-03-13 17:36:42 -070098 t := extensionTypeFromDesc(x.Desc)
Joe Tsai40b83d62019-05-16 11:45:52 -070099 x.SetEagerValue(t.InterfaceOf(v))
Joe Tsaif0c01e42018-11-06 13:05:20 -0800100 p.x.Set(n, x)
101}
102
103func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
104 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800105 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800106 return
107 }
Damien Neil4866b952019-03-13 17:36:42 -0700108 t := extensionTypeFromDesc(x.Desc)
Joe Tsai0fc49f82019-05-01 12:29:25 -0700109 d := t.Descriptor()
Joe Tsaiac31a352019-05-13 14:32:56 -0700110 if d.IsList() {
Joe Tsai40b83d62019-05-16 11:45:52 -0700111 t.ValueOf(x.GetValue()).List().Truncate(0)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800112 return
113 }
Joe Tsai40b83d62019-05-16 11:45:52 -0700114 x.SetEagerValue(nil)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800115 p.x.Set(n, x)
116}
117
Joe Tsai4ec39c72019-04-03 13:40:53 -0700118func (p legacyExtensionFields) WhichOneof(pref.Name) pref.FieldNumber {
119 return 0
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) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700157 d := t.Descriptor()
Joe Tsaiac31a352019-05-13 14:32:56 -0700158 if p.mi.PBType.Descriptor().FullName() != d.ContainingMessage().FullName() {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800159 panic("extended type mismatch")
160 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700161 if !p.mi.PBType.Descriptor().ExtensionRanges().Has(d.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800162 panic("invalid extension field number")
163 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700164 x := p.x.Get(d.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800165 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800166 panic("extension descriptor already registered")
167 }
Joe Tsaiafb455e2019-03-14 16:08:22 -0700168 x.Desc = extensionDescFromType(t)
Joe Tsaiac31a352019-05-13 14:32:56 -0700169 if d.IsList() {
Joe Tsaif6d4a422018-11-19 14:26:06 -0800170 // If the field is repeated, initialize the entry with an empty list
171 // so that future Get operations can return a mutable and concrete list.
Joe Tsai40b83d62019-05-16 11:45:52 -0700172 x.SetEagerValue(t.InterfaceOf(t.New()))
Joe Tsaif6d4a422018-11-19 14:26:06 -0800173 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700174 p.x.Set(d.Number(), x)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800175}
176
177func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700178 d := t.Descriptor()
179 if !p.mi.PBType.Descriptor().ExtensionRanges().Has(d.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800180 return
181 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700182 x := p.x.Get(d.Number())
Joe Tsaiac31a352019-05-13 14:32:56 -0700183 if d.IsList() {
Joe Tsaif6d4a422018-11-19 14:26:06 -0800184 // Treat an empty repeated field as unpopulated.
Joe Tsai40b83d62019-05-16 11:45:52 -0700185 v := reflect.ValueOf(x.GetValue())
186 if !x.HasValue() || v.IsNil() || v.Elem().Len() == 0 {
187 x.SetEagerValue(nil)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800188 }
189 }
Joe Tsai40b83d62019-05-16 11:45:52 -0700190 if x.GetValue() != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800191 panic("value for extension descriptor still populated")
192 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700193 p.x.Clear(d.Number())
Joe Tsaif0c01e42018-11-06 13:05:20 -0800194}
195
196func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
197 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800198 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700199 return extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800200 }
201 return nil
202}
203
204func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700205 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800206 if x.Desc != nil && x.Desc.Name == string(s) {
Damien Neil4866b952019-03-13 17:36:42 -0700207 t = extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800208 return false
209 }
210 return true
211 })
212 return t
213}
214
215func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700216 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800217 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700218 if !f(extensionTypeFromDesc(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800219 return false
220 }
221 }
222 return true
223 })
224}
Damien Neil4866b952019-03-13 17:36:42 -0700225
Joe Tsai4fddeba2019-03-20 18:29:32 -0700226func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
227 if xt, ok := typ.(interface {
228 ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
229 }); ok {
Joe Tsaiafb455e2019-03-14 16:08:22 -0700230 if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
231 return desc
232 }
233 }
234 return legacyWrapper.ExtensionDescFromType(typ)
235}
236
Joe Tsai4fddeba2019-03-20 18:29:32 -0700237func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
Damien Neil4866b952019-03-13 17:36:42 -0700238 if desc.Type != nil {
239 return desc.Type
240 }
241 return legacyWrapper.ExtensionTypeFromDesc(desc)
242}
Joe Tsai4fddeba2019-03-20 18:29:32 -0700243
Joe Tsai4fddeba2019-03-20 18:29:32 -0700244type ExtensionFieldV1 struct {
Joe Tsai50c16712019-04-16 01:18:50 -0700245 // TODO: We should turn this into a type alias to an unnamed type,
246 // which means that v1 can have the same struct, and we no longer have to
247 // export this from the v2 API.
Joe Tsai4fddeba2019-03-20 18:29:32 -0700248
249 // When an extension is stored in a message using SetExtension
250 // only desc and value are set. When the message is marshaled
251 // Raw will be set to the encoded form of the message.
252 //
253 // When a message is unmarshaled and contains extensions, each
254 // extension will have only Raw set. When such an extension is
255 // accessed using GetExtension (or GetExtensions) desc and value
256 // will be set.
257 Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
258
Joe Tsai40b83d62019-05-16 11:45:52 -0700259 // value is either the value of GetValue,
260 // or a *lazyExtensionValue that then returns the value of GetValue.
Joe Tsai4fddeba2019-03-20 18:29:32 -0700261 //
Joe Tsai40b83d62019-05-16 11:45:52 -0700262 // TODO: unexport this.
263 Value interface{}
264}
265
266// HasValue reports whether a value is set for the extension field.
267// This may be called concurrently.
268func (f ExtensionFieldV1) HasValue() bool {
269 return f.Value != nil
270}
271
272// GetValue returns the concrete value for the extension field.
273// Let the type of Desc.ExtensionType be the "API type" and
274// the type of GetValue be the "storage type".
275// The API type and storage type are the same except:
276// * for scalars (except []byte), where the API type uses *T,
277// while the storage type uses T.
278// * for repeated fields, where the API type uses []T,
279// while the storage type uses *[]T.
280//
281// The reason for the divergence is so that the storage type more naturally
282// matches what is expected of when retrieving the values through the
283// protobuf reflection APIs.
284//
285// GetValue is only populated if Desc is also populated.
286// This may be called concurrently.
287//
288// TODO: switch interface{} to protoreflect.Value
289func (f ExtensionFieldV1) GetValue() interface{} {
290 if f, ok := f.Value.(*lazyExtensionValue); ok {
291 return f.GetValue()
292 }
293 return f.Value
294}
295
296// SetEagerValue sets the current value of the extension.
297// This must not be called concurrently.
298func (f *ExtensionFieldV1) SetEagerValue(v interface{}) {
299 f.Value = v
300}
301
302// SetLazyValue sets a value that is to be lazily evaluated upon first use.
303// The returned value must not be nil.
304// This must not be called concurrently.
305func (f *ExtensionFieldV1) SetLazyValue(v func() interface{}) {
306 f.Value = &lazyExtensionValue{value: v}
307}
308
309type lazyExtensionValue struct {
310 once uint32 // atomically set if value is valid
311 mu sync.Mutex // protects value
312 value interface{} // either the value itself or a func() interface{}
313}
314
315func (v *lazyExtensionValue) GetValue() interface{} {
316 if atomic.LoadUint32(&v.once) == 0 {
317 v.mu.Lock()
318 if f, ok := v.value.(func() interface{}); ok {
319 v.value = f()
320 }
321 atomic.StoreUint32(&v.once, 1)
322 v.mu.Unlock()
323 }
324 return v.value
Joe Tsai4fddeba2019-03-20 18:29:32 -0700325}
326
Joe Tsai00e50dc2019-04-16 12:39:41 -0700327type legacyExtensionMap map[int32]ExtensionFieldV1
Joe Tsai4fddeba2019-03-20 18:29:32 -0700328
329func (m legacyExtensionMap) Len() int {
330 return len(m)
331}
332func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
333 _, ok := m[int32(n)]
334 return ok
335}
336func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
337 return m[int32(n)]
338}
339func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
340 if *m == nil {
341 *m = make(map[int32]ExtensionFieldV1)
342 }
343 (*m)[int32(n)] = x
344}
345func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
346 delete(*m, int32(n))
347}
348func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
349 for n, x := range m {
350 if !f(pref.FieldNumber(n), x) {
351 return
352 }
353 }
354}