github.com/matm/etcd@v0.3.1-0.20140328024009-5b4a473f1453/third_party/code.google.com/p/gogoprotobuf/proto/lib.go (about)

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2010 The Go Authors.  All rights reserved.
     4  // http://code.google.com/p/goprotobuf/
     5  //
     6  // Redistribution and use in source and binary forms, with or without
     7  // modification, are permitted provided that the following conditions are
     8  // met:
     9  //
    10  //     * Redistributions of source code must retain the above copyright
    11  // notice, this list of conditions and the following disclaimer.
    12  //     * Redistributions in binary form must reproduce the above
    13  // copyright notice, this list of conditions and the following disclaimer
    14  // in the documentation and/or other materials provided with the
    15  // distribution.
    16  //     * Neither the name of Google Inc. nor the names of its
    17  // contributors may be used to endorse or promote products derived from
    18  // this software without specific prior written permission.
    19  //
    20  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    24  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    25  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    26  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    27  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    28  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  
    32  /*
    33  	Package proto converts data structures to and from the wire format of
    34  	protocol buffers.  It works in concert with the Go source code generated
    35  	for .proto files by the protocol compiler.
    36  
    37  	A summary of the properties of the protocol buffer interface
    38  	for a protocol buffer variable v:
    39  
    40  	  - Names are turned from camel_case to CamelCase for export.
    41  	  - There are no methods on v to set fields; just treat
    42  	  	them as structure fields.
    43  	  - There are getters that return a field's value if set,
    44  		and return the field's default value if unset.
    45  		The getters work even if the receiver is a nil message.
    46  	  - The zero value for a struct is its correct initialization state.
    47  		All desired fields must be set before marshaling.
    48  	  - A Reset() method will restore a protobuf struct to its zero state.
    49  	  - Non-repeated fields are pointers to the values; nil means unset.
    50  		That is, optional or required field int32 f becomes F *int32.
    51  	  - Repeated fields are slices.
    52  	  - Helper functions are available to aid the setting of fields.
    53  		Helpers for getting values are superseded by the
    54  		GetFoo methods and their use is deprecated.
    55  			msg.Foo = proto.String("hello") // set field
    56  	  - Constants are defined to hold the default values of all fields that
    57  		have them.  They have the form Default_StructName_FieldName.
    58  		Because the getter methods handle defaulted values,
    59  		direct use of these constants should be rare.
    60  	  - Enums are given type names and maps from names to values.
    61  		Enum values are prefixed with the enum's type name. Enum types have
    62  		a String method, and a Enum method to assist in message construction.
    63  	  - Nested groups and enums have type names prefixed with the name of
    64  	  	the surrounding message type.
    65  	  - Extensions are given descriptor names that start with E_,
    66  		followed by an underscore-delimited list of the nested messages
    67  		that contain it (if any) followed by the CamelCased name of the
    68  		extension field itself.  HasExtension, ClearExtension, GetExtension
    69  		and SetExtension are functions for manipulating extensions.
    70  	  - Marshal and Unmarshal are functions to encode and decode the wire format.
    71  
    72  	The simplest way to describe this is to see an example.
    73  	Given file test.proto, containing
    74  
    75  		package example;
    76  
    77  		enum FOO { X = 17; };
    78  
    79  		message Test {
    80  		  required string label = 1;
    81  		  optional int32 type = 2 [default=77];
    82  		  repeated int64 reps = 3;
    83  		  optional group OptionalGroup = 4 {
    84  		    required string RequiredField = 5;
    85  		  }
    86  		}
    87  
    88  	The resulting file, test.pb.go, is:
    89  
    90  		package example
    91  
    92  		import "github.com/coreos/etcd/third_party/code.google.com/p/gogoprotobuf/proto"
    93  
    94  		type FOO int32
    95  		const (
    96  			FOO_X FOO = 17
    97  		)
    98  		var FOO_name = map[int32]string{
    99  			17: "X",
   100  		}
   101  		var FOO_value = map[string]int32{
   102  			"X": 17,
   103  		}
   104  
   105  		func (x FOO) Enum() *FOO {
   106  			p := new(FOO)
   107  			*p = x
   108  			return p
   109  		}
   110  		func (x FOO) String() string {
   111  			return proto.EnumName(FOO_name, int32(x))
   112  		}
   113  
   114  		type Test struct {
   115  			Label            *string             `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
   116  			Type             *int32              `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
   117  			Reps             []int64             `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
   118  			Optionalgroup    *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
   119  			XXX_unrecognized []byte              `json:"-"`
   120  		}
   121  		func (this *Test) Reset()         { *this = Test{} }
   122  		func (this *Test) String() string { return proto.CompactTextString(this) }
   123  		const Default_Test_Type int32 = 77
   124  
   125  		func (this *Test) GetLabel() string {
   126  			if this != nil && this.Label != nil {
   127  				return *this.Label
   128  			}
   129  			return ""
   130  		}
   131  
   132  		func (this *Test) GetType() int32 {
   133  			if this != nil && this.Type != nil {
   134  				return *this.Type
   135  			}
   136  			return Default_Test_Type
   137  		}
   138  
   139  		func (this *Test) GetOptionalgroup() *Test_OptionalGroup {
   140  			if this != nil {
   141  				return this.Optionalgroup
   142  			}
   143  			return nil
   144  		}
   145  
   146  		type Test_OptionalGroup struct {
   147  			RequiredField    *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
   148  			XXX_unrecognized []byte  `json:"-"`
   149  		}
   150  		func (this *Test_OptionalGroup) Reset()         { *this = Test_OptionalGroup{} }
   151  		func (this *Test_OptionalGroup) String() string { return proto.CompactTextString(this) }
   152  
   153  		func (this *Test_OptionalGroup) GetRequiredField() string {
   154  			if this != nil && this.RequiredField != nil {
   155  				return *this.RequiredField
   156  			}
   157  			return ""
   158  		}
   159  
   160  		func init() {
   161  			proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
   162  		}
   163  
   164  	To create and play with a Test object:
   165  
   166  		package main
   167  
   168  		import (
   169  			"log"
   170  
   171  			"github.com/coreos/etcd/third_party/code.google.com/p/gogoprotobuf/proto"
   172  			"./example.pb"
   173  		)
   174  
   175  		func main() {
   176  			test := &example.Test{
   177  				Label: proto.String("hello"),
   178  				Type:  proto.Int32(17),
   179  				Optionalgroup: &example.Test_OptionalGroup{
   180  					RequiredField: proto.String("good bye"),
   181  				},
   182  			}
   183  			data, err := proto.Marshal(test)
   184  			if err != nil {
   185  				log.Fatal("marshaling error: ", err)
   186  			}
   187  			newTest := new(example.Test)
   188  			err = proto.Unmarshal(data, newTest)
   189  			if err != nil {
   190  				log.Fatal("unmarshaling error: ", err)
   191  			}
   192  			// Now test and newTest contain the same data.
   193  			if test.GetLabel() != newTest.GetLabel() {
   194  				log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
   195  			}
   196  			// etc.
   197  		}
   198  */
   199  package proto
   200  
   201  import (
   202  	"encoding/json"
   203  	"fmt"
   204  	"log"
   205  	"reflect"
   206  	"strconv"
   207  	"sync"
   208  )
   209  
   210  // Message is implemented by generated protocol buffer messages.
   211  type Message interface {
   212  	Reset()
   213  	String() string
   214  	ProtoMessage()
   215  }
   216  
   217  // Stats records allocation details about the protocol buffer encoders
   218  // and decoders.  Useful for tuning the library itself.
   219  type Stats struct {
   220  	Emalloc uint64 // mallocs in encode
   221  	Dmalloc uint64 // mallocs in decode
   222  	Encode  uint64 // number of encodes
   223  	Decode  uint64 // number of decodes
   224  	Chit    uint64 // number of cache hits
   225  	Cmiss   uint64 // number of cache misses
   226  	Size    uint64 // number of sizes
   227  }
   228  
   229  // Set to true to enable stats collection.
   230  const collectStats = false
   231  
   232  var stats Stats
   233  
   234  // GetStats returns a copy of the global Stats structure.
   235  func GetStats() Stats { return stats }
   236  
   237  // A Buffer is a buffer manager for marshaling and unmarshaling
   238  // protocol buffers.  It may be reused between invocations to
   239  // reduce memory usage.  It is not necessary to use a Buffer;
   240  // the global functions Marshal and Unmarshal create a
   241  // temporary Buffer and are fine for most applications.
   242  type Buffer struct {
   243  	buf       []byte     // encode/decode byte stream
   244  	index     int        // write point
   245  	freelist  [10][]byte // list of available buffers
   246  	nfreelist int        // number of free buffers
   247  
   248  	// pools of basic types to amortize allocation.
   249  	bools   []bool
   250  	uint32s []uint32
   251  	uint64s []uint64
   252  
   253  	// extra pools, only used with pointer_reflect.go
   254  	int32s   []int32
   255  	int64s   []int64
   256  	float32s []float32
   257  	float64s []float64
   258  }
   259  
   260  // NewBuffer allocates a new Buffer and initializes its internal data to
   261  // the contents of the argument slice.
   262  func NewBuffer(e []byte) *Buffer {
   263  	p := new(Buffer)
   264  	if e == nil {
   265  		e = p.bufalloc()
   266  	}
   267  	p.buf = e
   268  	p.index = 0
   269  	return p
   270  }
   271  
   272  // Reset resets the Buffer, ready for marshaling a new protocol buffer.
   273  func (p *Buffer) Reset() {
   274  	if p.buf == nil {
   275  		p.buf = p.bufalloc()
   276  	}
   277  	p.buf = p.buf[0:0] // for reading/writing
   278  	p.index = 0        // for reading
   279  }
   280  
   281  // SetBuf replaces the internal buffer with the slice,
   282  // ready for unmarshaling the contents of the slice.
   283  func (p *Buffer) SetBuf(s []byte) {
   284  	p.buf = s
   285  	p.index = 0
   286  }
   287  
   288  // Bytes returns the contents of the Buffer.
   289  func (p *Buffer) Bytes() []byte { return p.buf }
   290  
   291  // Allocate a buffer for the Buffer.
   292  func (p *Buffer) bufalloc() []byte {
   293  	if p.nfreelist > 0 {
   294  		// reuse an old one
   295  		p.nfreelist--
   296  		s := p.freelist[p.nfreelist]
   297  		return s[0:0]
   298  	}
   299  	// make a new one
   300  	s := make([]byte, 0, 16)
   301  	return s
   302  }
   303  
   304  // Free (and remember in freelist) a byte buffer for the Buffer.
   305  func (p *Buffer) buffree(s []byte) {
   306  	if p.nfreelist < len(p.freelist) {
   307  		// Take next slot.
   308  		p.freelist[p.nfreelist] = s
   309  		p.nfreelist++
   310  		return
   311  	}
   312  
   313  	// Find the smallest.
   314  	besti := -1
   315  	bestl := len(s)
   316  	for i, b := range p.freelist {
   317  		if len(b) < bestl {
   318  			besti = i
   319  			bestl = len(b)
   320  		}
   321  	}
   322  
   323  	// Overwrite the smallest.
   324  	if besti >= 0 {
   325  		p.freelist[besti] = s
   326  	}
   327  }
   328  
   329  /*
   330   * Helper routines for simplifying the creation of optional fields of basic type.
   331   */
   332  
   333  // Bool is a helper routine that allocates a new bool value
   334  // to store v and returns a pointer to it.
   335  func Bool(v bool) *bool {
   336  	return &v
   337  }
   338  
   339  // Int32 is a helper routine that allocates a new int32 value
   340  // to store v and returns a pointer to it.
   341  func Int32(v int32) *int32 {
   342  	return &v
   343  }
   344  
   345  // Int is a helper routine that allocates a new int32 value
   346  // to store v and returns a pointer to it, but unlike Int32
   347  // its argument value is an int.
   348  func Int(v int) *int32 {
   349  	p := new(int32)
   350  	*p = int32(v)
   351  	return p
   352  }
   353  
   354  // Int64 is a helper routine that allocates a new int64 value
   355  // to store v and returns a pointer to it.
   356  func Int64(v int64) *int64 {
   357  	return &v
   358  }
   359  
   360  // Float32 is a helper routine that allocates a new float32 value
   361  // to store v and returns a pointer to it.
   362  func Float32(v float32) *float32 {
   363  	return &v
   364  }
   365  
   366  // Float64 is a helper routine that allocates a new float64 value
   367  // to store v and returns a pointer to it.
   368  func Float64(v float64) *float64 {
   369  	return &v
   370  }
   371  
   372  // Uint32 is a helper routine that allocates a new uint32 value
   373  // to store v and returns a pointer to it.
   374  func Uint32(v uint32) *uint32 {
   375  	p := new(uint32)
   376  	*p = v
   377  	return p
   378  }
   379  
   380  // Uint64 is a helper routine that allocates a new uint64 value
   381  // to store v and returns a pointer to it.
   382  func Uint64(v uint64) *uint64 {
   383  	return &v
   384  }
   385  
   386  // String is a helper routine that allocates a new string value
   387  // to store v and returns a pointer to it.
   388  func String(v string) *string {
   389  	return &v
   390  }
   391  
   392  // EnumName is a helper function to simplify printing protocol buffer enums
   393  // by name.  Given an enum map and a value, it returns a useful string.
   394  func EnumName(m map[int32]string, v int32) string {
   395  	s, ok := m[v]
   396  	if ok {
   397  		return s
   398  	}
   399  	return strconv.Itoa(int(v))
   400  }
   401  
   402  // UnmarshalJSONEnum is a helper function to simplify recovering enum int values
   403  // from their JSON-encoded representation. Given a map from the enum's symbolic
   404  // names to its int values, and a byte buffer containing the JSON-encoded
   405  // value, it returns an int32 that can be cast to the enum type by the caller.
   406  //
   407  // The function can deal with both JSON representations, numeric and symbolic.
   408  func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
   409  	if data[0] == '"' {
   410  		// New style: enums are strings.
   411  		var repr string
   412  		if err := json.Unmarshal(data, &repr); err != nil {
   413  			return -1, err
   414  		}
   415  		val, ok := m[repr]
   416  		if !ok {
   417  			return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
   418  		}
   419  		return val, nil
   420  	}
   421  	// Old style: enums are ints.
   422  	var val int32
   423  	if err := json.Unmarshal(data, &val); err != nil {
   424  		return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
   425  	}
   426  	return val, nil
   427  }
   428  
   429  // DebugPrint dumps the encoded data in b in a debugging format with a header
   430  // including the string s. Used in testing but made available for general debugging.
   431  func (o *Buffer) DebugPrint(s string, b []byte) {
   432  	var u uint64
   433  
   434  	obuf := o.buf
   435  	index := o.index
   436  	o.buf = b
   437  	o.index = 0
   438  	depth := 0
   439  
   440  	fmt.Printf("\n--- %s ---\n", s)
   441  
   442  out:
   443  	for {
   444  		for i := 0; i < depth; i++ {
   445  			fmt.Print("  ")
   446  		}
   447  
   448  		index := o.index
   449  		if index == len(o.buf) {
   450  			break
   451  		}
   452  
   453  		op, err := o.DecodeVarint()
   454  		if err != nil {
   455  			fmt.Printf("%3d: fetching op err %v\n", index, err)
   456  			break out
   457  		}
   458  		tag := op >> 3
   459  		wire := op & 7
   460  
   461  		switch wire {
   462  		default:
   463  			fmt.Printf("%3d: t=%3d unknown wire=%d\n",
   464  				index, tag, wire)
   465  			break out
   466  
   467  		case WireBytes:
   468  			var r []byte
   469  
   470  			r, err = o.DecodeRawBytes(false)
   471  			if err != nil {
   472  				break out
   473  			}
   474  			fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
   475  			if len(r) <= 6 {
   476  				for i := 0; i < len(r); i++ {
   477  					fmt.Printf(" %.2x", r[i])
   478  				}
   479  			} else {
   480  				for i := 0; i < 3; i++ {
   481  					fmt.Printf(" %.2x", r[i])
   482  				}
   483  				fmt.Printf(" ..")
   484  				for i := len(r) - 3; i < len(r); i++ {
   485  					fmt.Printf(" %.2x", r[i])
   486  				}
   487  			}
   488  			fmt.Printf("\n")
   489  
   490  		case WireFixed32:
   491  			u, err = o.DecodeFixed32()
   492  			if err != nil {
   493  				fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
   494  				break out
   495  			}
   496  			fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
   497  
   498  		case WireFixed64:
   499  			u, err = o.DecodeFixed64()
   500  			if err != nil {
   501  				fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
   502  				break out
   503  			}
   504  			fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
   505  			break
   506  
   507  		case WireVarint:
   508  			u, err = o.DecodeVarint()
   509  			if err != nil {
   510  				fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
   511  				break out
   512  			}
   513  			fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
   514  
   515  		case WireStartGroup:
   516  			if err != nil {
   517  				fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
   518  				break out
   519  			}
   520  			fmt.Printf("%3d: t=%3d start\n", index, tag)
   521  			depth++
   522  
   523  		case WireEndGroup:
   524  			depth--
   525  			if err != nil {
   526  				fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
   527  				break out
   528  			}
   529  			fmt.Printf("%3d: t=%3d end\n", index, tag)
   530  		}
   531  	}
   532  
   533  	if depth != 0 {
   534  		fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
   535  	}
   536  	fmt.Printf("\n")
   537  
   538  	o.buf = obuf
   539  	o.index = index
   540  }
   541  
   542  // SetDefaults sets unset protocol buffer fields to their default values.
   543  // It only modifies fields that are both unset and have defined defaults.
   544  // It recursively sets default values in any non-nil sub-messages.
   545  func SetDefaults(pb Message) {
   546  	setDefaults(reflect.ValueOf(pb), true, false)
   547  }
   548  
   549  // v is a pointer to a struct.
   550  func setDefaults(v reflect.Value, recur, zeros bool) {
   551  	v = v.Elem()
   552  
   553  	defaultMu.RLock()
   554  	dm, ok := defaults[v.Type()]
   555  	defaultMu.RUnlock()
   556  	if !ok {
   557  		dm = buildDefaultMessage(v.Type())
   558  		defaultMu.Lock()
   559  		defaults[v.Type()] = dm
   560  		defaultMu.Unlock()
   561  	}
   562  
   563  	for _, sf := range dm.scalars {
   564  		f := v.Field(sf.index)
   565  		if !f.IsNil() {
   566  			// field already set
   567  			continue
   568  		}
   569  		dv := sf.value
   570  		if dv == nil && !zeros {
   571  			// no explicit default, and don't want to set zeros
   572  			continue
   573  		}
   574  		fptr := f.Addr().Interface() // **T
   575  		// TODO: Consider batching the allocations we do here.
   576  		switch sf.kind {
   577  		case reflect.Bool:
   578  			b := new(bool)
   579  			if dv != nil {
   580  				*b = dv.(bool)
   581  			}
   582  			*(fptr.(**bool)) = b
   583  		case reflect.Float32:
   584  			f := new(float32)
   585  			if dv != nil {
   586  				*f = dv.(float32)
   587  			}
   588  			*(fptr.(**float32)) = f
   589  		case reflect.Float64:
   590  			f := new(float64)
   591  			if dv != nil {
   592  				*f = dv.(float64)
   593  			}
   594  			*(fptr.(**float64)) = f
   595  		case reflect.Int32:
   596  			// might be an enum
   597  			if ft := f.Type(); ft != int32PtrType {
   598  				// enum
   599  				f.Set(reflect.New(ft.Elem()))
   600  				if dv != nil {
   601  					f.Elem().SetInt(int64(dv.(int32)))
   602  				}
   603  			} else {
   604  				// int32 field
   605  				i := new(int32)
   606  				if dv != nil {
   607  					*i = dv.(int32)
   608  				}
   609  				*(fptr.(**int32)) = i
   610  			}
   611  		case reflect.Int64:
   612  			i := new(int64)
   613  			if dv != nil {
   614  				*i = dv.(int64)
   615  			}
   616  			*(fptr.(**int64)) = i
   617  		case reflect.String:
   618  			s := new(string)
   619  			if dv != nil {
   620  				*s = dv.(string)
   621  			}
   622  			*(fptr.(**string)) = s
   623  		case reflect.Uint8:
   624  			// exceptional case: []byte
   625  			var b []byte
   626  			if dv != nil {
   627  				db := dv.([]byte)
   628  				b = make([]byte, len(db))
   629  				copy(b, db)
   630  			} else {
   631  				b = []byte{}
   632  			}
   633  			*(fptr.(*[]byte)) = b
   634  		case reflect.Uint32:
   635  			u := new(uint32)
   636  			if dv != nil {
   637  				*u = dv.(uint32)
   638  			}
   639  			*(fptr.(**uint32)) = u
   640  		case reflect.Uint64:
   641  			u := new(uint64)
   642  			if dv != nil {
   643  				*u = dv.(uint64)
   644  			}
   645  			*(fptr.(**uint64)) = u
   646  		default:
   647  			log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
   648  		}
   649  	}
   650  
   651  	for _, ni := range dm.nested {
   652  		f := v.Field(ni)
   653  		if f.IsNil() {
   654  			continue
   655  		}
   656  		// f is *T or []*T
   657  		if f.Kind() == reflect.Ptr {
   658  			setDefaults(f, recur, zeros)
   659  		} else {
   660  			for i := 0; i < f.Len(); i++ {
   661  				e := f.Index(i)
   662  				if e.IsNil() {
   663  					continue
   664  				}
   665  				setDefaults(e, recur, zeros)
   666  			}
   667  		}
   668  	}
   669  }
   670  
   671  var (
   672  	// defaults maps a protocol buffer struct type to a slice of the fields,
   673  	// with its scalar fields set to their proto-declared non-zero default values.
   674  	defaultMu sync.RWMutex
   675  	defaults  = make(map[reflect.Type]defaultMessage)
   676  
   677  	int32PtrType = reflect.TypeOf((*int32)(nil))
   678  )
   679  
   680  // defaultMessage represents information about the default values of a message.
   681  type defaultMessage struct {
   682  	scalars []scalarField
   683  	nested  []int // struct field index of nested messages
   684  }
   685  
   686  type scalarField struct {
   687  	index int          // struct field index
   688  	kind  reflect.Kind // element type (the T in *T or []T)
   689  	value interface{}  // the proto-declared default value, or nil
   690  }
   691  
   692  func ptrToStruct(t reflect.Type) bool {
   693  	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
   694  }
   695  
   696  // t is a struct type.
   697  func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
   698  	sprop := GetProperties(t)
   699  	for _, prop := range sprop.Prop {
   700  		fi, ok := sprop.decoderTags.get(prop.Tag)
   701  		if !ok {
   702  			// XXX_unrecognized
   703  			continue
   704  		}
   705  		ft := t.Field(fi).Type
   706  
   707  		// nested messages
   708  		if ptrToStruct(ft) || (ft.Kind() == reflect.Slice && ptrToStruct(ft.Elem())) {
   709  			dm.nested = append(dm.nested, fi)
   710  			continue
   711  		}
   712  
   713  		sf := scalarField{
   714  			index: fi,
   715  			kind:  ft.Elem().Kind(),
   716  		}
   717  
   718  		// scalar fields without defaults
   719  		if prop.Default == "" {
   720  			dm.scalars = append(dm.scalars, sf)
   721  			continue
   722  		}
   723  
   724  		// a scalar field: either *T or []byte
   725  		switch ft.Elem().Kind() {
   726  		case reflect.Bool:
   727  			x, err := strconv.ParseBool(prop.Default)
   728  			if err != nil {
   729  				log.Printf("proto: bad default bool %q: %v", prop.Default, err)
   730  				continue
   731  			}
   732  			sf.value = x
   733  		case reflect.Float32:
   734  			x, err := strconv.ParseFloat(prop.Default, 32)
   735  			if err != nil {
   736  				log.Printf("proto: bad default float32 %q: %v", prop.Default, err)
   737  				continue
   738  			}
   739  			sf.value = float32(x)
   740  		case reflect.Float64:
   741  			x, err := strconv.ParseFloat(prop.Default, 64)
   742  			if err != nil {
   743  				log.Printf("proto: bad default float64 %q: %v", prop.Default, err)
   744  				continue
   745  			}
   746  			sf.value = x
   747  		case reflect.Int32:
   748  			x, err := strconv.ParseInt(prop.Default, 10, 32)
   749  			if err != nil {
   750  				log.Printf("proto: bad default int32 %q: %v", prop.Default, err)
   751  				continue
   752  			}
   753  			sf.value = int32(x)
   754  		case reflect.Int64:
   755  			x, err := strconv.ParseInt(prop.Default, 10, 64)
   756  			if err != nil {
   757  				log.Printf("proto: bad default int64 %q: %v", prop.Default, err)
   758  				continue
   759  			}
   760  			sf.value = x
   761  		case reflect.String:
   762  			sf.value = prop.Default
   763  		case reflect.Uint8:
   764  			// []byte (not *uint8)
   765  			sf.value = []byte(prop.Default)
   766  		case reflect.Uint32:
   767  			x, err := strconv.ParseUint(prop.Default, 10, 32)
   768  			if err != nil {
   769  				log.Printf("proto: bad default uint32 %q: %v", prop.Default, err)
   770  				continue
   771  			}
   772  			sf.value = uint32(x)
   773  		case reflect.Uint64:
   774  			x, err := strconv.ParseUint(prop.Default, 10, 64)
   775  			if err != nil {
   776  				log.Printf("proto: bad default uint64 %q: %v", prop.Default, err)
   777  				continue
   778  			}
   779  			sf.value = x
   780  		default:
   781  			log.Printf("proto: unhandled def kind %v", ft.Elem().Kind())
   782  			continue
   783  		}
   784  
   785  		dm.scalars = append(dm.scalars, sf)
   786  	}
   787  
   788  	return dm
   789  }