blob: 2186b268be15b8114aff96eaf899bb365fa4a2ed [file] [log] [blame]
Damien Neil954bd922019-07-17 16:52:10 -07001// 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
11 pref "google.golang.org/protobuf/reflect/protoreflect"
12)
13
14// Unwrapper unwraps the value to the underlying value.
15// This is implemented by List and Map.
16type Unwrapper interface {
17 ProtoUnwrap() interface{}
18}
19
20// A Converter coverts to/from Go reflect.Value types and protobuf protoreflect.Value types.
21type Converter interface {
Damien Neild4f08002019-08-07 12:21:41 -070022 // PBValueOf converts a reflect.Value to a protoreflect.Value.
Damien Neil954bd922019-07-17 16:52:10 -070023 PBValueOf(reflect.Value) pref.Value
Damien Neild4f08002019-08-07 12:21:41 -070024
25 // GoValueOf converts a protoreflect.Value to a reflect.Value.
Damien Neil954bd922019-07-17 16:52:10 -070026 GoValueOf(pref.Value) reflect.Value
Damien Neild4f08002019-08-07 12:21:41 -070027
Damien Neil835b2712019-08-29 14:08:28 -070028 // IsValidPB returns whether a protoreflect.Value is compatible with this type.
29 IsValidPB(pref.Value) bool
30
31 // IsValidGo returns whether a reflect.Value is compatible with this type.
32 IsValidGo(reflect.Value) bool
33
Damien Neild4f08002019-08-07 12:21:41 -070034 // New returns a new field value.
35 // For scalars, it returns the default value of the field.
36 // For composite types, it returns a new mutable value.
Damien Neil954bd922019-07-17 16:52:10 -070037 New() pref.Value
Damien Neild4f08002019-08-07 12:21:41 -070038
39 // Zero returns a new field value.
40 // For scalars, it returns the default value of the field.
41 // For composite types, it returns an immutable, empty value.
42 Zero() pref.Value
Damien Neil954bd922019-07-17 16:52:10 -070043}
44
45// NewConverter matches a Go type with a protobuf field and returns a Converter
46// that converts between the two. Enums must be a named int32 kind that
47// implements protoreflect.Enum, and messages must be pointer to a named
48// struct type that implements protoreflect.ProtoMessage.
49//
50// This matcher deliberately supports a wider range of Go types than what
51// protoc-gen-go historically generated to be able to automatically wrap some
52// v1 messages generated by other forks of protoc-gen-go.
53func NewConverter(t reflect.Type, fd pref.FieldDescriptor) Converter {
54 switch {
55 case fd.IsList():
56 return newListConverter(t, fd)
57 case fd.IsMap():
58 return newMapConverter(t, fd)
59 default:
60 return newSingularConverter(t, fd)
61 }
62 panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName()))
63}
64
65var (
66 boolType = reflect.TypeOf(bool(false))
67 int32Type = reflect.TypeOf(int32(0))
68 int64Type = reflect.TypeOf(int64(0))
69 uint32Type = reflect.TypeOf(uint32(0))
70 uint64Type = reflect.TypeOf(uint64(0))
71 float32Type = reflect.TypeOf(float32(0))
72 float64Type = reflect.TypeOf(float64(0))
73 stringType = reflect.TypeOf(string(""))
74 bytesType = reflect.TypeOf([]byte(nil))
75 byteType = reflect.TypeOf(byte(0))
76)
77
Damien Neilf5274512019-08-05 10:48:38 -070078var (
79 boolZero = pref.ValueOf(bool(false))
80 int32Zero = pref.ValueOf(int32(0))
81 int64Zero = pref.ValueOf(int64(0))
82 uint32Zero = pref.ValueOf(uint32(0))
83 uint64Zero = pref.ValueOf(uint64(0))
84 float32Zero = pref.ValueOf(float32(0))
85 float64Zero = pref.ValueOf(float64(0))
86 stringZero = pref.ValueOf(string(""))
87 bytesZero = pref.ValueOf([]byte(nil))
88)
89
Damien Neil954bd922019-07-17 16:52:10 -070090func newSingularConverter(t reflect.Type, fd pref.FieldDescriptor) Converter {
Damien Neilf5274512019-08-05 10:48:38 -070091 defVal := func(fd pref.FieldDescriptor, zero pref.Value) pref.Value {
92 if fd.Cardinality() == pref.Repeated {
93 // Default isn't defined for repeated fields.
94 return zero
95 }
96 return fd.Default()
97 }
Damien Neil954bd922019-07-17 16:52:10 -070098 switch fd.Kind() {
99 case pref.BoolKind:
100 if t.Kind() == reflect.Bool {
Damien Neilc5060d22019-08-22 17:01:56 -0700101 return &boolConverter{t, defVal(fd, boolZero)}
Damien Neil954bd922019-07-17 16:52:10 -0700102 }
103 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
104 if t.Kind() == reflect.Int32 {
Damien Neilc5060d22019-08-22 17:01:56 -0700105 return &int32Converter{t, defVal(fd, int32Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700106 }
107 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
108 if t.Kind() == reflect.Int64 {
Damien Neilc5060d22019-08-22 17:01:56 -0700109 return &int64Converter{t, defVal(fd, int64Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700110 }
111 case pref.Uint32Kind, pref.Fixed32Kind:
112 if t.Kind() == reflect.Uint32 {
Damien Neilc5060d22019-08-22 17:01:56 -0700113 return &uint32Converter{t, defVal(fd, uint32Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700114 }
115 case pref.Uint64Kind, pref.Fixed64Kind:
116 if t.Kind() == reflect.Uint64 {
Damien Neilc5060d22019-08-22 17:01:56 -0700117 return &uint64Converter{t, defVal(fd, uint64Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700118 }
119 case pref.FloatKind:
120 if t.Kind() == reflect.Float32 {
Damien Neilc5060d22019-08-22 17:01:56 -0700121 return &float32Converter{t, defVal(fd, float32Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700122 }
123 case pref.DoubleKind:
124 if t.Kind() == reflect.Float64 {
Damien Neilc5060d22019-08-22 17:01:56 -0700125 return &float64Converter{t, defVal(fd, float64Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700126 }
127 case pref.StringKind:
128 if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
Damien Neilc5060d22019-08-22 17:01:56 -0700129 return &stringConverter{t, defVal(fd, stringZero)}
Damien Neil954bd922019-07-17 16:52:10 -0700130 }
131 case pref.BytesKind:
132 if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
Damien Neilc5060d22019-08-22 17:01:56 -0700133 return &bytesConverter{t, defVal(fd, bytesZero)}
Damien Neil954bd922019-07-17 16:52:10 -0700134 }
135 case pref.EnumKind:
136 // Handle enums, which must be a named int32 type.
137 if t.Kind() == reflect.Int32 {
138 return newEnumConverter(t, fd)
139 }
140 case pref.MessageKind, pref.GroupKind:
141 return newMessageConverter(t)
142 }
143 panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName()))
144}
145
Damien Neilc5060d22019-08-22 17:01:56 -0700146type boolConverter struct {
147 goType reflect.Type
148 def pref.Value
149}
150
151func (c *boolConverter) PBValueOf(v reflect.Value) pref.Value {
Damien Neil954bd922019-07-17 16:52:10 -0700152 if v.Type() != c.goType {
153 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
154 }
Damien Neilc5060d22019-08-22 17:01:56 -0700155 return pref.ValueOfBool(v.Bool())
156}
157func (c *boolConverter) GoValueOf(v pref.Value) reflect.Value {
158 return reflect.ValueOf(v.Bool()).Convert(c.goType)
159}
Damien Neil835b2712019-08-29 14:08:28 -0700160func (c *boolConverter) IsValidPB(v pref.Value) bool {
161 _, ok := v.Interface().(bool)
162 return ok
163}
164func (c *boolConverter) IsValidGo(v reflect.Value) bool {
165 return v.Type() == c.goType
166}
Damien Neilc5060d22019-08-22 17:01:56 -0700167func (c *boolConverter) New() pref.Value { return c.def }
168func (c *boolConverter) Zero() pref.Value { return c.def }
169
170type int32Converter struct {
171 goType reflect.Type
172 def pref.Value
Damien Neil954bd922019-07-17 16:52:10 -0700173}
174
Damien Neilc5060d22019-08-22 17:01:56 -0700175func (c *int32Converter) PBValueOf(v reflect.Value) pref.Value {
176 if v.Type() != c.goType {
177 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
Damien Neil954bd922019-07-17 16:52:10 -0700178 }
Damien Neilc5060d22019-08-22 17:01:56 -0700179 return pref.ValueOfInt32(int32(v.Int()))
180}
181func (c *int32Converter) GoValueOf(v pref.Value) reflect.Value {
182 return reflect.ValueOf(int32(v.Int())).Convert(c.goType)
183}
Damien Neil835b2712019-08-29 14:08:28 -0700184func (c *int32Converter) IsValidPB(v pref.Value) bool {
185 _, ok := v.Interface().(int32)
186 return ok
187}
188func (c *int32Converter) IsValidGo(v reflect.Value) bool {
189 return v.Type() == c.goType
190}
Damien Neilc5060d22019-08-22 17:01:56 -0700191func (c *int32Converter) New() pref.Value { return c.def }
192func (c *int32Converter) Zero() pref.Value { return c.def }
193
194type int64Converter struct {
195 goType reflect.Type
196 def pref.Value
197}
198
199func (c *int64Converter) PBValueOf(v reflect.Value) pref.Value {
200 if v.Type() != c.goType {
201 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
202 }
203 return pref.ValueOfInt64(int64(v.Int()))
204}
205func (c *int64Converter) GoValueOf(v pref.Value) reflect.Value {
206 return reflect.ValueOf(int64(v.Int())).Convert(c.goType)
207}
Damien Neil835b2712019-08-29 14:08:28 -0700208func (c *int64Converter) IsValidPB(v pref.Value) bool {
209 _, ok := v.Interface().(int64)
210 return ok
211}
212func (c *int64Converter) IsValidGo(v reflect.Value) bool {
213 return v.Type() == c.goType
214}
Damien Neilc5060d22019-08-22 17:01:56 -0700215func (c *int64Converter) New() pref.Value { return c.def }
216func (c *int64Converter) Zero() pref.Value { return c.def }
217
218type uint32Converter struct {
219 goType reflect.Type
220 def pref.Value
221}
222
223func (c *uint32Converter) PBValueOf(v reflect.Value) pref.Value {
224 if v.Type() != c.goType {
225 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
226 }
227 return pref.ValueOfUint32(uint32(v.Uint()))
228}
229func (c *uint32Converter) GoValueOf(v pref.Value) reflect.Value {
230 return reflect.ValueOf(uint32(v.Uint())).Convert(c.goType)
231}
Damien Neil835b2712019-08-29 14:08:28 -0700232func (c *uint32Converter) IsValidPB(v pref.Value) bool {
233 _, ok := v.Interface().(uint32)
234 return ok
235}
236func (c *uint32Converter) IsValidGo(v reflect.Value) bool {
237 return v.Type() == c.goType
238}
Damien Neilc5060d22019-08-22 17:01:56 -0700239func (c *uint32Converter) New() pref.Value { return c.def }
240func (c *uint32Converter) Zero() pref.Value { return c.def }
241
242type uint64Converter struct {
243 goType reflect.Type
244 def pref.Value
245}
246
247func (c *uint64Converter) PBValueOf(v reflect.Value) pref.Value {
248 if v.Type() != c.goType {
249 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
250 }
251 return pref.ValueOfUint64(uint64(v.Uint()))
252}
253func (c *uint64Converter) GoValueOf(v pref.Value) reflect.Value {
254 return reflect.ValueOf(uint64(v.Uint())).Convert(c.goType)
255}
Damien Neil835b2712019-08-29 14:08:28 -0700256func (c *uint64Converter) IsValidPB(v pref.Value) bool {
257 _, ok := v.Interface().(uint64)
258 return ok
259}
260func (c *uint64Converter) IsValidGo(v reflect.Value) bool {
261 return v.Type() == c.goType
262}
Damien Neilc5060d22019-08-22 17:01:56 -0700263func (c *uint64Converter) New() pref.Value { return c.def }
264func (c *uint64Converter) Zero() pref.Value { return c.def }
265
266type float32Converter struct {
267 goType reflect.Type
268 def pref.Value
269}
270
271func (c *float32Converter) PBValueOf(v reflect.Value) pref.Value {
272 if v.Type() != c.goType {
273 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
274 }
275 return pref.ValueOfFloat32(float32(v.Float()))
276}
277func (c *float32Converter) GoValueOf(v pref.Value) reflect.Value {
278 return reflect.ValueOf(float32(v.Float())).Convert(c.goType)
279}
Damien Neil835b2712019-08-29 14:08:28 -0700280func (c *float32Converter) IsValidPB(v pref.Value) bool {
281 _, ok := v.Interface().(float32)
282 return ok
283}
284func (c *float32Converter) IsValidGo(v reflect.Value) bool {
285 return v.Type() == c.goType
286}
Damien Neilc5060d22019-08-22 17:01:56 -0700287func (c *float32Converter) New() pref.Value { return c.def }
288func (c *float32Converter) Zero() pref.Value { return c.def }
289
290type float64Converter struct {
291 goType reflect.Type
292 def pref.Value
293}
294
295func (c *float64Converter) PBValueOf(v reflect.Value) pref.Value {
296 if v.Type() != c.goType {
297 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
298 }
299 return pref.ValueOfFloat64(float64(v.Float()))
300}
301func (c *float64Converter) GoValueOf(v pref.Value) reflect.Value {
302 return reflect.ValueOf(float64(v.Float())).Convert(c.goType)
303}
Damien Neil835b2712019-08-29 14:08:28 -0700304func (c *float64Converter) IsValidPB(v pref.Value) bool {
305 _, ok := v.Interface().(float64)
306 return ok
307}
308func (c *float64Converter) IsValidGo(v reflect.Value) bool {
309 return v.Type() == c.goType
310}
Damien Neilc5060d22019-08-22 17:01:56 -0700311func (c *float64Converter) New() pref.Value { return c.def }
312func (c *float64Converter) Zero() pref.Value { return c.def }
313
314type stringConverter struct {
315 goType reflect.Type
316 def pref.Value
317}
318
319func (c *stringConverter) PBValueOf(v reflect.Value) pref.Value {
320 if v.Type() != c.goType {
321 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
322 }
323 return pref.ValueOfString(v.Convert(stringType).String())
324}
325func (c *stringConverter) GoValueOf(v pref.Value) reflect.Value {
326 // pref.Value.String never panics, so we go through an interface
327 // conversion here to check the type.
328 s := v.Interface().(string)
329 if c.goType.Kind() == reflect.Slice && s == "" {
Damien Neil954bd922019-07-17 16:52:10 -0700330 return reflect.Zero(c.goType) // ensure empty string is []byte(nil)
331 }
Damien Neilc5060d22019-08-22 17:01:56 -0700332 return reflect.ValueOf(s).Convert(c.goType)
333}
Damien Neil835b2712019-08-29 14:08:28 -0700334func (c *stringConverter) IsValidPB(v pref.Value) bool {
335 _, ok := v.Interface().(string)
336 return ok
337}
338func (c *stringConverter) IsValidGo(v reflect.Value) bool {
339 return v.Type() == c.goType
340}
Damien Neilc5060d22019-08-22 17:01:56 -0700341func (c *stringConverter) New() pref.Value { return c.def }
342func (c *stringConverter) Zero() pref.Value { return c.def }
343
344type bytesConverter struct {
345 goType reflect.Type
346 def pref.Value
Damien Neil954bd922019-07-17 16:52:10 -0700347}
348
Damien Neilc5060d22019-08-22 17:01:56 -0700349func (c *bytesConverter) PBValueOf(v reflect.Value) pref.Value {
350 if v.Type() != c.goType {
351 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
Damien Neilf5274512019-08-05 10:48:38 -0700352 }
Damien Neilc5060d22019-08-22 17:01:56 -0700353 if c.goType.Kind() == reflect.String && v.Len() == 0 {
354 return pref.ValueOfBytes(nil) // ensure empty string is []byte(nil)
355 }
356 return pref.ValueOfBytes(v.Convert(bytesType).Bytes())
Damien Neil954bd922019-07-17 16:52:10 -0700357}
Damien Neilc5060d22019-08-22 17:01:56 -0700358func (c *bytesConverter) GoValueOf(v pref.Value) reflect.Value {
359 return reflect.ValueOf(v.Bytes()).Convert(c.goType)
Damien Neild4f08002019-08-07 12:21:41 -0700360}
Damien Neil835b2712019-08-29 14:08:28 -0700361func (c *bytesConverter) IsValidPB(v pref.Value) bool {
362 _, ok := v.Interface().([]byte)
363 return ok
364}
365func (c *bytesConverter) IsValidGo(v reflect.Value) bool {
366 return v.Type() == c.goType
367}
Damien Neilc5060d22019-08-22 17:01:56 -0700368func (c *bytesConverter) New() pref.Value { return c.def }
369func (c *bytesConverter) Zero() pref.Value { return c.def }
Damien Neild4f08002019-08-07 12:21:41 -0700370
Damien Neil954bd922019-07-17 16:52:10 -0700371type enumConverter struct {
372 goType reflect.Type
373 def pref.Value
374}
375
376func newEnumConverter(goType reflect.Type, fd pref.FieldDescriptor) Converter {
Damien Neilf5274512019-08-05 10:48:38 -0700377 var def pref.Value
378 if fd.Cardinality() == pref.Repeated {
379 def = pref.ValueOf(fd.Enum().Values().Get(0).Number())
380 } else {
381 def = fd.Default()
382 }
383 return &enumConverter{goType, def}
Damien Neil954bd922019-07-17 16:52:10 -0700384}
385
386func (c *enumConverter) PBValueOf(v reflect.Value) pref.Value {
387 if v.Type() != c.goType {
388 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
389 }
390 return pref.ValueOf(pref.EnumNumber(v.Int()))
391}
392
393func (c *enumConverter) GoValueOf(v pref.Value) reflect.Value {
394 return reflect.ValueOf(v.Enum()).Convert(c.goType)
395}
396
Damien Neil835b2712019-08-29 14:08:28 -0700397func (c *enumConverter) IsValidPB(v pref.Value) bool {
398 _, ok := v.Interface().(pref.EnumNumber)
399 return ok
400}
401
402func (c *enumConverter) IsValidGo(v reflect.Value) bool {
403 return v.Type() == c.goType
404}
405
Damien Neil954bd922019-07-17 16:52:10 -0700406func (c *enumConverter) New() pref.Value {
407 return c.def
408}
409
Damien Neild4f08002019-08-07 12:21:41 -0700410func (c *enumConverter) Zero() pref.Value {
411 return c.def
412}
413
Damien Neil954bd922019-07-17 16:52:10 -0700414type messageConverter struct {
415 goType reflect.Type
416}
417
418func newMessageConverter(goType reflect.Type) Converter {
419 return &messageConverter{goType}
420}
421
422func (c *messageConverter) PBValueOf(v reflect.Value) pref.Value {
423 if v.Type() != c.goType {
424 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
425 }
426 if m, ok := v.Interface().(pref.ProtoMessage); ok {
427 return pref.ValueOf(m.ProtoReflect())
428 }
429 return pref.ValueOf(legacyWrapMessage(v).ProtoReflect())
430}
431
432func (c *messageConverter) GoValueOf(v pref.Value) reflect.Value {
433 m := v.Message()
434 var rv reflect.Value
435 if u, ok := m.(Unwrapper); ok {
436 rv = reflect.ValueOf(u.ProtoUnwrap())
437 } else {
438 rv = reflect.ValueOf(m.Interface())
439 }
440 if rv.Type() != c.goType {
441 panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), c.goType))
442 }
443 return rv
444}
445
Damien Neil835b2712019-08-29 14:08:28 -0700446func (c *messageConverter) IsValidPB(v pref.Value) bool {
447 m := v.Message()
448 var rv reflect.Value
449 if u, ok := m.(Unwrapper); ok {
450 rv = reflect.ValueOf(u.ProtoUnwrap())
451 } else {
452 rv = reflect.ValueOf(m.Interface())
453 }
454 return rv.Type() == c.goType
455}
456
457func (c *messageConverter) IsValidGo(v reflect.Value) bool {
458 return v.Type() == c.goType
459}
460
Damien Neil954bd922019-07-17 16:52:10 -0700461func (c *messageConverter) New() pref.Value {
462 return c.PBValueOf(reflect.New(c.goType.Elem()))
463}
Damien Neild4f08002019-08-07 12:21:41 -0700464
465func (c *messageConverter) Zero() pref.Value {
466 return c.PBValueOf(reflect.Zero(c.goType))
467}