podman

Форк
0
610 строк · 17.0 Кб
1
// Protocol Buffers for Go with Gadgets
2
//
3
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
4
// http://github.com/gogo/protobuf
5
//
6
// Go support for Protocol Buffers - Google's data interchange format
7
//
8
// Copyright 2010 The Go Authors.  All rights reserved.
9
// https://github.com/golang/protobuf
10
//
11
// Redistribution and use in source and binary forms, with or without
12
// modification, are permitted provided that the following conditions are
13
// met:
14
//
15
//     * Redistributions of source code must retain the above copyright
16
// notice, this list of conditions and the following disclaimer.
17
//     * Redistributions in binary form must reproduce the above
18
// copyright notice, this list of conditions and the following disclaimer
19
// in the documentation and/or other materials provided with the
20
// distribution.
21
//     * Neither the name of Google Inc. nor the names of its
22
// contributors may be used to endorse or promote products derived from
23
// this software without specific prior written permission.
24
//
25
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36

37
package proto
38

39
/*
40
 * Routines for encoding data into the wire format for protocol buffers.
41
 */
42

43
import (
44
	"fmt"
45
	"log"
46
	"reflect"
47
	"sort"
48
	"strconv"
49
	"strings"
50
	"sync"
51
)
52

53
const debug bool = false
54

55
// Constants that identify the encoding of a value on the wire.
56
const (
57
	WireVarint     = 0
58
	WireFixed64    = 1
59
	WireBytes      = 2
60
	WireStartGroup = 3
61
	WireEndGroup   = 4
62
	WireFixed32    = 5
63
)
64

65
// tagMap is an optimization over map[int]int for typical protocol buffer
66
// use-cases. Encoded protocol buffers are often in tag order with small tag
67
// numbers.
68
type tagMap struct {
69
	fastTags []int
70
	slowTags map[int]int
71
}
72

73
// tagMapFastLimit is the upper bound on the tag number that will be stored in
74
// the tagMap slice rather than its map.
75
const tagMapFastLimit = 1024
76

77
func (p *tagMap) get(t int) (int, bool) {
78
	if t > 0 && t < tagMapFastLimit {
79
		if t >= len(p.fastTags) {
80
			return 0, false
81
		}
82
		fi := p.fastTags[t]
83
		return fi, fi >= 0
84
	}
85
	fi, ok := p.slowTags[t]
86
	return fi, ok
87
}
88

89
func (p *tagMap) put(t int, fi int) {
90
	if t > 0 && t < tagMapFastLimit {
91
		for len(p.fastTags) < t+1 {
92
			p.fastTags = append(p.fastTags, -1)
93
		}
94
		p.fastTags[t] = fi
95
		return
96
	}
97
	if p.slowTags == nil {
98
		p.slowTags = make(map[int]int)
99
	}
100
	p.slowTags[t] = fi
101
}
102

103
// StructProperties represents properties for all the fields of a struct.
104
// decoderTags and decoderOrigNames should only be used by the decoder.
105
type StructProperties struct {
106
	Prop             []*Properties  // properties for each field
107
	reqCount         int            // required count
108
	decoderTags      tagMap         // map from proto tag to struct field number
109
	decoderOrigNames map[string]int // map from original name to struct field number
110
	order            []int          // list of struct field numbers in tag order
111

112
	// OneofTypes contains information about the oneof fields in this message.
113
	// It is keyed by the original name of a field.
114
	OneofTypes map[string]*OneofProperties
115
}
116

117
// OneofProperties represents information about a specific field in a oneof.
118
type OneofProperties struct {
119
	Type  reflect.Type // pointer to generated struct type for this oneof field
120
	Field int          // struct field number of the containing oneof in the message
121
	Prop  *Properties
122
}
123

124
// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
125
// See encode.go, (*Buffer).enc_struct.
126

127
func (sp *StructProperties) Len() int { return len(sp.order) }
128
func (sp *StructProperties) Less(i, j int) bool {
129
	return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
130
}
131
func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
132

