blob: eac04b99fc22d60e5ba86834bce5555d3ba59fe7 [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"
9
Damien Neile89e6242019-05-13 23:55:40 -070010 pref "google.golang.org/protobuf/reflect/protoreflect"
11 piface "google.golang.org/protobuf/runtime/protoiface"
Joe Tsaif0c01e42018-11-06 13:05:20 -080012)
13
14func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
15 f := makeLegacyExtensionMapFunc(t)
16 if f == nil {
17 return nil
18 }
19 return func(p *messageDataType) pref.KnownFields {
Joe Tsai6cf80c42018-12-01 04:57:09 -080020 if p.p.IsNil() {
21 return emptyExtensionFields{}
22 }
Joe Tsaif0c01e42018-11-06 13:05:20 -080023 return legacyExtensionFields{p.mi, f(p)}
24 }
25}
26
Joe Tsai00e50dc2019-04-16 12:39:41 -070027var extType = reflect.TypeOf(map[int32]ExtensionFieldV1{})
Joe Tsaif18ab532018-11-27 17:25:04 -080028
Joe Tsai50c16712019-04-16 01:18:50 -070029func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) *legacyExtensionMap {
30 fx, _ := t.FieldByName("XXX_extensions")
31 if fx.Type != extType {
32 fx, _ = t.FieldByName("XXX_InternalExtensions")
33 }
34 if fx.Type != extType {
Joe Tsaif18ab532018-11-27 17:25:04 -080035 return nil
36 }
Joe Tsai50c16712019-04-16 01:18:50 -070037
38 fieldOffset := offsetOf(fx)
39 return func(p *messageDataType) *legacyExtensionMap {
40 v := p.p.Apply(fieldOffset).AsValueOf(fx.Type).Interface()
Joe Tsai00e50dc2019-04-16 12:39:41 -070041 return (*legacyExtensionMap)(v.(*map[int32]ExtensionFieldV1))
Joe Tsai50c16712019-04-16 01:18:50 -070042 }
Joe Tsaif18ab532018-11-27 17:25:04 -080043}
44
Joe Tsaif0c01e42018-11-06 13:05:20 -080045type legacyExtensionFields struct {
46 mi *MessageType
Joe Tsai50c16712019-04-16 01:18:50 -070047 x *legacyExtensionMap
Joe Tsaif0c01e42018-11-06 13:05:20 -080048}
49
50func (p legacyExtensionFields) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -070051 p.x.Range(func(num pref.FieldNumber, _ ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -080052 if p.Has(pref.FieldNumber(num)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -080053 n++
54 }
55 return true
56 })
57 return n
58}
59
60func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
61 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080062 if x.Value == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080063 return false
64 }
Damien Neil4866b952019-03-13 17:36:42 -070065 t := extensionTypeFromDesc(x.Desc)
Joe Tsai0fc49f82019-05-01 12:29:25 -070066 d := t.Descriptor()
Joe Tsaiac31a352019-05-13 14:32:56 -070067 if d.IsList() {
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 Tsai0fc49f82019-05-01 12:29:25 -070079 d := t.Descriptor()
Joe Tsaif18ab532018-11-27 17:25:04 -080080 if x.Value == nil {
81 // NOTE: x.Value is never nil for Lists since they are always populated
Joe Tsaif6d4a422018-11-19 14:26:06 -080082 // during ExtensionFieldTypes.Register.
Joe Tsai0fc49f82019-05-01 12:29:25 -070083 if d.Kind() == pref.MessageKind || d.Kind() == pref.GroupKind {
Joe Tsaif0c01e42018-11-06 13:05:20 -080084 return pref.Value{}
85 }
Joe Tsai0fc49f82019-05-01 12:29:25 -070086 return d.Default()
Joe Tsaif0c01e42018-11-06 13:05:20 -080087 }
Joe Tsaif18ab532018-11-27 17:25:04 -080088 return t.ValueOf(x.Value)
Joe Tsaif0c01e42018-11-06 13:05:20 -080089}
90
91func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
92 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080093 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080094 panic("no extension descriptor registered")
95 }
Damien Neil4866b952019-03-13 17:36:42 -070096 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -080097 x.Value = t.InterfaceOf(v)
Joe Tsaif0c01e42018-11-06 13:05:20 -080098 p.x.Set(n, x)
99}
100
101func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
102 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800103 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800104 return
105 }
Damien Neil4866b952019-03-13 17:36:42 -0700106 t := extensionTypeFromDesc(x.Desc)
Joe Tsai0fc49f82019-05-01 12:29:25 -0700107 d := t.Descriptor()
Joe Tsaiac31a352019-05-13 14:32:56 -0700108 if d.IsList() {
Joe Tsaif18ab532018-11-27 17:25:04 -0800109 t.ValueOf(x.Value).List().Truncate(0)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800110 return
111 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800112 x.Value = nil
Joe Tsaif0c01e42018-11-06 13:05:20 -0800113 p.x.Set(n, x)
114}
115
Joe Tsai4ec39c72019-04-03 13:40:53 -0700116func (p legacyExtensionFields) WhichOneof(pref.Name) pref.FieldNumber {
117 return 0
118}
119
Joe Tsaif0c01e42018-11-06 13:05:20 -0800120func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700121 p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800122 if p.Has(n) {
123 return f(n, p.Get(n))
124 }
125 return true
126 })
127}
128
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800129func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
Damien Neil97e7f572018-12-07 14:28:33 -0800130 x := p.x.Get(n)
131 if x.Desc == nil {
132 panic("no extension descriptor registered")
133 }
Damien Neil4866b952019-03-13 17:36:42 -0700134 xt := extensionTypeFromDesc(x.Desc)
Joe Tsaid18bd312019-01-09 03:23:55 -0800135 return xt.New().Message()
Damien Neil97e7f572018-12-07 14:28:33 -0800136}
137
Joe Tsaif0c01e42018-11-06 13:05:20 -0800138func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
139 return legacyExtensionTypes(p)
140}
141
142type legacyExtensionTypes legacyExtensionFields
143
144func (p legacyExtensionTypes) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700145 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800146 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800147 n++
148 }
149 return true
150 })
151 return n
152}
153
154func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700155 d := t.Descriptor()
Joe Tsaiac31a352019-05-13 14:32:56 -0700156 if p.mi.PBType.Descriptor().FullName() != d.ContainingMessage().FullName() {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800157 panic("extended type mismatch")
158 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700159 if !p.mi.PBType.Descriptor().ExtensionRanges().Has(d.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800160 panic("invalid extension field number")
161 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700162 x := p.x.Get(d.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800163 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800164 panic("extension descriptor already registered")
165 }
Joe Tsaiafb455e2019-03-14 16:08:22 -0700166 x.Desc = extensionDescFromType(t)
Joe Tsaiac31a352019-05-13 14:32:56 -0700167 if d.IsList() {
Joe Tsaif6d4a422018-11-19 14:26:06 -0800168 // If the field is repeated, initialize the entry with an empty list
169 // so that future Get operations can return a mutable and concrete list.
Joe Tsaid18bd312019-01-09 03:23:55 -0800170 x.Value = t.InterfaceOf(t.New())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800171 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700172 p.x.Set(d.Number(), x)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800173}
174
175func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700176 d := t.Descriptor()
177 if !p.mi.PBType.Descriptor().ExtensionRanges().Has(d.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800178 return
179 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700180 x := p.x.Get(d.Number())
Joe Tsaiac31a352019-05-13 14:32:56 -0700181 if d.IsList() {
Joe Tsaif6d4a422018-11-19 14:26:06 -0800182 // 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 Tsai0fc49f82019-05-01 12:29:25 -0700191 p.x.Clear(d.Number())
Joe Tsaif0c01e42018-11-06 13:05:20 -0800192}
193
194func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
195 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800196 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700197 return extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800198 }
199 return nil
200}
201
202func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700203 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800204 if x.Desc != nil && x.Desc.Name == string(s) {
Damien Neil4866b952019-03-13 17:36:42 -0700205 t = extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800206 return false
207 }
208 return true
209 })
210 return t
211}
212
213func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700214 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800215 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700216 if !f(extensionTypeFromDesc(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800217 return false
218 }
219 }
220 return true
221 })
222}
Damien Neil4866b952019-03-13 17:36:42 -0700223
Joe Tsai4fddeba2019-03-20 18:29:32 -0700224func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
225 if xt, ok := typ.(interface {
226 ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
227 }); ok {
Joe Tsaiafb455e2019-03-14 16:08:22 -0700228 if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
229 return desc
230 }
231 }
232 return legacyWrapper.ExtensionDescFromType(typ)
233}
234
Joe Tsai4fddeba2019-03-20 18:29:32 -0700235func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
Damien Neil4866b952019-03-13 17:36:42 -0700236 if desc.Type != nil {
237 return desc.Type
238 }
239 return legacyWrapper.ExtensionTypeFromDesc(desc)
240}
Joe Tsai4fddeba2019-03-20 18:29:32 -0700241
Joe Tsai4fddeba2019-03-20 18:29:32 -0700242type ExtensionFieldV1 struct {
Joe Tsai50c16712019-04-16 01:18:50 -0700243 // TODO: We should turn this into a type alias to an unnamed type,
244 // which means that v1 can have the same struct, and we no longer have to
245 // export this from the v2 API.
Joe Tsai4fddeba2019-03-20 18:29:32 -0700246
247 // When an extension is stored in a message using SetExtension
248 // only desc and value are set. When the message is marshaled
249 // Raw will be set to the encoded form of the message.
250 //
251 // When a message is unmarshaled and contains extensions, each
252 // extension will have only Raw set. When such an extension is
253 // accessed using GetExtension (or GetExtensions) desc and value
254 // will be set.
255 Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
256
257 // Value is a concrete value for the extension field. Let the type of
258 // Desc.ExtensionType be the "API type" and the type of Value be the
259 // "storage type". The API type and storage type are the same except:
260 // * for scalars (except []byte), where the API type uses *T,
261 // while the storage type uses T.
262 // * for repeated fields, where the API type uses []T,
263 // while the storage type uses *[]T.
264 //
265 // The reason for the divergence is so that the storage type more naturally
266 // matches what is expected of when retrieving the values through the
267 // protobuf reflection APIs.
268 //
269 // The Value may only be populated if Desc is also populated.
270 Value interface{} // TODO: switch to protoreflect.Value
Joe Tsai4fddeba2019-03-20 18:29:32 -0700271}
272
Joe Tsai00e50dc2019-04-16 12:39:41 -0700273type legacyExtensionMap map[int32]ExtensionFieldV1
Joe Tsai4fddeba2019-03-20 18:29:32 -0700274
275func (m legacyExtensionMap) Len() int {
276 return len(m)
277}
278func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
279 _, ok := m[int32(n)]
280 return ok
281}
282func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
283 return m[int32(n)]
284}
285func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
286 if *m == nil {
287 *m = make(map[int32]ExtensionFieldV1)
288 }
289 (*m)[int32(n)] = x
290}
291func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
292 delete(*m, int32(n))
293}
294func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
295 for n, x := range m {
296 if !f(pref.FieldNumber(n), x) {
297 return
298 }
299 }
300}