blob: 9ea5b0a2e32110d3ff018978acb6de3ea22033ef [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
Joe Tsaif0c01e42018-11-06 13:05:20 -080010 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Joe Tsai4fddeba2019-03-20 18:29:32 -070011 piface "github.com/golang/protobuf/v2/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 Tsaif0c01e42018-11-06 13:05:20 -080066 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -080067 return t.ValueOf(x.Value).List().Len() > 0
Joe Tsaif0c01e42018-11-06 13:05:20 -080068 }
69 return true
70}
71
72func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
73 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080074 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080075 return pref.Value{}
76 }
Damien Neil4866b952019-03-13 17:36:42 -070077 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -080078 if x.Value == nil {
79 // NOTE: x.Value is never nil for Lists since they are always populated
Joe Tsaif6d4a422018-11-19 14:26:06 -080080 // during ExtensionFieldTypes.Register.
Joe Tsaif0c01e42018-11-06 13:05:20 -080081 if t.Kind() == pref.MessageKind || t.Kind() == pref.GroupKind {
Joe Tsaif0c01e42018-11-06 13:05:20 -080082 return pref.Value{}
83 }
84 return t.Default()
85 }
Joe Tsaif18ab532018-11-27 17:25:04 -080086 return t.ValueOf(x.Value)
Joe Tsaif0c01e42018-11-06 13:05:20 -080087}
88
89func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
90 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080091 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080092 panic("no extension descriptor registered")
93 }
Damien Neil4866b952019-03-13 17:36:42 -070094 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -080095 x.Value = t.InterfaceOf(v)
Joe Tsaif0c01e42018-11-06 13:05:20 -080096 p.x.Set(n, x)
97}
98
99func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
100 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800101 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800102 return
103 }
Damien Neil4866b952019-03-13 17:36:42 -0700104 t := extensionTypeFromDesc(x.Desc)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800105 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -0800106 t.ValueOf(x.Value).List().Truncate(0)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800107 return
108 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800109 x.Value = nil
Joe Tsaif0c01e42018-11-06 13:05:20 -0800110 p.x.Set(n, x)
111}
112
Joe Tsai4ec39c72019-04-03 13:40:53 -0700113func (p legacyExtensionFields) WhichOneof(pref.Name) pref.FieldNumber {
114 return 0
115}
116
Joe Tsaif0c01e42018-11-06 13:05:20 -0800117func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700118 p.x.Range(func(n pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800119 if p.Has(n) {
120 return f(n, p.Get(n))
121 }
122 return true
123 })
124}
125
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800126func (p legacyExtensionFields) NewMessage(n pref.FieldNumber) pref.Message {
Damien Neil97e7f572018-12-07 14:28:33 -0800127 x := p.x.Get(n)
128 if x.Desc == nil {
129 panic("no extension descriptor registered")
130 }
Damien Neil4866b952019-03-13 17:36:42 -0700131 xt := extensionTypeFromDesc(x.Desc)
Joe Tsaid18bd312019-01-09 03:23:55 -0800132 return xt.New().Message()
Damien Neil97e7f572018-12-07 14:28:33 -0800133}
134
Joe Tsaif0c01e42018-11-06 13:05:20 -0800135func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
136 return legacyExtensionTypes(p)
137}
138
139type legacyExtensionTypes legacyExtensionFields
140
141func (p legacyExtensionTypes) Len() (n int) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700142 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800143 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800144 n++
145 }
146 return true
147 })
148 return n
149}
150
151func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
Joe Tsaid24bc722019-04-15 23:39:09 -0700152 if p.mi.PBType.FullName() != t.Extendee().FullName() {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800153 panic("extended type mismatch")
154 }
Damien Neil8012b442019-01-18 09:32:24 -0800155 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800156 panic("invalid extension field number")
157 }
158 x := p.x.Get(t.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800159 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800160 panic("extension descriptor already registered")
161 }
Joe Tsaiafb455e2019-03-14 16:08:22 -0700162 x.Desc = extensionDescFromType(t)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800163 if t.Cardinality() == pref.Repeated {
164 // If the field is repeated, initialize the entry with an empty list
165 // so that future Get operations can return a mutable and concrete list.
Joe Tsaid18bd312019-01-09 03:23:55 -0800166 x.Value = t.InterfaceOf(t.New())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800167 }
Joe Tsaif0c01e42018-11-06 13:05:20 -0800168 p.x.Set(t.Number(), x)
169}
170
171func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
Damien Neil8012b442019-01-18 09:32:24 -0800172 if !p.mi.PBType.ExtensionRanges().Has(t.Number()) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800173 return
174 }
175 x := p.x.Get(t.Number())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800176 if t.Cardinality() == pref.Repeated {
177 // Treat an empty repeated field as unpopulated.
Joe Tsaif18ab532018-11-27 17:25:04 -0800178 v := reflect.ValueOf(x.Value)
179 if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
180 x.Value = nil
Joe Tsaif6d4a422018-11-19 14:26:06 -0800181 }
182 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800183 if x.Value != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800184 panic("value for extension descriptor still populated")
185 }
Joe Tsai00a323d2019-05-06 23:27:29 -0700186 p.x.Clear(t.Number())
Joe Tsaif0c01e42018-11-06 13:05:20 -0800187}
188
189func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
190 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800191 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700192 return extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800193 }
194 return nil
195}
196
197func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700198 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800199 if x.Desc != nil && x.Desc.Name == string(s) {
Damien Neil4866b952019-03-13 17:36:42 -0700200 t = extensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800201 return false
202 }
203 return true
204 })
205 return t
206}
207
208func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsai4fddeba2019-03-20 18:29:32 -0700209 p.x.Range(func(_ pref.FieldNumber, x ExtensionFieldV1) bool {
Joe Tsaif18ab532018-11-27 17:25:04 -0800210 if x.Desc != nil {
Damien Neil4866b952019-03-13 17:36:42 -0700211 if !f(extensionTypeFromDesc(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800212 return false
213 }
214 }
215 return true
216 })
217}
Damien Neil4866b952019-03-13 17:36:42 -0700218
Joe Tsai4fddeba2019-03-20 18:29:32 -0700219func extensionDescFromType(typ pref.ExtensionType) *piface.ExtensionDescV1 {
220 if xt, ok := typ.(interface {
221 ProtoLegacyExtensionDesc() *piface.ExtensionDescV1
222 }); ok {
Joe Tsaiafb455e2019-03-14 16:08:22 -0700223 if desc := xt.ProtoLegacyExtensionDesc(); desc != nil {
224 return desc
225 }
226 }
227 return legacyWrapper.ExtensionDescFromType(typ)
228}
229
Joe Tsai4fddeba2019-03-20 18:29:32 -0700230func extensionTypeFromDesc(desc *piface.ExtensionDescV1) pref.ExtensionType {
Damien Neil4866b952019-03-13 17:36:42 -0700231 if desc.Type != nil {
232 return desc.Type
233 }
234 return legacyWrapper.ExtensionTypeFromDesc(desc)
235}
Joe Tsai4fddeba2019-03-20 18:29:32 -0700236
Joe Tsai4fddeba2019-03-20 18:29:32 -0700237type ExtensionFieldV1 struct {
Joe Tsai50c16712019-04-16 01:18:50 -0700238 // TODO: We should turn this into a type alias to an unnamed type,
239 // which means that v1 can have the same struct, and we no longer have to
240 // export this from the v2 API.
Joe Tsai4fddeba2019-03-20 18:29:32 -0700241
242 // When an extension is stored in a message using SetExtension
243 // only desc and value are set. When the message is marshaled
244 // Raw will be set to the encoded form of the message.
245 //
246 // When a message is unmarshaled and contains extensions, each
247 // extension will have only Raw set. When such an extension is
248 // accessed using GetExtension (or GetExtensions) desc and value
249 // will be set.
250 Desc *piface.ExtensionDescV1 // TODO: switch to protoreflect.ExtensionType
251
252 // Value is a concrete value for the extension field. Let the type of
253 // Desc.ExtensionType be the "API type" and the type of Value be the
254 // "storage type". The API type and storage type are the same except:
255 // * for scalars (except []byte), where the API type uses *T,
256 // while the storage type uses T.
257 // * for repeated fields, where the API type uses []T,
258 // while the storage type uses *[]T.
259 //
260 // The reason for the divergence is so that the storage type more naturally
261 // matches what is expected of when retrieving the values through the
262 // protobuf reflection APIs.
263 //
264 // The Value may only be populated if Desc is also populated.
265 Value interface{} // TODO: switch to protoreflect.Value
266
Joe Tsai50c16712019-04-16 01:18:50 -0700267 Raw []byte // TODO: remove; let this be handled by XXX_unrecognized
Joe Tsai4fddeba2019-03-20 18:29:32 -0700268}
269
Joe Tsai00e50dc2019-04-16 12:39:41 -0700270type legacyExtensionMap map[int32]ExtensionFieldV1
Joe Tsai4fddeba2019-03-20 18:29:32 -0700271
272func (m legacyExtensionMap) Len() int {
273 return len(m)
274}
275func (m legacyExtensionMap) Has(n pref.FieldNumber) bool {
276 _, ok := m[int32(n)]
277 return ok
278}
279func (m legacyExtensionMap) Get(n pref.FieldNumber) ExtensionFieldV1 {
280 return m[int32(n)]
281}
282func (m *legacyExtensionMap) Set(n pref.FieldNumber, x ExtensionFieldV1) {
283 if *m == nil {
284 *m = make(map[int32]ExtensionFieldV1)
285 }
286 (*m)[int32(n)] = x
287}
288func (m *legacyExtensionMap) Clear(n pref.FieldNumber) {
289 delete(*m, int32(n))
290}
291func (m legacyExtensionMap) Range(f func(pref.FieldNumber, ExtensionFieldV1) bool) {
292 for n, x := range m {
293 if !f(pref.FieldNumber(n), x) {
294 return
295 }
296 }
297}