Test Failed
Push — main ( 973aa1...436074 )
by Christian
02:37
created

impl.newSingularConverter   F

Complexity

Conditions 28

Size

Total Lines 54
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 28
eloc 39
nop 2
dl 0
loc 54
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like impl.newSingularConverter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
// 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
5
package impl
6
7
import (
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.
16
type unwrapper interface {
17
	protoUnwrap() interface{}
18
}
19
20
// A Converter coverts to/from Go reflect.Value types and protobuf protoreflect.Value types.
21
type Converter interface {
22
	// PBValueOf converts a reflect.Value to a protoreflect.Value.
23
	PBValueOf(reflect.Value) pref.Value
24
25
	// GoValueOf converts a protoreflect.Value to a reflect.Value.
26
	GoValueOf(pref.Value) reflect.Value
27
28
	// 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
34
	// 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.
37
	New() pref.Value
38
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
43
}
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.
53
func 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
65
var (
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
78
var (
79
	boolZero    = pref.ValueOfBool(false)
80
	int32Zero   = pref.ValueOfInt32(0)
81
	int64Zero   = pref.ValueOfInt64(0)
82
	uint32Zero  = pref.ValueOfUint32(0)
83
	uint64Zero  = pref.ValueOfUint64(0)
84
	float32Zero = pref.ValueOfFloat32(0)
85
	float64Zero = pref.ValueOfFloat64(0)
86
	stringZero  = pref.ValueOfString("")
87
	bytesZero   = pref.ValueOfBytes(nil)
88
)
89
90
func newSingularConverter(t reflect.Type, fd pref.FieldDescriptor) Converter {
91
	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
	}
98
	switch fd.Kind() {
99
	case pref.BoolKind:
100
		if t.Kind() == reflect.Bool {
101
			return &boolConverter{t, defVal(fd, boolZero)}
102
		}
103
	case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
104
		if t.Kind() == reflect.Int32 {
105
			return &int32Converter{t, defVal(fd, int32Zero)}
106
		}
107
	case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
108
		if t.Kind() == reflect.Int64 {
109
			return &int64Converter{t, defVal(fd, int64Zero)}
110
		}
111
	case pref.Uint32Kind, pref.Fixed32Kind:
112
		if t.Kind() == reflect.Uint32 {
113
			return &uint32Converter{t, defVal(fd, uint32Zero)}
114
		}
115
	case pref.Uint64Kind, pref.Fixed64Kind:
116
		if t.Kind() == reflect.Uint64 {
117
			return &uint64Converter{t, defVal(fd, uint64Zero)}
118
		}
119
	case pref.FloatKind:
120
		if t.Kind() == reflect.Float32 {
121
			return &float32Converter{t, defVal(fd, float32Zero)}
122
		}
123
	case pref.DoubleKind:
124
		if t.Kind() == reflect.Float64 {
125
			return &float64Converter{t, defVal(fd, float64Zero)}
126
		}
127
	case pref.StringKind:
128
		if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
129
			return &stringConverter{t, defVal(fd, stringZero)}
130
		}
131
	case pref.BytesKind:
132
		if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
133
			return &bytesConverter{t, defVal(fd, bytesZero)}
134
		}
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
146
type boolConverter struct {
147
	goType reflect.Type
148
	def    pref.Value
149
}
150
151
func (c *boolConverter) PBValueOf(v reflect.Value) pref.Value {
152
	if v.Type() != c.goType {
153
		panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
154
	}
155
	return pref.ValueOfBool(v.Bool())
156
}
157
func (c *boolConverter) GoValueOf(v pref.Value) reflect.Value {
158
	return reflect.ValueOf(v.Bool()).Convert(c.goType)
159
}
160
func (c *boolConverter) IsValidPB(v pref.Value) bool {
161
	_, ok := v.Interface().(bool)
162
	return ok
163
}
164
func (c *boolConverter) IsValidGo(v reflect.Value) bool {
165
	return v.IsValid() && v.Type() == c.goType
166
}
167
func (c *boolConverter) New() pref.Value  { return c.def }
168
func (c *boolConverter) Zero() pref.Value { return c.def }
169
170
type int32Converter struct {
171
	goType reflect.Type
172
	def    pref.Value
173
}
174
175
func (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))
178
	}
179
	return pref.ValueOfInt32(int32(v.Int()))
