podman

Форк
0
543 строки · 15.1 Кб
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
	"math"
10
	"reflect"
11
	"sync"
12

13
	"google.golang.org/protobuf/internal/flags"
14
	"google.golang.org/protobuf/reflect/protoreflect"
15
	"google.golang.org/protobuf/reflect/protoregistry"
16
)
17

18
type fieldInfo struct {
19
	fieldDesc protoreflect.FieldDescriptor
20

21
	// These fields are used for protobuf reflection support.
22
	has        func(pointer) bool
23
	clear      func(pointer)
24
	get        func(pointer) protoreflect.Value
25
	set        func(pointer, protoreflect.Value)
26
	mutable    func(pointer) protoreflect.Value
27
	newMessage func() protoreflect.Message
28
	newField   func() protoreflect.Value
29
}
30

31
func fieldInfoForMissing(fd protoreflect.FieldDescriptor) fieldInfo {
32
	// This never occurs for generated message types.
33
	// It implies that a hand-crafted type has missing Go fields
34
	// for specific protobuf message fields.
35
	return fieldInfo{
36
		fieldDesc: fd,
37
		has: func(p pointer) bool {
38
			return false
39
		},
40
		clear: func(p pointer) {
41
			panic("missing Go struct field for " + string(fd.FullName()))
42
		},
43
		get: func(p pointer) protoreflect.Value {
44
			return fd.Default()
45
		},
46
		set: func(p pointer, v protoreflect.Value) {
47
			panic("missing Go struct field for " + string(fd.FullName()))
48
		},
49
		mutable: func(p pointer) protoreflect.Value {
50
			panic("missing Go struct field for " + string(fd.FullName()))
51
		},
52
		newMessage: func() protoreflect.Message {
53
			panic("missing Go struct field for " + string(fd.FullName()))
54
		},
55
		newField: func() protoreflect.Value {
56
			if v := fd.Default(); v.IsValid() {
57
				return v
58
			}
59
			panic("missing Go struct field for " + string(fd.FullName()))
60
		},
61
	}
62
}
63

64
func fieldInfoForOneof(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo {
65
	ft := fs.Type
66
	if ft.Kind() != reflect.Interface {
67
		panic(fmt.Sprintf("field %v has invalid type: got %v, want interface kind", fd.FullName(), ft))
68
	}
69
	if ot.Kind() != reflect.Struct {
70
		panic(fmt.Sprintf("field %v has invalid type: got %v, want struct kind", fd.FullName(), ot))
71
	}
72
	if !reflect.PtrTo(ot).Implements(ft) {
73
		panic(fmt.Sprintf("field %v has invalid type: %v does not implement %v", fd.FullName(), ot, ft))
74
	}
75
	conv := NewConverter(ot.Field(0).Type, fd)
76
	isMessage := fd.Message() != nil
77

78
	// TODO: Implement unsafe fast path?
79
	fieldOffset := offsetOf(fs, x)
80
	return fieldInfo{
81
		// NOTE: The logic below intentionally assumes that oneof fields are
82
		// well-formatted. That is, the oneof interface never contains a
83
		// typed nil pointer to one of the wrapper structs.
84

85
		fieldDesc: fd,
86
		has: func(p pointer) bool {
87
			if p.IsNil() {
88
				return false
89
			}
90
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
91
			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
92
				return false
93
			}
94
			return true
95
		},
96
		clear: func(p pointer) {
97
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
98
			if rv.IsNil() || rv.Elem().Type().Elem() != ot {
99
				// NOTE: We intentionally don't check for rv.Elem().IsNil()
100
				// so that (*OneofWrapperType)(nil) gets cleared to nil.
101
				return
102
			}
103
			rv.Set(reflect.Zero(rv.Type()))
104
		},
105
		get: func(p pointer) protoreflect.Value {
106
			if p.IsNil() {
107
				return conv.Zero()
108
			}
109
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
110
			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
111
				return conv.Zero()
112
			}
113
			rv = rv.Elem().Elem().Field(0)
114
			return conv.PBValueOf(rv)
115
		},
116
		set: func(p pointer, v protoreflect.Value) {
117
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
118
			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
119
				rv.Set(reflect.New(ot))
120
			}
121
			rv = rv.Elem().Elem().Field(0)
122
			rv.Set(conv.GoValueOf(v))
123
		},
124
		mutable: func(p pointer) protoreflect.Value {
125
			if !isMessage {
126
				panic(fmt.Sprintf("field %v with invalid Mutable call on field with non-composite type", fd.FullName()))
127
			}
128
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
129
			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
130
				rv.Set(reflect.New(ot))
131
			}
