| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 | // Protocol Buffers for Go with Gadgets//// Copyright (c) 2013, The GoGo Authors. All rights reserved.// http://github.com/gogo/protobuf//// Go support for Protocol Buffers - Google's data interchange format//// Copyright 2010 The Go Authors.  All rights reserved.// https://github.com/golang/protobuf//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:////     * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.//     * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.//     * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived from// this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.package proto/* * Routines for encoding data into the wire format for protocol buffers. */import (	"fmt"	"log"	"reflect"	"sort"	"strconv"	"strings"	"sync")const debug bool = false// Constants that identify the encoding of a value on the wire.const (	WireVarint     = 0	WireFixed64    = 1	WireBytes      = 2	WireStartGroup = 3	WireEndGroup   = 4	WireFixed32    = 5)// tagMap is an optimization over map[int]int for typical protocol buffer// use-cases. Encoded protocol buffers are often in tag order with small tag// numbers.type tagMap struct {	fastTags []int	slowTags map[int]int}// tagMapFastLimit is the upper bound on the tag number that will be stored in// the tagMap slice rather than its map.const tagMapFastLimit = 1024func (p *tagMap) get(t int) (int, bool) {	if t > 0 && t < tagMapFastLimit {		if t >= len(p.fastTags) {			return 0, false		}		fi := p.fastTags[t]		return fi, fi >= 0	}	fi, ok := p.slowTags[t]	return fi, ok}func (p *tagMap) put(t int, fi int) {	if t > 0 && t < tagMapFastLimit {		for len(p.fastTags) < t+1 {			p.fastTags = append(p.fastTags, -1)		}		p.fastTags[t] = fi		return	}	if p.slowTags == nil {		p.slowTags = make(map[int]int)	}	p.slowTags[t] = fi}// StructProperties represents properties for all the fields of a struct.// decoderTags and decoderOrigNames should only be used by the decoder.type StructProperties struct {	Prop             []*Properties  // properties for each field	reqCount         int            // required count	decoderTags      tagMap         // map from proto tag to struct field number	decoderOrigNames map[string]int // map from original name to struct field number	order            []int          // list of struct field numbers in tag order	// OneofTypes contains information about the oneof fields in this message.	// It is keyed by the original name of a field.	OneofTypes map[string]*OneofProperties}// OneofProperties represents information about a specific field in a oneof.type OneofProperties struct {	Type  reflect.Type // pointer to generated struct type for this oneof field	Field int          // struct field number of the containing oneof in the message	Prop  *Properties}// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.// See encode.go, (*Buffer).enc_struct.func (sp *StructProperties) Len() int { return len(sp.order) }func (sp *StructProperties) Less(i, j int) bool {	return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag}func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }// Properties represents the protocol-specific behavior of a single struct field.type Properties struct {	Name     string // name of the field, for error messages	OrigName string // original name before protocol compiler (always set)	JSONName string // name to use for JSON; determined by protoc	Wire     string	WireType int	Tag      int	Required bool	Optional bool	Repeated bool	Packed   bool   // relevant for repeated primitives only	Enum     string // set for enum types only	proto3   bool   // whether this is known to be a proto3 field	oneof    bool   // whether this is a oneof field	Default     string // default value	HasDefault  bool   // whether an explicit default was provided	CustomType  string	CastType    string	StdTime     bool	StdDuration bool	WktPointer  bool	stype reflect.Type      // set for struct types only	ctype reflect.Type      // set for custom types only	sprop *StructProperties // set for struct types only	mtype      reflect.Type // set for map types only	MapKeyProp *Properties  // set for map types only	MapValProp *Properties  // set for map types only}// String formats the properties in the protobuf struct field tag style.func (p *Properties) String() string {	s := p.Wire	s += ","	s += strconv.Itoa(p.Tag)	if p.Required {		s += ",req"	}	if p.Optional {		s += ",opt"	}	if p.Repeated {		s += ",rep"	}	if p.Packed {		s += ",packed"	}	s += ",name=" + p.OrigName	if p.JSONName != p.OrigName {		s += ",json=" + p.JSONName	}	if p.proto3 {		s += ",proto3"	}	if p.oneof {		s += ",oneof"	}	if len(p.Enum) > 0 {		s += ",enum=" + p.Enum	}	if p.HasDefault {		s += ",def=" + p.Default	}	return s}// Parse populates p by parsing a string in the protobuf struct field tag style.func (p *Properties) Parse(s string) {	// "bytes,49,opt,name=foo,def=hello!"	fields := strings.Split(s, ",") // breaks def=, but handled below.	if len(fields) < 2 {		log.Printf("proto: tag has too few fields: %q", s)		return	}	p.Wire = fields[0]	switch p.Wire {	case "varint":		p.WireType = WireVarint	case "fixed32":		p.WireType = WireFixed32	case "fixed64":		p.WireType = WireFixed64	case "zigzag32":		p.WireType = WireVarint	case "zigzag64":		p.WireType = WireVarint	case "bytes", "group":		p.WireType = WireBytes		// no numeric converter for non-numeric types	default:		log.Printf("proto: tag has unknown wire type: %q", s)		return	}	var err error	p.Tag, err = strconv.Atoi(fields[1])	if err != nil {		return	}outer:	for i := 2; i < len(fields); i++ {		f := fields[i]		switch {		case f == "req":			p.Required = true		case f == "opt":			p.Optional = true		case f == "rep":			p.Repeated = true		case f == "packed":			p.Packed = true		case strings.HasPrefix(f, "name="):			p.OrigName = f[5:]		case strings.HasPrefix(f, "json="):			p.JSONName = f[5:]		case strings.HasPrefix(f, "enum="):			p.Enum = f[5:]		case f == "proto3":			p.proto3 = true		case f == "oneof":			p.oneof = true		case strings.HasPrefix(f, "def="):			p.HasDefault = true			p.Default = f[4:] // rest of string			if i+1 < len(fields) {				// Commas aren't escaped, and def is always last.				p.Default += "," + strings.Join(fields[i+1:], ",")				break outer			}		case strings.HasPrefix(f, "embedded="):			p.OrigName = strings.Split(f, "=")[1]		case strings.HasPrefix(f, "customtype="):			p.CustomType = strings.Split(f, "=")[1]		case strings.HasPrefix(f, "casttype="):			p.CastType = strings.Split(f, "=")[1]		case f == "stdtime":			p.StdTime = true		case f == "stdduration":			p.StdDuration = true		case f == "wktptr":			p.WktPointer = true		}	}}var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()// setFieldProps initializes the field properties for submessages and maps.func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {	isMap := typ.Kind() == reflect.Map	if len(p.CustomType) > 0 && !isMap {		p.ctype = typ		p.setTag(lockGetProp)		return	}	if p.StdTime && !isMap {		p.setTag(lockGetProp)		return	}	if p.StdDuration && !isMap {		p.setTag(lockGetProp)		return	}	if p.WktPointer && !isMap {		p.setTag(lockGetProp)		return	}	switch t1 := typ; t1.Kind() {	case reflect.Struct:		p.stype = typ	case reflect.Ptr:		if t1.Elem().Kind() == reflect.Struct {			p.stype = t1.Elem()		}	case reflect.Slice:		switch t2 := t1.Elem(); t2.Kind() {		case reflect.Ptr:			switch t3 := t2.Elem(); t3.Kind() {			case reflect.Struct:				p.stype = t3			}		case reflect.Struct:			p.stype = t2		}	case reflect.Map:		p.mtype = t1		p.MapKeyProp = &Properties{}		p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)		p.MapValProp = &Properties{}		vtype := p.mtype.Elem()		if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {			// The value type is not a message (*T) or bytes ([]byte),			// so we need encoders for the pointer to this type.			vtype = reflect.PtrTo(vtype)		}		p.MapValProp.CustomType = p.CustomType		p.MapValProp.StdDuration = p.StdDuration		p.MapValProp.StdTime = p.StdTime		p.MapValProp.WktPointer = p.WktPointer		p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)	}	p.setTag(lockGetProp)}func (p *Properties) setTag(lockGetProp bool) {	if p.stype != nil {		if lockGetProp {			p.sprop = GetProperties(p.stype)		} else {			p.sprop = getPropertiesLocked(p.stype)		}	}}var (	marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem())// Init populates the properties from a protocol buffer struct tag.func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {	p.init(typ, name, tag, f, true)}func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {	// "bytes,49,opt,def=hello!"	p.Name = name	p.OrigName = name	if tag == "" {		return	}	p.Parse(tag)	p.setFieldProps(typ, f, lockGetProp)}var (	propertiesMu  sync.RWMutex	propertiesMap = make(map[reflect.Type]*StructProperties))// GetProperties returns the list of properties for the type represented by t.// t must represent a generated struct type of a protocol message.func GetProperties(t reflect.Type) *StructProperties {	if t.Kind() != reflect.Struct {		panic("proto: type must have kind struct")	}	// Most calls to GetProperties in a long-running program will be	// retrieving details for types we have seen before.	propertiesMu.RLock()	sprop, ok := propertiesMap[t]	propertiesMu.RUnlock()	if ok {		return sprop	}	propertiesMu.Lock()	sprop = getPropertiesLocked(t)	propertiesMu.Unlock()	return sprop}type (	oneofFuncsIface interface {		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})	}	oneofWrappersIface interface {		XXX_OneofWrappers() []interface{}	})// getPropertiesLocked requires that propertiesMu is held.func getPropertiesLocked(t reflect.Type) *StructProperties {	if prop, ok := propertiesMap[t]; ok {		return prop	}	prop := new(StructProperties)	// in case of recursive protos, fill this in now.	propertiesMap[t] = prop	// build properties	prop.Prop = make([]*Properties, t.NumField())	prop.order = make([]int, t.NumField())	isOneofMessage := false	for i := 0; i < t.NumField(); i++ {		f := t.Field(i)		p := new(Properties)		name := f.Name		p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)		oneof := f.Tag.Get("protobuf_oneof") // special case		if oneof != "" {			isOneofMessage = true			// Oneof fields don't use the traditional protobuf tag.			p.OrigName = oneof		}		prop.Prop[i] = p		prop.order[i] = i		if debug {			print(i, " ", f.Name, " ", t.String(), " ")			if p.Tag > 0 {				print(p.String())			}			print("\n")		}	}	// Re-order prop.order.	sort.Sort(prop)	if isOneofMessage {		var oots []interface{}		switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {		case oneofFuncsIface:			_, _, _, oots = m.XXX_OneofFuncs()		case oneofWrappersIface:			oots = m.XXX_OneofWrappers()		}		if len(oots) > 0 {			// Interpret oneof metadata.			prop.OneofTypes = make(map[string]*OneofProperties)			for _, oot := range oots {				oop := &OneofProperties{					Type: reflect.ValueOf(oot).Type(), // *T					Prop: new(Properties),				}				sft := oop.Type.Elem().Field(0)				oop.Prop.Name = sft.Name				oop.Prop.Parse(sft.Tag.Get("protobuf"))				// There will be exactly one interface field that				// this new value is assignable to.				for i := 0; i < t.NumField(); i++ {					f := t.Field(i)					if f.Type.Kind() != reflect.Interface {						continue					}					if !oop.Type.AssignableTo(f.Type) {						continue					}					oop.Field = i					break				}				prop.OneofTypes[oop.Prop.OrigName] = oop			}		}	}	// build required counts	// build tags	reqCount := 0	prop.decoderOrigNames = make(map[string]int)	for i, p := range prop.Prop {		if strings.HasPrefix(p.Name, "XXX_") {			// Internal fields should not appear in tags/origNames maps.			// They are handled specially when encoding and decoding.			continue		}		if p.Required {			reqCount++		}		prop.decoderTags.put(p.Tag, i)		prop.decoderOrigNames[p.OrigName] = i	}	prop.reqCount = reqCount	return prop}// A global registry of enum types.// The generated code will register the generated maps by calling RegisterEnum.var enumValueMaps = make(map[string]map[string]int32)var enumStringMaps = make(map[string]map[int32]string)// RegisterEnum is called from the generated code to install the enum descriptor// maps into the global table to aid parsing text format protocol buffers.func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {	if _, ok := enumValueMaps[typeName]; ok {		panic("proto: duplicate enum registered: " + typeName)	}	enumValueMaps[typeName] = valueMap	if _, ok := enumStringMaps[typeName]; ok {		panic("proto: duplicate enum registered: " + typeName)	}	enumStringMaps[typeName] = unusedNameMap}// EnumValueMap returns the mapping from names to integers of the// enum type enumType, or a nil if not found.func EnumValueMap(enumType string) map[string]int32 {	return enumValueMaps[enumType]}// A registry of all linked message types.// The string is a fully-qualified proto name ("pkg.Message").var (	protoTypedNils = make(map[string]Message)      // a map from proto names to typed nil pointers	protoMapTypes  = make(map[string]reflect.Type) // a map from proto names to map types	revProtoTypes  = make(map[reflect.Type]string))// RegisterType is called from generated code and maps from the fully qualified// proto name to the type (pointer to struct) of the protocol buffer.func RegisterType(x Message, name string) {	if _, ok := protoTypedNils[name]; ok {		// TODO: Some day, make this a panic.		log.Printf("proto: duplicate proto type registered: %s", name)		return	}	t := reflect.TypeOf(x)	if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {		// Generated code always calls RegisterType with nil x.		// This check is just for extra safety.		protoTypedNils[name] = x	} else {		protoTypedNils[name] = reflect.Zero(t).Interface().(Message)	}	revProtoTypes[t] = name}// RegisterMapType is called from generated code and maps from the fully qualified// proto name to the native map type of the proto map definition.func RegisterMapType(x interface{}, name string) {	if reflect.TypeOf(x).Kind() != reflect.Map {		panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))	}	if _, ok := protoMapTypes[name]; ok {		log.Printf("proto: duplicate proto type registered: %s", name)		return	}	t := reflect.TypeOf(x)	protoMapTypes[name] = t	revProtoTypes[t] = name}// MessageName returns the fully-qualified proto name for the given message type.func MessageName(x Message) string {	type xname interface {		XXX_MessageName() string	}	if m, ok := x.(xname); ok {		return m.XXX_MessageName()	}	return revProtoTypes[reflect.TypeOf(x)]}// MessageType returns the message type (pointer to struct) for a named message.// The type is not guaranteed to implement proto.Message if the name refers to a// map entry.func MessageType(name string) reflect.Type {	if t, ok := protoTypedNils[name]; ok {		return reflect.TypeOf(t)	}	return protoMapTypes[name]}// A registry of all linked proto files.var (	protoFiles = make(map[string][]byte) // file name => fileDescriptor)// RegisterFile is called from generated code and maps from the// full file name of a .proto file to its compressed FileDescriptorProto.func RegisterFile(filename string, fileDescriptor []byte) {	protoFiles[filename] = fileDescriptor}// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.func FileDescriptor(filename string) []byte { return protoFiles[filename] }
 |