blob: d87892f7641f8b0dbf146af433c6819e9e8b5ea0 [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 (
8 "fmt"
9 "reflect"
10
Joe Tsaif18ab532018-11-27 17:25:04 -080011 papi "github.com/golang/protobuf/protoapi"
Joe Tsaif0c01e42018-11-06 13:05:20 -080012 ptag "github.com/golang/protobuf/v2/internal/encoding/tag"
13 pvalue "github.com/golang/protobuf/v2/internal/value"
14 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
15 ptype "github.com/golang/protobuf/v2/reflect/prototype"
16)
17
18func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
19 f := makeLegacyExtensionMapFunc(t)
20 if f == nil {
21 return nil
22 }
23 return func(p *messageDataType) pref.KnownFields {
24 return legacyExtensionFields{p.mi, f(p)}
25 }
26}
27
Joe Tsaif18ab532018-11-27 17:25:04 -080028var (
29 extTypeA = reflect.TypeOf(map[int32]papi.ExtensionField(nil))
30 extTypeB = reflect.TypeOf(papi.XXX_InternalExtensions{})
31)
32
33func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) papi.ExtensionFields {
34 fx1, _ := t.FieldByName("XXX_extensions")
35 fx2, _ := t.FieldByName("XXX_InternalExtensions")
36 switch {
37 case fx1.Type == extTypeA:
38 fieldOffset := offsetOf(fx1)
39 return func(p *messageDataType) papi.ExtensionFields {
40 v := p.p.apply(fieldOffset).asType(fx1.Type).Interface()
41 return papi.ExtensionFieldsOf(v)
42 }
43 case fx2.Type == extTypeB:
44 fieldOffset := offsetOf(fx2)
45 return func(p *messageDataType) papi.ExtensionFields {
46 v := p.p.apply(fieldOffset).asType(fx2.Type).Interface()
47 return papi.ExtensionFieldsOf(v)
48 }
49 default:
50 return nil
51 }
52}
53
Joe Tsaif0c01e42018-11-06 13:05:20 -080054type legacyExtensionFields struct {
55 mi *MessageType
Joe Tsaif18ab532018-11-27 17:25:04 -080056 x papi.ExtensionFields
Joe Tsaif0c01e42018-11-06 13:05:20 -080057}
58
59func (p legacyExtensionFields) Len() (n int) {
Joe Tsaif18ab532018-11-27 17:25:04 -080060 p.x.Range(func(num pref.FieldNumber, _ papi.ExtensionField) bool {
61 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 }
Joe Tsaif18ab532018-11-27 17:25:04 -080074 t := legacyExtensionTypeOf(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 }
Joe Tsaif18ab532018-11-27 17:25:04 -080086 t := legacyExtensionTypeOf(x.Desc)
87 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 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800103 t := legacyExtensionTypeOf(x.Desc)
104 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 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800113 t := legacyExtensionTypeOf(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
122func (p legacyExtensionFields) Mutable(n pref.FieldNumber) pref.Mutable {
123 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800124 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800125 panic("no extension descriptor registered")
126 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800127 t := legacyExtensionTypeOf(x.Desc)
128 if x.Value == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800129 v := t.ValueOf(t.New())
Joe Tsaif18ab532018-11-27 17:25:04 -0800130 x.Value = t.InterfaceOf(v)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800131 p.x.Set(n, x)
132 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800133 return t.ValueOf(x.Value).Interface().(pref.Mutable)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800134}
135
136func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800137 p.x.Range(func(n pref.FieldNumber, x papi.ExtensionField) bool {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800138 if p.Has(n) {
139 return f(n, p.Get(n))
140 }
141 return true
142 })
143}
144
145func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
146 return legacyExtensionTypes(p)
147}
148
149type legacyExtensionTypes legacyExtensionFields
150
151func (p legacyExtensionTypes) Len() (n int) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800152 p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
153 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800154 n++
155 }
156 return true
157 })
158 return n
159}
160
161func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
162 if p.mi.Type.FullName() != t.ExtendedType().FullName() {
163 panic("extended type mismatch")
164 }
165 if !p.mi.Type.ExtensionRanges().Has(t.Number()) {
166 panic("invalid extension field number")
167 }
168 x := p.x.Get(t.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800169 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800170 panic("extension descriptor already registered")
171 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800172 x.Desc = legacyExtensionDescOf(t, p.mi.goType)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800173 if t.Cardinality() == pref.Repeated {
174 // If the field is repeated, initialize the entry with an empty list
175 // so that future Get operations can return a mutable and concrete list.
Joe Tsaif18ab532018-11-27 17:25:04 -0800176 x.Value = t.InterfaceOf(t.ValueOf(t.New()))
Joe Tsaif6d4a422018-11-19 14:26:06 -0800177 }
Joe Tsaif0c01e42018-11-06 13:05:20 -0800178 p.x.Set(t.Number(), x)
179}
180
181func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
182 if !p.mi.Type.ExtensionRanges().Has(t.Number()) {
183 return
184 }
185 x := p.x.Get(t.Number())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800186 if t.Cardinality() == pref.Repeated {
187 // Treat an empty repeated field as unpopulated.
Joe Tsaif18ab532018-11-27 17:25:04 -0800188 v := reflect.ValueOf(x.Value)
189 if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
190 x.Value = nil
Joe Tsaif6d4a422018-11-19 14:26:06 -0800191 }
192 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800193 if x.Value != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800194 panic("value for extension descriptor still populated")
195 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800196 x.Desc = nil
197 if len(x.Raw) == 0 {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800198 p.x.Clear(t.Number())
199 } else {
200 p.x.Set(t.Number(), x)
201 }
202}
203
204func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
205 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800206 if x.Desc != nil {
207 return legacyExtensionTypeOf(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800208 }
209 return nil
210}
211
212func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800213 p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
214 if x.Desc != nil && x.Desc.Name == string(s) {
215 t = legacyExtensionTypeOf(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800216 return false
217 }
218 return true
219 })
220 return t
221}
222
223func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800224 p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
225 if x.Desc != nil {
226 if !f(legacyExtensionTypeOf(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800227 return false
228 }
229 }
230 return true
231 })
232}
233
Joe Tsaif18ab532018-11-27 17:25:04 -0800234func legacyExtensionDescOf(t pref.ExtensionType, parent reflect.Type) *papi.ExtensionDesc {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800235 if t, ok := t.(*legacyExtensionType); ok {
236 return t.desc
237 }
238
239 // Determine the v1 extension type, which is unfortunately not the same as
240 // the v2 ExtensionType.GoType.
241 extType := t.GoType()
242 switch extType.Kind() {
243 case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
244 extType = reflect.PtrTo(extType) // T -> *T for singular scalar fields
245 case reflect.Ptr:
246 if extType.Elem().Kind() == reflect.Slice {
247 extType = extType.Elem() // *[]T -> []T for repeated fields
248 }
249 }
250
251 // Reconstruct the legacy enum full name, which is an odd mixture of the
252 // proto package name with the Go type name.
253 var enumName string
254 if t.Kind() == pref.EnumKind {
255 enumName = t.GoType().Name()
256 for d, ok := pref.Descriptor(t.EnumType()), true; ok; d, ok = d.Parent() {
257 if fd, _ := d.(pref.FileDescriptor); fd != nil && fd.Package() != "" {
258 enumName = string(fd.Package()) + "." + enumName
259 }
260 }
261 }
262
263 // Construct and return a v1 ExtensionDesc.
Joe Tsaif18ab532018-11-27 17:25:04 -0800264 return &papi.ExtensionDesc{
265 ExtendedType: reflect.Zero(parent).Interface().(papi.Message),
Joe Tsaif0c01e42018-11-06 13:05:20 -0800266 ExtensionType: reflect.Zero(extType).Interface(),
267 Field: int32(t.Number()),
268 Name: string(t.FullName()),
269 Tag: ptag.Marshal(t, enumName),
270 }
271}
272
Joe Tsaif18ab532018-11-27 17:25:04 -0800273func legacyExtensionTypeOf(d *papi.ExtensionDesc) pref.ExtensionType {
274 if d.Type != nil {
275 return d.Type
276 }
Joe Tsaif0c01e42018-11-06 13:05:20 -0800277
278 // Derive basic field information from the struct tag.
279 t := reflect.TypeOf(d.ExtensionType)
280 isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct
281 isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
282 if isOptional || isRepeated {
283 t = t.Elem()
284 }
285 f := ptag.Unmarshal(d.Tag, t)
286
287 // Construct a v2 ExtensionType.
288 conv := newConverter(t, f.Kind)
289 xd, err := ptype.NewExtension(&ptype.StandaloneExtension{
290 FullName: pref.FullName(d.Name),
291 Number: pref.FieldNumber(d.Field),
292 Cardinality: f.Cardinality,
293 Kind: f.Kind,
294 Default: f.Default,
295 Options: f.Options,
296 EnumType: conv.EnumType,
297 MessageType: conv.MessageType,
298 ExtendedType: legacyLoadMessageDesc(reflect.TypeOf(d.ExtendedType)),
299 })
300 if err != nil {
301 panic(err)
302 }
303 xt := ptype.GoExtension(xd, conv.EnumType, conv.MessageType)
304
305 // Return the extension type as is if the dependencies already support v2.
306 xt2 := &legacyExtensionType{ExtensionType: xt, desc: d}
307 if !conv.IsLegacy {
308 return xt2
309 }
310
311 // If the dependency is a v1 enum or message, we need to create a custom
312 // extension type where ExtensionType.GoType continues to use the legacy
313 // v1 Go type, instead of the wrapped versions that satisfy the v2 API.
314 if xd.Cardinality() != pref.Repeated {
315 // Custom extension type for singular enums and messages.
316 // The legacy wrappers use legacyEnumWrapper and legacyMessageWrapper
317 // to implement the v2 interfaces for enums and messages.
318 // Both of those type satisfy the value.Unwrapper interface.
319 xt2.typ = t
320 xt2.new = func() interface{} {
Joe Tsaiba0ef9a2018-11-29 14:54:05 -0800321 return xt.New().(pvalue.Unwrapper).ProtoUnwrap()
Joe Tsaif0c01e42018-11-06 13:05:20 -0800322 }
323 xt2.valueOf = func(v interface{}) pref.Value {
324 if reflect.TypeOf(v) != xt2.typ {
325 panic(fmt.Sprintf("invalid type: got %T, want %v", v, xt2.typ))
326 }
327 if xd.Kind() == pref.EnumKind {
328 return xt.ValueOf(legacyWrapEnum(reflect.ValueOf(v)))
329 } else {
330 return xt.ValueOf(legacyWrapMessage(reflect.ValueOf(v)))
331 }
332 }
333 xt2.interfaceOf = func(v pref.Value) interface{} {
Joe Tsaiba0ef9a2018-11-29 14:54:05 -0800334 return xt.InterfaceOf(v).(pvalue.Unwrapper).ProtoUnwrap()
Joe Tsaif0c01e42018-11-06 13:05:20 -0800335 }
336 } else {
337 // Custom extension type for repeated enums and messages.
338 xt2.typ = reflect.PtrTo(reflect.SliceOf(t))
339 xt2.new = func() interface{} {
340 return reflect.New(xt2.typ.Elem()).Interface()
341 }
342 xt2.valueOf = func(v interface{}) pref.Value {
343 if reflect.TypeOf(v) != xt2.typ {
344 panic(fmt.Sprintf("invalid type: got %T, want %v", v, xt2.typ))
345 }
Joe Tsai4b7aff62018-11-14 14:05:19 -0800346 return pref.ValueOf(pvalue.ListOf(v, conv))
Joe Tsaif0c01e42018-11-06 13:05:20 -0800347 }
348 xt2.interfaceOf = func(pv pref.Value) interface{} {
Joe Tsaiba0ef9a2018-11-29 14:54:05 -0800349 v := pv.List().(pvalue.Unwrapper).ProtoUnwrap()
Joe Tsaif0c01e42018-11-06 13:05:20 -0800350 if reflect.TypeOf(v) != xt2.typ {
351 panic(fmt.Sprintf("invalid type: got %T, want %v", v, xt2.typ))
352 }
353 return v
354 }
355 }
356 return xt2
357}
358
359type legacyExtensionType struct {
360 pref.ExtensionType
Joe Tsaif18ab532018-11-27 17:25:04 -0800361 desc *papi.ExtensionDesc
Joe Tsaif0c01e42018-11-06 13:05:20 -0800362 typ reflect.Type
363 new func() interface{}
364 valueOf func(interface{}) pref.Value
365 interfaceOf func(pref.Value) interface{}
366}
367
368func (x *legacyExtensionType) GoType() reflect.Type {
369 if x.typ != nil {
370 return x.typ
371 }
372 return x.ExtensionType.GoType()
373}
374func (x *legacyExtensionType) New() interface{} {
375 if x.new != nil {
376 return x.new()
377 }
378 return x.ExtensionType.New()
379}
380func (x *legacyExtensionType) ValueOf(v interface{}) pref.Value {
381 if x.valueOf != nil {
382 return x.valueOf(v)
383 }
384 return x.ExtensionType.ValueOf(v)
385}
386func (x *legacyExtensionType) InterfaceOf(v pref.Value) interface{} {
387 if x.interfaceOf != nil {
388 return x.interfaceOf(v)
389 }
390 return x.ExtensionType.InterfaceOf(v)
391}