blob: 9b74c0377944d758ba4441aeeada6c175ab10f00 [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
28 // New returns a new field value.
29 // For scalars, it returns the default value of the field.
30 // For composite types, it returns a new mutable value.
Damien Neil954bd922019-07-17 16:52:10 -070031 New() pref.Value
Damien Neild4f08002019-08-07 12:21:41 -070032
33 // Zero returns a new field value.
34 // For scalars, it returns the default value of the field.
35 // For composite types, it returns an immutable, empty value.
36 Zero() pref.Value
Damien Neil954bd922019-07-17 16:52:10 -070037}
38
39// NewConverter matches a Go type with a protobuf field and returns a Converter
40// that converts between the two. Enums must be a named int32 kind that
41// implements protoreflect.Enum, and messages must be pointer to a named
42// struct type that implements protoreflect.ProtoMessage.
43//
44// This matcher deliberately supports a wider range of Go types than what
45// protoc-gen-go historically generated to be able to automatically wrap some
46// v1 messages generated by other forks of protoc-gen-go.
47func NewConverter(t reflect.Type, fd pref.FieldDescriptor) Converter {
48 switch {
49 case fd.IsList():
50 return newListConverter(t, fd)
51 case fd.IsMap():
52 return newMapConverter(t, fd)
53 default:
54 return newSingularConverter(t, fd)
55 }
56 panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName()))
57}
58
59var (
60 boolType = reflect.TypeOf(bool(false))
61 int32Type = reflect.TypeOf(int32(0))
62 int64Type = reflect.TypeOf(int64(0))
63 uint32Type = reflect.TypeOf(uint32(0))
64 uint64Type = reflect.TypeOf(uint64(0))
65 float32Type = reflect.TypeOf(float32(0))
66 float64Type = reflect.TypeOf(float64(0))
67 stringType = reflect.TypeOf(string(""))
68 bytesType = reflect.TypeOf([]byte(nil))
69 byteType = reflect.TypeOf(byte(0))
70)
71
Damien Neilf5274512019-08-05 10:48:38 -070072var (
73 boolZero = pref.ValueOf(bool(false))
74 int32Zero = pref.ValueOf(int32(0))
75 int64Zero = pref.ValueOf(int64(0))
76 uint32Zero = pref.ValueOf(uint32(0))
77 uint64Zero = pref.ValueOf(uint64(0))
78 float32Zero = pref.ValueOf(float32(0))
79 float64Zero = pref.ValueOf(float64(0))
80 stringZero = pref.ValueOf(string(""))
81 bytesZero = pref.ValueOf([]byte(nil))
82)
83
Damien Neil954bd922019-07-17 16:52:10 -070084func newSingularConverter(t reflect.Type, fd pref.FieldDescriptor) Converter {
Damien Neilf5274512019-08-05 10:48:38 -070085 defVal := func(fd pref.FieldDescriptor, zero pref.Value) pref.Value {
86 if fd.Cardinality() == pref.Repeated {
87 // Default isn't defined for repeated fields.
88 return zero
89 }
90 return fd.Default()
91 }
Damien Neil954bd922019-07-17 16:52:10 -070092 switch fd.Kind() {
93 case pref.BoolKind:
94 if t.Kind() == reflect.Bool {
Damien Neilc5060d22019-08-22 17:01:56 -070095 return &boolConverter{t, defVal(fd, boolZero)}
Damien Neil954bd922019-07-17 16:52:10 -070096 }
97 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
98 if t.Kind() == reflect.Int32 {
Damien Neilc5060d22019-08-22 17:01:56 -070099 return &int32Converter{t, defVal(fd, int32Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700100 }
101 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
102 if t.Kind() == reflect.Int64 {
Damien Neilc5060d22019-08-22 17:01:56 -0700103 return &int64Converter{t, defVal(fd, int64Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700104 }
105 case pref.Uint32Kind, pref.Fixed32Kind:
106 if t.Kind() == reflect.Uint32 {
Damien Neilc5060d22019-08-22 17:01:56 -0700107 return &uint32Converter{t, defVal(fd, uint32Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700108 }
109 case pref.Uint64Kind, pref.Fixed64Kind:
110 if t.Kind() == reflect.Uint64 {
Damien Neilc5060d22019-08-22 17:01:56 -0700111 return &uint64Converter{t, defVal(fd, uint64Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700112 }
113 case pref.FloatKind:
114 if t.Kind() == reflect.Float32 {
Damien Neilc5060d22019-08-22 17:01:56 -0700115 return &float32Converter{t, defVal(fd, float32Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700116 }
117 case pref.DoubleKind:
118 if t.Kind() == reflect.Float64 {
Damien Neilc5060d22019-08-22 17:01:56 -0700119 return &float64Converter{t, defVal(fd, float64Zero)}
Damien Neil954bd922019-07-17 16:52:10 -0700120 }
121 case pref.StringKind:
122 if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
Damien Neilc5060d22019-08-22 17:01:56 -0700123 return &stringConverter{t, defVal(fd, stringZero)}
Damien Neil954bd922019-07-17 16:52:10 -0700124 }
125 case pref.BytesKind:
126 if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
Damien Neilc5060d22019-08-22 17:01:56 -0700127 return &bytesConverter{t, defVal(fd, bytesZero)}
Damien Neil954bd922019-07-17 16:52:10 -0700128 }
129 case pref.EnumKind:
130 // Handle enums, which must be a named int32 type.
131 if t.Kind() == reflect.Int32 {
132 return newEnumConverter(t, fd)
133 }
134 case pref.MessageKind, pref.GroupKind:
135 return newMessageConverter(t)
136 }
137 panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName()))
138}
139
Damien Neilc5060d22019-08-22 17:01:56 -0700140type boolConverter struct {
141 goType reflect.Type
142 def pref.Value
143}
144
145func (c *boolConverter) PBValueOf(v reflect.Value) pref.Value {
Damien Neil954bd922019-07-17 16:52:10 -0700146 if v.Type() != c.goType {
147 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
148 }
Damien Neilc5060d22019-08-22 17:01:56 -0700149 return pref.ValueOfBool(v.Bool())
150}
151func (c *boolConverter) GoValueOf(v pref.Value) reflect.Value {
152 return reflect.ValueOf(v.Bool()).Convert(c.goType)
153}
154func (c *boolConverter) New() pref.Value { return c.def }
155func (c *boolConverter) Zero() pref.Value { return c.def }
156
157type int32Converter struct {
158 goType reflect.Type
159 def pref.Value
Damien Neil954bd922019-07-17 16:52:10 -0700160}
161
Damien Neilc5060d22019-08-22 17:01:56 -0700162func (c *int32Converter) PBValueOf(v reflect.Value) pref.Value {
163 if v.Type() != c.goType {
164 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
Damien Neil954bd922019-07-17 16:52:10 -0700165 }
Damien Neilc5060d22019-08-22 17:01:56 -0700166 return pref.ValueOfInt32(int32(v.Int()))
167}
168func (c *int32Converter) GoValueOf(v pref.Value) reflect.Value {
169 return reflect.ValueOf(int32(v.Int())).Convert(c.goType)
170}
171func (c *int32Converter) New() pref.Value { return c.def }
172func (c *int32Converter) Zero() pref.Value { return c.def }
173
174type int64Converter struct {
175 goType reflect.Type
176 def pref.Value
177}
178
179func (c *int64Converter) PBValueOf(v reflect.Value) pref.Value {
180 if v.Type() != c.goType {
181 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
182 }
183 return pref.ValueOfInt64(int64(v.Int()))
184}
185func (c *int64Converter) GoValueOf(v pref.Value) reflect.Value {
186 return reflect.ValueOf(int64(v.Int())).Convert(c.goType)
187}
188func (c *int64Converter) New() pref.Value { return c.def }
189func (c *int64Converter) Zero() pref.Value { return c.def }
190
191type uint32Converter struct {
192 goType reflect.Type
193 def pref.Value
194}
195
196func (c *uint32Converter) PBValueOf(v reflect.Value) pref.Value {
197 if v.Type() != c.goType {
198 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
199 }
200 return pref.ValueOfUint32(uint32(v.Uint()))
201}
202func (c *uint32Converter) GoValueOf(v pref.Value) reflect.Value {
203 return reflect.ValueOf(uint32(v.Uint())).Convert(c.goType)
204}
205func (c *uint32Converter) New() pref.Value { return c.def }
206func (c *uint32Converter) Zero() pref.Value { return c.def }
207
208type uint64Converter struct {
209 goType reflect.Type
210 def pref.Value
211}
212
213func (c *uint64Converter) PBValueOf(v reflect.Value) pref.Value {
214 if v.Type() != c.goType {
215 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
216 }
217 return pref.ValueOfUint64(uint64(v.Uint()))
218}
219func (c *uint64Converter) GoValueOf(v pref.Value) reflect.Value {
220 return reflect.ValueOf(uint64(v.Uint())).Convert(c.goType)
221}
222func (c *uint64Converter) New() pref.Value { return c.def }
223func (c *uint64Converter) Zero() pref.Value { return c.def }
224
225type float32Converter struct {
226 goType reflect.Type
227 def pref.Value
228}
229
230func (c *float32Converter) PBValueOf(v reflect.Value) pref.Value {
231 if v.Type() != c.goType {
232 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
233 }
234 return pref.ValueOfFloat32(float32(v.Float()))
235}
236func (c *float32Converter) GoValueOf(v pref.Value) reflect.Value {
237 return reflect.ValueOf(float32(v.Float())).Convert(c.goType)
238}
239func (c *float32Converter) New() pref.Value { return c.def }
240func (c *float32Converter) Zero() pref.Value { return c.def }
241
242type float64Converter struct {
243 goType reflect.Type
244 def pref.Value
245}
246
247func (c *float64Converter) 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.ValueOfFloat64(float64(v.Float()))
252}
253func (c *float64Converter) GoValueOf(v pref.Value) reflect.Value {
254 return reflect.ValueOf(float64(v.Float())).Convert(c.goType)
255}
256func (c *float64Converter) New() pref.Value { return c.def }
257func (c *float64Converter) Zero() pref.Value { return c.def }
258
259type stringConverter struct {
260 goType reflect.Type
261 def pref.Value
262}
263
264func (c *stringConverter) PBValueOf(v reflect.Value) pref.Value {
265 if v.Type() != c.goType {
266 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
267 }
268 return pref.ValueOfString(v.Convert(stringType).String())
269}
270func (c *stringConverter) GoValueOf(v pref.Value) reflect.Value {
271 // pref.Value.String never panics, so we go through an interface
272 // conversion here to check the type.
273 s := v.Interface().(string)
274 if c.goType.Kind() == reflect.Slice && s == "" {
Damien Neil954bd922019-07-17 16:52:10 -0700275 return reflect.Zero(c.goType) // ensure empty string is []byte(nil)
276 }
Damien Neilc5060d22019-08-22 17:01:56 -0700277 return reflect.ValueOf(s).Convert(c.goType)
278}
279func (c *stringConverter) New() pref.Value { return c.def }
280func (c *stringConverter) Zero() pref.Value { return c.def }
281
282type bytesConverter struct {
283 goType reflect.Type
284 def pref.Value
Damien Neil954bd922019-07-17 16:52:10 -0700285}
286
Damien Neilc5060d22019-08-22 17:01:56 -0700287func (c *bytesConverter) PBValueOf(v reflect.Value) pref.Value {
288 if v.Type() != c.goType {
289 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
Damien Neilf5274512019-08-05 10:48:38 -0700290 }
Damien Neilc5060d22019-08-22 17:01:56 -0700291 if c.goType.Kind() == reflect.String && v.Len() == 0 {
292 return pref.ValueOfBytes(nil) // ensure empty string is []byte(nil)
293 }
294 return pref.ValueOfBytes(v.Convert(bytesType).Bytes())
Damien Neil954bd922019-07-17 16:52:10 -0700295}
Damien Neilc5060d22019-08-22 17:01:56 -0700296func (c *bytesConverter) GoValueOf(v pref.Value) reflect.Value {
297 return reflect.ValueOf(v.Bytes()).Convert(c.goType)
Damien Neild4f08002019-08-07 12:21:41 -0700298}
Damien Neilc5060d22019-08-22 17:01:56 -0700299func (c *bytesConverter) New() pref.Value { return c.def }
300func (c *bytesConverter) Zero() pref.Value { return c.def }
Damien Neild4f08002019-08-07 12:21:41 -0700301
Damien Neil954bd922019-07-17 16:52:10 -0700302type enumConverter struct {
303 goType reflect.Type
304 def pref.Value
305}
306
307func newEnumConverter(goType reflect.Type, fd pref.FieldDescriptor) Converter {
Damien Neilf5274512019-08-05 10:48:38 -0700308 var def pref.Value
309 if fd.Cardinality() == pref.Repeated {
310 def = pref.ValueOf(fd.Enum().Values().Get(0).Number())
311 } else {
312 def = fd.Default()
313 }
314 return &enumConverter{goType, def}
Damien Neil954bd922019-07-17 16:52:10 -0700315}
316
317func (c *enumConverter) PBValueOf(v reflect.Value) pref.Value {
318 if v.Type() != c.goType {
319 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
320 }
321 return pref.ValueOf(pref.EnumNumber(v.Int()))
322}
323
324func (c *enumConverter) GoValueOf(v pref.Value) reflect.Value {
325 return reflect.ValueOf(v.Enum()).Convert(c.goType)
326}
327
328func (c *enumConverter) New() pref.Value {
329 return c.def
330}
331
Damien Neild4f08002019-08-07 12:21:41 -0700332func (c *enumConverter) Zero() pref.Value {
333 return c.def
334}
335
Damien Neil954bd922019-07-17 16:52:10 -0700336type messageConverter struct {
337 goType reflect.Type
338}
339
340func newMessageConverter(goType reflect.Type) Converter {
341 return &messageConverter{goType}
342}
343
344func (c *messageConverter) PBValueOf(v reflect.Value) pref.Value {
345 if v.Type() != c.goType {
346 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
347 }
348 if m, ok := v.Interface().(pref.ProtoMessage); ok {
349 return pref.ValueOf(m.ProtoReflect())
350 }
351 return pref.ValueOf(legacyWrapMessage(v).ProtoReflect())
352}
353
354func (c *messageConverter) GoValueOf(v pref.Value) reflect.Value {
355 m := v.Message()
356 var rv reflect.Value
357 if u, ok := m.(Unwrapper); ok {
358 rv = reflect.ValueOf(u.ProtoUnwrap())
359 } else {
360 rv = reflect.ValueOf(m.Interface())
361 }
362 if rv.Type() != c.goType {
363 panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), c.goType))
364 }
365 return rv
366}
367
368func (c *messageConverter) New() pref.Value {
369 return c.PBValueOf(reflect.New(c.goType.Elem()))
370}
Damien Neild4f08002019-08-07 12:21:41 -0700371
372func (c *messageConverter) Zero() pref.Value {
373 return c.PBValueOf(reflect.Zero(c.goType))
374}