133
// Properties represents the protocol-specific behavior of a single struct field.
134
type Properties struct {
135
	Name     string // name of the field, for error messages
136
	OrigName string // original name before protocol compiler (always set)
137
	JSONName string // name to use for JSON; determined by protoc
138
	Wire     string
139
	WireType int
140
	Tag      int
141
	Required bool
142
	Optional bool
143
	Repeated bool
144
	Packed   bool   // relevant for repeated primitives only
145
	Enum     string // set for enum types only
146
	proto3   bool   // whether this is known to be a proto3 field
147
	oneof    bool   // whether this is a oneof field
148

149
	Default     string // default value
150
	HasDefault  bool   // whether an explicit default was provided
151
	CustomType  string
152
	CastType    string
153
	StdTime     bool
154
	StdDuration bool
155
	WktPointer  bool
156

157
	stype reflect.Type      // set for struct types only
158
	ctype reflect.Type      // set for custom types only
159
	sprop *StructProperties // set for struct types only
160

161
	mtype      reflect.Type // set for map types only
162
	MapKeyProp *Properties  // set for map types only
163
	MapValProp *Properties  // set for map types only
164
}
165

166
// String formats the properties in the protobuf struct field tag style.
167
func (p *Properties) String() string {
168
	s := p.Wire
169
	s += ","
170
	s += strconv.Itoa(p.Tag)
171
	if p.Required {
172
		s += ",req"
173
	}
174
	if p.Optional {
175
		s += ",opt"
176
	}
177
	if p.Repeated {
178
		s += ",rep"
179
	}
180
	if p.Packed {
181
		s += ",packed"
182
	}
183
	s += ",name=" + p.OrigName
184
	if p.JSONName != p.OrigName {
185
		s += ",json=" + p.JSONName
186
	}
187
	if p.proto3 {
188
		s += ",proto3"
189
	}
190
	if p.oneof {
191
		s += ",oneof"
192
	}
193
	if len(p.Enum) > 0 {
194
		s += ",enum=" + p.Enum
195
	}
196
	if p.HasDefault {
197
		s += ",def=" + p.Default
198
	}
199
	return s
200
}
201

202
// Parse populates p by parsing a string in the protobuf struct field tag style.
203
func (p *Properties) Parse(s string) {
204
	// "bytes,49,opt,name=foo,def=hello!"
205
	fields := strings.Split(s, ",") // breaks def=, but handled below.
206
	if len(fields) < 2 {
207
		log.Printf("proto: tag has too few fields: %q", s)
208
		return
209
	}
210

211
	p.Wire = fields[0]
212
	switch p.Wire {
213
	case "varint":
214
		p.WireType = WireVarint
215
	case "fixed32":
216
		p.WireType = WireFixed32
217
	case "fixed64":
218
		p.WireType = WireFixed64
219
	case "zigzag32":
220
		p.WireType = WireVarint
221
	case "zigzag64":
222
		p.WireType = WireVarint
223
	case "bytes", "group":
224
		p.WireType = WireBytes
225
		// no numeric converter for non-numeric types
226
	default:
227
		log.Printf("proto: tag has unknown wire type: %q", s)
228
		return
229
	}
230

231
	var err error
232
	p.Tag, err = strconv.Atoi(fields[1])
233
	if err != nil {
234
		return
235
	}
236

237
outer:
238
	for i := 2; i < len(fields); i++ {
239
		f := fields[i]
240
		switch {
241
		case f == "req":
242
			p.Required = true
243
		case f == "opt":
244
			p.Optional = true
245
		case f == "rep":
246
			p.Repeated = true
247
		case f == "packed":
248
			p.Packed = true
249
		case strings.HasPrefix(f, "name="):
250
			p.OrigName = f[5:]
251
		case strings.HasPrefix(f, "json="):
252
			p.JSONName = f[5:]
253
		case strings.HasPrefix(f, "enum="):
254
			p.Enum = f[5:]
255
		case f == "proto3":
256
			p.proto3 = true
257
		case f == "oneof":
258
			p.oneof = true
259
		case strings.HasPrefix(f, "def="):
260
			p.HasDefault = true
261
			p.Default = f[4:] // rest of string
262
			if i+1 < len(fields) {
263
				// Commas aren't escaped, and def is always last.
264
				p.Default += "," + strings.Join(fields[i+1:], ",")
265
				break outer
266
			}
267
		case strings.HasPrefix(f, "embedded="):
268
			p.OrigName = strings.Split(f, "=")[1]
269
		case strings.HasPrefix(f, "customtype="):
270
			p.CustomType = strings.Split(f, "=")[1]
271
		case strings.HasPrefix(f, "casttype="):
272
			p.CastType = strings.Split(f, "=")[1]
273
		case f == "stdtime":
274
			p.StdTime = true
275
		case f == "stdduration":
276
			p.StdDuration = true
277
		case f == "wktptr":
278
			p.WktPointer = true
279
		}
280
	}
281
}
282