132
			rv = rv.Elem().Elem().Field(0)
133
			if rv.Kind() == reflect.Ptr && rv.IsNil() {
134
				rv.Set(conv.GoValueOf(protoreflect.ValueOfMessage(conv.New().Message())))
135
			}
136
			return conv.PBValueOf(rv)
137
		},
138
		newMessage: func() protoreflect.Message {
139
			return conv.New().Message()
140
		},
141
		newField: func() protoreflect.Value {
142
			return conv.New()
143
		},
144
	}
145
}
146

147
func fieldInfoForMap(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
148
	ft := fs.Type
149
	if ft.Kind() != reflect.Map {
150
		panic(fmt.Sprintf("field %v has invalid type: got %v, want map kind", fd.FullName(), ft))
151
	}
152
	conv := NewConverter(ft, fd)
153

154
	// TODO: Implement unsafe fast path?
155
	fieldOffset := offsetOf(fs, x)
156
	return fieldInfo{
157
		fieldDesc: fd,
158
		has: func(p pointer) bool {
159
			if p.IsNil() {
160
				return false
161
			}
162
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
163
			return rv.Len() > 0
164
		},
165
		clear: func(p pointer) {
166
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
167
			rv.Set(reflect.Zero(rv.Type()))
168
		},
169
		get: func(p pointer) protoreflect.Value {
170
			if p.IsNil() {
171
				return conv.Zero()
172
			}
173
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
174
			if rv.Len() == 0 {
175
				return conv.Zero()
176
			}
177
			return conv.PBValueOf(rv)
178
		},
179
		set: func(p pointer, v protoreflect.Value) {
180
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
181
			pv := conv.GoValueOf(v)
182
			if pv.IsNil() {
183
				panic(fmt.Sprintf("map field %v cannot be set with read-only value", fd.FullName()))
184
			}
185
			rv.Set(pv)
186
		},
187
		mutable: func(p pointer) protoreflect.Value {
188
			v := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
189
			if v.IsNil() {
190
				v.Set(reflect.MakeMap(fs.Type))
191
			}
192
			return conv.PBValueOf(v)
193
		},
194
		newField: func() protoreflect.Value {
195
			return conv.New()
196
		},
197
	}
198
}
199

200
func fieldInfoForList(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
201
	ft := fs.Type
202
	if ft.Kind() != reflect.Slice {
203
		panic(fmt.Sprintf("field %v has invalid type: got %v, want slice kind", fd.FullName(), ft))
204
	}
205
	conv := NewConverter(reflect.PtrTo(ft), fd)
206

207
	// TODO: Implement unsafe fast path?
208
	fieldOffset := offsetOf(fs, x)
209
	return fieldInfo{
210
		fieldDesc: fd,
211
		has: func(p pointer) bool {
212
			if p.IsNil() {
213
				return false
214
			}
215
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
216
			return rv.Len() > 0
217
		},
218
		clear: func(p pointer) {
219
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
220
			rv.Set(reflect.Zero(rv.Type()))
221
		},
222
		get: func(p pointer) protoreflect.Value {
223
			if p.IsNil() {
224
				return conv.Zero()
225
			}
226
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type)
227
			if rv.Elem().Len() == 0 {
228
				return conv.Zero()
229
			}
230
			return conv.PBValueOf(rv)
231
		},
232
		set: func(p pointer, v protoreflect.Value) {
233
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
234
			pv := conv.GoValueOf(v)
235
			if pv.IsNil() {
236
				panic(fmt.Sprintf("list field %v cannot be set with read-only value", fd.FullName()))
237
			}
238
			rv.Set(pv.Elem())
239
		},
240
		mutable: func(p pointer) protoreflect.Value {
241
			v := p.Apply(fieldOffset).AsValueOf(fs.Type)
242
			return conv.PBValueOf(v)
243
		},
244
		newField: func() protoreflect.Value {
245
			return conv.New()
246
		},
247
	}
248
}
249

250
var (
251
	nilBytes   = reflect.ValueOf([]byte(nil))
252
	emptyBytes = reflect.ValueOf([]byte{})
253
)
254