180
}
181
func (c *int32Converter) GoValueOf(v pref.Value) reflect.Value {
182
	return reflect.ValueOf(int32(v.Int())).Convert(c.goType)
183
}
184
func (c *int32Converter) IsValidPB(v pref.Value) bool {
185
	_, ok := v.Interface().(int32)
186
	return ok
187
}
188
func (c *int32Converter) IsValidGo(v reflect.Value) bool {
189
	return v.IsValid() && v.Type() == c.goType
190
}
191
func (c *int32Converter) New() pref.Value  { return c.def }
192
func (c *int32Converter) Zero() pref.Value { return c.def }
193
194
type int64Converter struct {
195
	goType reflect.Type
196
	def    pref.Value
197
}
198
199
func (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
}
205
func (c *int64Converter) GoValueOf(v pref.Value) reflect.Value {
206
	return reflect.ValueOf(int64(v.Int())).Convert(c.goType)
207
}
208
func (c *int64Converter) IsValidPB(v pref.Value) bool {
209
	_, ok := v.Interface().(int64)
210
	return ok
211
}
212
func (c *int64Converter) IsValidGo(v reflect.Value) bool {
213
	return v.IsValid() && v.Type() == c.goType
214
}
215
func (c *int64Converter) New() pref.Value  { return c.def }
216
func (c *int64Converter) Zero() pref.Value { return c.def }
217
218
type uint32Converter struct {
219
	goType reflect.Type
220
	def    pref.Value
221
}
222
223
func (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
}
229
func (c *uint32Converter) GoValueOf(v pref.Value) reflect.Value {
230
	return reflect.ValueOf(uint32(v.Uint())).Convert(c.goType)
231
}
232
func (c *uint32Converter) IsValidPB(v pref.Value) bool {
233
	_, ok := v.Interface().(uint32)
234
	return ok
235
}
236
func (c *uint32Converter) IsValidGo(v reflect.Value) bool {
237
	return v.IsValid() && v.Type() == c.goType
238
}
239
func (c *uint32Converter) New() pref.Value  { return c.def }
240
func (c *uint32Converter) Zero() pref.Value { return c.def }
241
242
type uint64Converter struct {
243
	goType reflect.Type
244
	def    pref.Value
245
}
246
247
func (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
}
253
func (c *uint64Converter) GoValueOf(v pref.Value) reflect.Value {
254
	return reflect.ValueOf(uint64(v.Uint())).Convert(c.goType)
255
}
256
func (c *uint64Converter) IsValidPB(v pref.Value) bool {
257
	_, ok := v.Interface().(uint64)
258
	return ok
259
}
260
func (c *uint64Converter) IsValidGo(v reflect.Value) bool {
261
	return v.IsValid() && v.Type() == c.goType
262
}
263
func (c *uint64Converter) New() pref.Value  { return c.def }
264
func (c *uint64Converter) Zero() pref.Value { return c.def }
265
266
type float32Converter struct {
267
	goType reflect.Type
268
	def    pref.Value
269
}
270
271
func (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
}
277
func (c *float32Converter) GoValueOf(v pref.Value) reflect.Value {
278
	return reflect.ValueOf(float32(v.Float())).Convert(c.goType)
279
}
280
func (c *float32Converter) IsValidPB(v pref.Value) bool {
281
	_, ok := v.Interface().(float32)
282
	return ok
283
}
284
func (c *float32Converter) IsValidGo(v reflect.Value) bool {
285
	return v.IsValid() && v.Type() == c.goType
286
}
287
func (c *float32Converter) New() pref.Value  { return c.def }
288
func (c *float32Converter) Zero() pref.Value { return c.def }
289
290
type float64Converter struct {
291
	goType reflect.Type
292
	def    pref.Value
293
}
294
295
func (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
}
301
func (c *float64Converter) GoValueOf(v pref.Value) reflect.Value {
302
	return reflect.ValueOf(float64(v.Float())).Convert(c.goType)
303
}
304
func (c *float64Converter) IsValidPB(v pref.Value) bool {
305
	_, ok := v.Interface().(float64)
306
	return ok
307
}
308
func (c *float64Converter) IsValidGo(v reflect.Value) bool {
309
	return v.IsValid() && v.Type() == c.goType
310
}
311
func (c *float64Converter) New() pref.Value  { return c.def }
312
func (c *float64Converter) Zero() pref.Value { return c.def }
313
314
type stringConverter struct {
315
	goType reflect.Type
316
	def    pref.Value
317
}
318
319
func (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
}
325
func (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 == "" {
330
		return reflect.Zero(c.goType) // ensure empty string is []byte(nil)
331
	}
332
	return reflect.ValueOf(s).Convert(c.goType)
333
}
334
func (c *stringConverter) IsValidPB(v pref.Value) bool {
335
	_, ok := v.Interface().(string)
336
	return ok
337
}
338
func (c *stringConverter) IsValidGo(v reflect.Value) bool {
339
	return v.IsValid() && v.Type() == c.goType
340
}
341
func (c *stringConverter) New() pref.Value  { return c.def }
342
func (c *stringConverter) Zero() pref.Value { return c.def }
343
344
type bytesConverter struct {
345
	goType reflect.Type
346
	def    pref.Value
347
}
348
349
func (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))
352
	}