283
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
284

285
// setFieldProps initializes the field properties for submessages and maps.
286
func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
287
	isMap := typ.Kind() == reflect.Map
288
	if len(p.CustomType) > 0 && !isMap {
289
		p.ctype = typ
290
		p.setTag(lockGetProp)
291
		return
292
	}
293
	if p.StdTime && !isMap {
294
		p.setTag(lockGetProp)
295
		return
296
	}
297
	if p.StdDuration && !isMap {
298
		p.setTag(lockGetProp)
299
		return
300
	}
301
	if p.WktPointer && !isMap {
302
		p.setTag(lockGetProp)
303
		return
304
	}
305
	switch t1 := typ; t1.Kind() {
306
	case reflect.Struct:
307
		p.stype = typ
308
	case reflect.Ptr:
309
		if t1.Elem().Kind() == reflect.Struct {
310
			p.stype = t1.Elem()
311
		}
312
	case reflect.Slice:
313
		switch t2 := t1.Elem(); t2.Kind() {
314
		case reflect.Ptr:
315
			switch t3 := t2.Elem(); t3.Kind() {
316
			case reflect.Struct:
317
				p.stype = t3
318
			}
319
		case reflect.Struct:
320
			p.stype = t2
321
		}
322

323
	case reflect.Map:
324

325
		p.mtype = t1
326
		p.MapKeyProp = &Properties{}
327
		p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
328
		p.MapValProp = &Properties{}
329
		vtype := p.mtype.Elem()
330
		if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
331
			// The value type is not a message (*T) or bytes ([]byte),
332
			// so we need encoders for the pointer to this type.
333
			vtype = reflect.PtrTo(vtype)
334
		}
335

336
		p.MapValProp.CustomType = p.CustomType
337
		p.MapValProp.StdDuration = p.StdDuration
338
		p.MapValProp.StdTime = p.StdTime
339
		p.MapValProp.WktPointer = p.WktPointer
340
		p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
341
	}
342
	p.setTag(lockGetProp)
343
}
344

345
func (p *Properties) setTag(lockGetProp bool) {
346
	if p.stype != nil {
347
		if lockGetProp {
348
			p.sprop = GetProperties(p.stype)
349
		} else {
350
			p.sprop = getPropertiesLocked(p.stype)
351
		}
352
	}
353
}
354

355
var (
356
	marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
357
)
358

359
// Init populates the properties from a protocol buffer struct tag.
360
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
361
	p.init(typ, name, tag, f, true)
362
}
363

364
func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
365
	// "bytes,49,opt,def=hello!"
366
	p.Name = name
367
	p.OrigName = name
368
	if tag == "" {
369
		return
370
	}
371
	p.Parse(tag)
372
	p.setFieldProps(typ, f, lockGetProp)
373
}
374

375
var (
376
	propertiesMu  sync.RWMutex
377
	propertiesMap = make(map[reflect.Type]*StructProperties)
378
)
379