255
func fieldInfoForScalar(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
256
	ft := fs.Type
257
	nullable := fd.HasPresence()
258
	isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8
259
	if nullable {
260
		if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice {
261
			// This never occurs for generated message types.
262
			// Despite the protobuf type system specifying presence,
263
			// the Go field type cannot represent it.
264
			nullable = false
265
		}
266
		if ft.Kind() == reflect.Ptr {
267
			ft = ft.Elem()
268
		}
269
	}
270
	conv := NewConverter(ft, fd)
271

272
	// TODO: Implement unsafe fast path?
273
	fieldOffset := offsetOf(fs, x)
274
	return fieldInfo{
275
		fieldDesc: fd,
276
		has: func(p pointer) bool {
277
			if p.IsNil() {
278
				return false
279
			}
280
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
281
			if nullable {
282
				return !rv.IsNil()
283
			}
284
			switch rv.Kind() {
285
			case reflect.Bool:
286
				return rv.Bool()
287
			case reflect.Int32, reflect.Int64:
288
				return rv.Int() != 0
289
			case reflect.Uint32, reflect.Uint64:
290
				return rv.Uint() != 0
291
			case reflect.Float32, reflect.Float64:
292
				return rv.Float() != 0 || math.Signbit(rv.Float())
293
			case reflect.String, reflect.Slice:
294
				return rv.Len() > 0
295
			default:
296
				panic(fmt.Sprintf("field %v has invalid type: %v", fd.FullName(), rv.Type())) // should never happen
297
			}
298
		},
299
		clear: func(p pointer) {
300
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
301
			rv.Set(reflect.Zero(rv.Type()))
302
		},
303
		get: func(p pointer) protoreflect.Value {
304
			if p.IsNil() {
305
				return conv.Zero()
306
			}
307
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
308
			if nullable {
309
				if rv.IsNil() {
310
					return conv.Zero()
311
				}
312
				if rv.Kind() == reflect.Ptr {
313
					rv = rv.Elem()
314
				}
315
			}
316
			return conv.PBValueOf(rv)
317
		},
318
		set: func(p pointer, v protoreflect.Value) {
319
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
320
			if nullable && rv.Kind() == reflect.Ptr {
321
				if rv.IsNil() {
322
					rv.Set(reflect.New(ft))
323
				}
324
				rv = rv.Elem()
325
			}
326
			rv.Set(conv.GoValueOf(v))
327
			if isBytes && rv.Len() == 0 {
328
				if nullable {
329
					rv.Set(emptyBytes) // preserve presence
330
				} else {
331
					rv.Set(nilBytes) // do not preserve presence
332
				}
333
			}
334
		},
335
		newField: func() protoreflect.Value {
336
			return conv.New()
337
		},
338
	}
339
}
340

341
func fieldInfoForWeakMessage(fd protoreflect.FieldDescriptor, weakOffset offset) fieldInfo {
342
	if !flags.ProtoLegacy {
343
		panic("no support for proto1 weak fields")
344
	}
345

346
	var once sync.Once
347
	var messageType protoreflect.MessageType
348
	lazyInit := func() {
349
		once.Do(func() {
350
			messageName := fd.Message().FullName()
351
			messageType, _ = protoregistry.GlobalTypes.FindMessageByName(messageName)
352
			if messageType == nil {
353
				panic(fmt.Sprintf("weak message %v for field %v is not linked in", messageName, fd.FullName()))
354
			}
355
		})
356
	}
357

358
	num := fd.Number()
359
	return fieldInfo{
360
		fieldDesc: fd,
361
		has: func(p pointer) bool {
362
			if p.IsNil() {
363
				return false
364
			}
365
			_, ok := p.Apply(weakOffset).WeakFields().get(num)
366
			return ok
367
		},
368
		clear: func(p pointer) {
369
			p.Apply(weakOffset).WeakFields().clear(num)
370
		},
371
		get: func(p pointer) protoreflect.Value {
372
			lazyInit()
373
			if p.IsNil() {
374
				return protoreflect.ValueOfMessage(messageType.Zero())
375
			}
376
			m, ok := p.Apply(weakOffset).WeakFields().get(num)
377
			if !ok {
378
				return protoreflect.ValueOfMessage(messageType.Zero())
379
			}
380
			return protoreflect.ValueOfMessage(m.ProtoReflect())
381
		},
382
		set: func(p pointer, v protoreflect.Value) {
383
			lazyInit()
384
			m := v.Message()
385
			if m.Descriptor() != messageType.Descriptor() {
386
				if got, want := m.Descriptor().FullName(), messageType.Descriptor().FullName(); got != want {
387
					panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", fd.FullName(), got, want))
388
				}
389
				panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", fd.FullName(), m.Descriptor().FullName()))
390
			}
391
			p.Apply(weakOffset).WeakFields().set(num, m.Interface())
392
		},
393
		mutable: func(p pointer) protoreflect.Value {
394
			lazyInit()
395
			fs := p.Apply(weakOffset).WeakFields()
396
			m, ok := fs.get(num)
397
			if !ok {
398
				m = messageType.New().Interface()
399
				fs.set(num, m)
400
			}
401
			return protoreflect.ValueOfMessage(m.ProtoReflect())
402
		},
403
		newMessage: func() protoreflect.Message {
404
			lazyInit()
405
			return messageType.New()
406
		},
407
		newField: func() protoreflect.Value {
408
			lazyInit()
409
			return protoreflect.ValueOfMessage(messageType.New())
410
		},
411
	}
412
}
413