353
	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())
357
}
358
func (c *bytesConverter) GoValueOf(v pref.Value) reflect.Value {
359
	return reflect.ValueOf(v.Bytes()).Convert(c.goType)
360
}
361
func (c *bytesConverter) IsValidPB(v pref.Value) bool {
362
	_, ok := v.Interface().([]byte)
363
	return ok
364
}
365
func (c *bytesConverter) IsValidGo(v reflect.Value) bool {
366
	return v.IsValid() && v.Type() == c.goType
367
}
368
func (c *bytesConverter) New() pref.Value  { return c.def }
369
func (c *bytesConverter) Zero() pref.Value { return c.def }
370
371
type enumConverter struct {
372
	goType reflect.Type
373
	def    pref.Value
374
}
375
376
func newEnumConverter(goType reflect.Type, fd pref.FieldDescriptor) Converter {
377
	var def pref.Value
378
	if fd.Cardinality() == pref.Repeated {
379
		def = pref.ValueOfEnum(fd.Enum().Values().Get(0).Number())
380
	} else {
381
		def = fd.Default()
382
	}
383
	return &enumConverter{goType, def}
384
}
385
386
func (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.ValueOfEnum(pref.EnumNumber(v.Int()))
391
}
392
393
func (c *enumConverter) GoValueOf(v pref.Value) reflect.Value {
394
	return reflect.ValueOf(v.Enum()).Convert(c.goType)
395
}
396
397
func (c *enumConverter) IsValidPB(v pref.Value) bool {
398
	_, ok := v.Interface().(pref.EnumNumber)
399
	return ok
400
}
401
402
func (c *enumConverter) IsValidGo(v reflect.Value) bool {
403
	return v.IsValid() && v.Type() == c.goType
404
}
405
406
func (c *enumConverter) New() pref.Value {
407
	return c.def
408
}
409
410
func (c *enumConverter) Zero() pref.Value {
411
	return c.def
412
}
413
414
type messageConverter struct {
415
	goType reflect.Type
416
}
417
418
func newMessageConverter(goType reflect.Type) Converter {
419
	return &messageConverter{goType}
420
}
421
422
func (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 c.isNonPointer() {
427
		if v.CanAddr() {
428
			v = v.Addr() // T => *T
429
		} else {
430
			v = reflect.Zero(reflect.PtrTo(v.Type()))
431
		}
432
	}
433
	if m, ok := v.Interface().(pref.ProtoMessage); ok {
434
		return pref.ValueOfMessage(m.ProtoReflect())
435
	}
436
	return pref.ValueOfMessage(legacyWrapMessage(v))
437
}
438
439
func (c *messageConverter) GoValueOf(v pref.Value) reflect.Value {
440
	m := v.Message()
441
	var rv reflect.Value
442
	if u, ok := m.(unwrapper); ok {
443
		rv = reflect.ValueOf(u.protoUnwrap())
444
	} else {
445
		rv = reflect.ValueOf(m.Interface())
446
	}
447
	if c.isNonPointer() {
448
		if rv.Type() != reflect.PtrTo(c.goType) {
449
			panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), reflect.PtrTo(c.goType)))
450
		}
451
		if !rv.IsNil() {
452
			rv = rv.Elem() // *T => T
453
		} else {
454
			rv = reflect.Zero(rv.Type().Elem())
455
		}
456
	}
457
	if rv.Type() != c.goType {
458
		panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), c.goType))
459
	}
460
	return rv
461
}
462
463
func (c *messageConverter) IsValidPB(v pref.Value) bool {
464
	m := v.Message()
465
	var rv reflect.Value
466
	if u, ok := m.(unwrapper); ok {
467
		rv = reflect.ValueOf(u.protoUnwrap())
468
	} else {
469
		rv = reflect.ValueOf(m.Interface())
470
	}
471
	if c.isNonPointer() {
472
		return rv.Type() == reflect.PtrTo(c.goType)
473
	}
474
	return rv.Type() == c.goType
475
}
476
477
func (c *messageConverter) IsValidGo(v reflect.Value) bool {
478
	return v.IsValid() && v.Type() == c.goType
479
}
480
481
func (c *messageConverter) New() pref.Value {
482
	if c.isNonPointer() {
483
		return c.PBValueOf(reflect.New(c.goType).Elem())
484
	}
485
	return c.PBValueOf(reflect.New(c.goType.Elem()))
486
}
487
488
func (c *messageConverter) Zero() pref.Value {
489
	return c.PBValueOf(reflect.Zero(c.goType))
490
}
491
492
// isNonPointer reports whether the type is a non-pointer type.
493
// This never occurs for generated message types.
494
func (c *messageConverter) isNonPointer() bool {
495
	return c.goType.Kind() != reflect.Ptr
496
}
497