blob: ada2f8727135e61edd3b3303f82ebf05f3dad150 [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 {
Joe Tsai4fe96632019-05-22 05:12:36 -040048 mi *MessageInfo
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 Tsai11caeff2019-05-16 12:00:29 -0700261 value interface{}
Joe Tsai40b83d62019-05-16 11:45:52 -0700262}
263
264// HasValue reports whether a value is set for the extension field.
265// This may be called concurrently.
266func (f ExtensionFieldV1) HasValue() bool {
Joe Tsai11caeff2019-05-16 12:00:29 -0700267 return f.value != nil
Joe Tsai40b83d62019-05-16 11:45:52 -0700268}
269
270// GetValue returns the concrete value for the extension field.
271// Let the type of Desc.ExtensionType be the "API type" and
272// the type of GetValue be the "storage type".
273// The API type and storage type are the same except:
274// * for scalars (except []byte), where the API type uses *T,
275// while the storage type uses T.
276// * for repeated fields, where the API type uses []T,
277// while the storage type uses *[]T.
278//
279// The reason for the divergence is so that the storage type more naturally
280// matches what is expected of when retrieving the values through the
281// protobuf reflection APIs.
282//
283// GetValue is only populated if Desc is also populated.
284// This may be called concurrently.
285//
286// TODO: switch interface{} to protoreflect.Value
287func (f ExtensionFieldV1) GetValue() interface{} {
Joe Tsai11caeff2019-05-16 12:00:29 -0700288 if f, ok := f.value.(*lazyExtensionValue); ok {
Joe Tsai40b83d62019-05-16 11:45:52 -0700289 return f.GetValue()
290 }
Joe Tsai11caeff2019-05-16 12:00:29 -0700291 return f.value
Joe Tsai40b83d62019-05-16 11:45:52 -0700292}
293
294// SetEagerValue sets the current value of the extension.
295// This must not be called concurrently.
296func (f *ExtensionFieldV1) SetEagerValue(v interface{}) {
Joe Tsai11caeff2019-05-16 12:00:29 -0700297 f.value = v
Joe Tsai40b83d62019-05-16 11:45:52 -0700298}
299
300// SetLazyValue sets a value that is to be lazily evaluated upon first use.
301// The returned value must not be nil.
302// This must not be called concurrently.
303func (f *ExtensionFieldV1) SetLazyValue(v func() interface{}) {
Joe Tsai11caeff2019-05-16 12:00:29 -0700304 f.value = &lazyExtensionValue{value: v}
Joe Tsai40b83d62019-05-16 11:45:52 -0700305}
306
307type lazyExtensionValue struct {
308 once uint32 // atomically set if value is valid
309 mu sync.Mutex // protects value
310 value interface{} // either the value itself or a func() interface{}
311}
312
313func (v *lazyExtensionValue) GetValue() interface{} {
314 if atomic.LoadUint32(&v.once) == 0 {
315 v.mu.Lock()
316 if f, ok := v.value.(func() interface{}); ok {
317 v.value = f()
318 }
319 atomic.StoreUint32(&v.once, 1)
320 v.mu.Unlock()
321 }
322 return v.value
Joe Tsai4fddeba2019-03-20 18:29:32 -0700323}
324
Joe Tsai00e50dc2019-04-16 12:39:41 -0700325type legacyExtensionMap map[int32]ExtensionFieldV1
Joe Tsai4fddeba2019-03-20 18:29:32 -0700326
327func (m legacyExtensionMap) Len() int {
328 return len(m)
329}
330func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
331 _, ok := m[int32(n)]
332 return ok
333}
334func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
335 return m[int32(n)]
336}
337func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
338 if *m == nil {
339 *m = make(map[int32]ExtensionFieldV1)
340 }
341 (*m)[int32(n)] = x
342}
343func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
344 delete(*m, int32(n))
345}
346func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
347 for n, x := range m {
348 if !f(pref.FieldNumber(n), x) {
349 return
350 }
351 }
352}