380
// GetProperties returns the list of properties for the type represented by t.
381
// t must represent a generated struct type of a protocol message.
382
func GetProperties(t reflect.Type) *StructProperties {
383
	if t.Kind() != reflect.Struct {
384
		panic("proto: type must have kind struct")
385
	}
386

387
	// Most calls to GetProperties in a long-running program will be
388
	// retrieving details for types we have seen before.
389
	propertiesMu.RLock()
390
	sprop, ok := propertiesMap[t]
391
	propertiesMu.RUnlock()
392
	if ok {
393
		return sprop
394
	}
395

396
	propertiesMu.Lock()
397
	sprop = getPropertiesLocked(t)
398
	propertiesMu.Unlock()
399
	return sprop
400
}
401

402
type (
403
	oneofFuncsIface interface {
404
		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
405
	}
406
	oneofWrappersIface interface {
407
		XXX_OneofWrappers() []interface{}
408
	}
409
)
410

411
// getPropertiesLocked requires that propertiesMu is held.
412
func getPropertiesLocked(t reflect.Type) *StructProperties {
413
	if prop, ok := propertiesMap[t]; ok {
414
		return prop
415
	}
416

417
	prop := new(StructProperties)
418
	// in case of recursive protos, fill this in now.
419
	propertiesMap[t] = prop
420

421
	// build properties
422
	prop.Prop = make([]*Properties, t.NumField())
423
	prop.order = make([]int, t.NumField())
424

425
	isOneofMessage := false
426
	for i := 0; i < t.NumField(); i++ {
427
		f := t.Field(i)
428
		p := new(Properties)
429
		name := f.Name
430
		p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
431

432
		oneof := f.Tag.Get("protobuf_oneof") // special case
433
		if oneof != "" {
434
			isOneofMessage = true
435
			// Oneof fields don't use the traditional protobuf tag.
436
			p.OrigName = oneof
437
		}
438
		prop.Prop[i] = p
439
		prop.order[i] = i
440
		if debug {
441
			print(i, " ", f.Name, " ", t.String(), " ")
442
			if p.Tag > 0 {
443
				print(p.String())
444
			}
445
			print("\n")
446
		}
447
	}
448

449
	// Re-order prop.order.
450
	sort.Sort(prop)
451

452
	if isOneofMessage {
453
		var oots []interface{}
454
		switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
455
		case oneofFuncsIface:
456
			_, _, _, oots = m.XXX_OneofFuncs()
457
		case oneofWrappersIface:
458
			oots = m.XXX_OneofWrappers()
459
		}
460
		if len(oots) > 0 {
461
			// Interpret oneof metadata.
462
			prop.OneofTypes = make(map[string]*OneofProperties)
463
			for _, oot := range oots {
464
				oop := &OneofProperties{
465
					Type: reflect.ValueOf(oot).Type(), // *T
466
					Prop: new(Properties),
467
				}
468
				sft := oop.Type.Elem().Field(0)
469
				oop.Prop.Name = sft.Name
470
				oop.Prop.Parse(sft.Tag.Get("protobuf"))
471
				// There will be exactly one interface field that
472
				// this new value is assignable to.
473
				for i := 0; i < t.NumField(); i++ {
474
					f := t.Field(i)
475
					if f.Type.Kind() != reflect.Interface {
476
						continue
477
					}
478
					if !oop.Type.AssignableTo(f.Type) {
479
						continue
480
					}
481
					oop.Field = i
482
					break
483
				}
484
				prop.OneofTypes[oop.Prop.OrigName] = oop
485
			}
486
		}
487
	}
488

489
	// build required counts
490
	// build tags
491
	reqCount := 0
492
	prop.decoderOrigNames = make(map[string]int)
493
	for i, p := range prop.Prop {
494
		if strings.HasPrefix(p.Name, "XXX_") {
495
			// Internal fields should not appear in tags/origNames maps.
496
			// They are handled specially when encoding and decoding.
497
			continue
498
		}
499
		if p.Required {
500
			reqCount++
501
		}
502
		prop.decoderTags.put(p.Tag, i)
503
		prop.decoderOrigNames[p.OrigName] = i
504
	}