414
func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
415
	ft := fs.Type
416
	conv := NewConverter(ft, fd)
417

418
	// TODO: Implement unsafe fast path?
419
	fieldOffset := offsetOf(fs, x)
420
	return fieldInfo{
421
		fieldDesc: fd,
422
		has: func(p pointer) bool {
423
			if p.IsNil() {
424
				return false
425
			}
426
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
427
			if fs.Type.Kind() != reflect.Ptr {
428
				return !isZero(rv)
429
			}
430
			return !rv.IsNil()
431
		},
432
		clear: func(p pointer) {
433
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
434
			rv.Set(reflect.Zero(rv.Type()))
435
		},
436
		get: func(p pointer) protoreflect.Value {
437
			if p.IsNil() {
438
				return conv.Zero()
439
			}
440
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
441
			return conv.PBValueOf(rv)
442
		},
443
		set: func(p pointer, v protoreflect.Value) {
444
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
445
			rv.Set(conv.GoValueOf(v))
446
			if fs.Type.Kind() == reflect.Ptr && rv.IsNil() {
447
				panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName()))
448
			}
449
		},
450
		mutable: func(p pointer) protoreflect.Value {
451
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
452
			if fs.Type.Kind() == reflect.Ptr && rv.IsNil() {
453
				rv.Set(conv.GoValueOf(conv.New()))
454
			}
455
			return conv.PBValueOf(rv)
456
		},
457
		newMessage: func() protoreflect.Message {
458
			return conv.New().Message()
459
		},
460
		newField: func() protoreflect.Value {
461
			return conv.New()
462
		},
463
	}
464
}
465

466
type oneofInfo struct {
467
	oneofDesc protoreflect.OneofDescriptor
468
	which     func(pointer) protoreflect.FieldNumber
469
}
470

471
func makeOneofInfo(od protoreflect.OneofDescriptor, si structInfo, x exporter) *oneofInfo {
472
	oi := &oneofInfo{oneofDesc: od}
473
	if od.IsSynthetic() {
474
		fs := si.fieldsByNumber[od.Fields().Get(0).Number()]
475
		fieldOffset := offsetOf(fs, x)
476
		oi.which = func(p pointer) protoreflect.FieldNumber {
477
			if p.IsNil() {
478
				return 0
479
			}
480
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
481
			if rv.IsNil() { // valid on either *T or []byte
482
				return 0
483
			}
484
			return od.Fields().Get(0).Number()
485
		}
486
	} else {
487
		fs := si.oneofsByName[od.Name()]
488
		fieldOffset := offsetOf(fs, x)
489
		oi.which = func(p pointer) protoreflect.FieldNumber {
490
			if p.IsNil() {
491
				return 0
492
			}
493
			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
494
			if rv.IsNil() {
495
				return 0
496
			}
497
			rv = rv.Elem()
498
			if rv.IsNil() {
499
				return 0
500
			}
501
			return si.oneofWrappersByType[rv.Type().Elem()]
502
		}
503
	}
504
	return oi
505
}
506

507
// isZero is identical to reflect.Value.IsZero.
508
// TODO: Remove this when Go1.13 is the minimally supported Go version.
509
func isZero(v reflect.Value) bool {
510
	switch v.Kind() {
511
	case reflect.Bool:
512
		return !v.Bool()
513
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
514
		return v.Int() == 0
515
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
516
		return v.Uint() == 0
517
	case reflect.Float32, reflect.Float64:
518
		return math.Float64bits(v.Float()) == 0
519
	case reflect.Complex64, reflect.Complex128:
520
		c := v.Complex()
521
		return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
522
	case reflect.Array:
523
		for i := 0; i < v.Len(); i++ {
524
			if !isZero(v.Index(i)) {
525
				return false
526
			}
527
		}
528
		return true
529
	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
530
		return v.IsNil()
531
	case reflect.String:
532
		return v.Len() == 0
533
	case reflect.Struct:
534
		for i := 0; i < v.NumField(); i++ {
535
			if !isZero(v.Field(i)) {
536
				return false
537
			}
538
		}
539
		return true
540
	default:
541
		panic(&reflect.ValueError{Method: "reflect.Value.IsZero", Kind: v.Kind()})
542
	}
543
}
544

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.