505
	prop.reqCount = reqCount
506

507
	return prop
508
}
509

510
// A global registry of enum types.
511
// The generated code will register the generated maps by calling RegisterEnum.
512

513
var enumValueMaps = make(map[string]map[string]int32)
514
var enumStringMaps = make(map[string]map[int32]string)
515

516
// RegisterEnum is called from the generated code to install the enum descriptor
517
// maps into the global table to aid parsing text format protocol buffers.
518
func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
519
	if _, ok := enumValueMaps[typeName]; ok {
520
		panic("proto: duplicate enum registered: " + typeName)
521
	}
522
	enumValueMaps[typeName] = valueMap
523
	if _, ok := enumStringMaps[typeName]; ok {
524
		panic("proto: duplicate enum registered: " + typeName)
525
	}
526
	enumStringMaps[typeName] = unusedNameMap
527
}
528

529
// EnumValueMap returns the mapping from names to integers of the
530
// enum type enumType, or a nil if not found.
531
func EnumValueMap(enumType string) map[string]int32 {
532
	return enumValueMaps[enumType]
533
}
534

535
// A registry of all linked message types.
536
// The string is a fully-qualified proto name ("pkg.Message").
537
var (
538
	protoTypedNils = make(map[string]Message)      // a map from proto names to typed nil pointers
539
	protoMapTypes  = make(map[string]reflect.Type) // a map from proto names to map types
540
	revProtoTypes  = make(map[reflect.Type]string)
541
)
542

543
// RegisterType is called from generated code and maps from the fully qualified
544
// proto name to the type (pointer to struct) of the protocol buffer.
545
func RegisterType(x Message, name string) {
546
	if _, ok := protoTypedNils[name]; ok {
547
		// TODO: Some day, make this a panic.
548
		log.Printf("proto: duplicate proto type registered: %s", name)
549
		return
550
	}
551
	t := reflect.TypeOf(x)
552
	if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
553
		// Generated code always calls RegisterType with nil x.
554
		// This check is just for extra safety.
555
		protoTypedNils[name] = x
556
	} else {
557
		protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
558
	}
559
	revProtoTypes[t] = name
560
}
561

562
// RegisterMapType is called from generated code and maps from the fully qualified
563
// proto name to the native map type of the proto map definition.
564
func RegisterMapType(x interface{}, name string) {
565
	if reflect.TypeOf(x).Kind() != reflect.Map {
566
		panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
567
	}
568
	if _, ok := protoMapTypes[name]; ok {
569
		log.Printf("proto: duplicate proto type registered: %s", name)
570
		return
571
	}
572
	t := reflect.TypeOf(x)
573
	protoMapTypes[name] = t
574
	revProtoTypes[t] = name
575
}
576

577
// MessageName returns the fully-qualified proto name for the given message type.
578
func MessageName(x Message) string {
579
	type xname interface {
580
		XXX_MessageName() string
581
	}
582
	if m, ok := x.(xname); ok {
583
		return m.XXX_MessageName()
584
	}
585
	return revProtoTypes[reflect.TypeOf(x)]
586
}
587

588
// MessageType returns the message type (pointer to struct) for a named message.
589
// The type is not guaranteed to implement proto.Message if the name refers to a
590
// map entry.
591
func MessageType(name string) reflect.Type {
592
	if t, ok := protoTypedNils[name]; ok {
593
		return reflect.TypeOf(t)
594
	}
595
	return protoMapTypes[name]
596
}
597

598
// A registry of all linked proto files.
599
var (
600
	protoFiles = make(map[string][]byte) // file name => fileDescriptor
601
)
602

603
// RegisterFile is called from generated code and maps from the
604
// full file name of a .proto file to its compressed FileDescriptorProto.
605
func RegisterFile(filename string, fileDescriptor []byte) {
606
	protoFiles[filename] = fileDescriptor
607
}
608

609
// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
610
func FileDescriptor(filename string) []byte { return protoFiles[filename] }
611

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

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

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

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