blob: dcabe3bc0dc27d1996fb8ebf3ee7846bb6e2f008 [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// Go support for Protocol Buffers - Google's data interchange format
2//
David Symondsee6e9c52012-11-29 08:51:07 +11003// Copyright 2010 The Go Authors. All rights reserved.
David Symonds558f13f2014-11-24 10:28:53 +11004// https://github.com/golang/protobuf
Rob Pikeaaa3a622010-03-20 22:32:34 -07005//
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/*
David Symondsb955ee12015-05-02 04:05:00 +100033Package proto converts data structures to and from the wire format of
34protocol buffers. It works in concert with the Go source code generated
35for .proto files by the protocol compiler.
Rob Pikeaaa3a622010-03-20 22:32:34 -070036
David Symondsb955ee12015-05-02 04:05:00 +100037A summary of the properties of the protocol buffer interface
38for a protocol buffer variable v:
Rob Pikeaaa3a622010-03-20 22:32:34 -070039
David Symondsb955ee12015-05-02 04:05:00 +100040 - 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 msg.Foo = proto.String("hello") // set field
54 - Constants are defined to hold the default values of all fields that
55 have them. They have the form Default_StructName_FieldName.
56 Because the getter methods handle defaulted values,
57 direct use of these constants should be rare.
58 - Enums are given type names and maps from names to values.
59 Enum values are prefixed by the enclosing message's name, or by the
60 enum's type name if it is a top-level enum. Enum types have a String
61 method, and a Enum method to assist in message construction.
62 - Nested messages, groups and enums have type names prefixed with the name of
63 the surrounding message type.
64 - Extensions are given descriptor names that start with E_,
65 followed by an underscore-delimited list of the nested messages
66 that contain it (if any) followed by the CamelCased name of the
67 extension field itself. HasExtension, ClearExtension, GetExtension
68 and SetExtension are functions for manipulating extensions.
David Symonds59b73b32015-08-24 13:22:02 +100069 - Oneof field sets are given a single field in their message,
70 with distinguished wrapper types for each possible field value.
David Symondsb955ee12015-05-02 04:05:00 +100071 - Marshal and Unmarshal are functions to encode and decode the wire format.
Rob Pikeaaa3a622010-03-20 22:32:34 -070072
David Symondsb955ee12015-05-02 04:05:00 +100073The simplest way to describe this is to see an example.
74Given file test.proto, containing
Rob Pikeaaa3a622010-03-20 22:32:34 -070075
David Symondsb955ee12015-05-02 04:05:00 +100076 package example;
Rob Pikeaaa3a622010-03-20 22:32:34 -070077
David Symondsb955ee12015-05-02 04:05:00 +100078 enum FOO { X = 17; }
Rob Pikeaaa3a622010-03-20 22:32:34 -070079
David Symondsb955ee12015-05-02 04:05:00 +100080 message Test {
81 required string label = 1;
82 optional int32 type = 2 [default=77];
83 repeated int64 reps = 3;
84 optional group OptionalGroup = 4 {
85 required string RequiredField = 5;
86 }
Dave Dayef197e12015-09-02 09:30:00 +100087 oneof union {
88 int32 number = 6;
89 string name = 7;
90 }
David Symondsb955ee12015-05-02 04:05:00 +100091 }
92
93The resulting file, test.pb.go, is:
94
95 package example
96
97 import proto "github.com/golang/protobuf/proto"
98 import math "math"
99
100 type FOO int32
101 const (
102 FOO_X FOO = 17
103 )
104 var FOO_name = map[int32]string{
105 17: "X",
106 }
107 var FOO_value = map[string]int32{
108 "X": 17,
109 }
110
111 func (x FOO) Enum() *FOO {
112 p := new(FOO)
113 *p = x
114 return p
115 }
116 func (x FOO) String() string {
117 return proto.EnumName(FOO_name, int32(x))
118 }
119 func (x *FOO) UnmarshalJSON(data []byte) error {
120 value, err := proto.UnmarshalJSONEnum(FOO_value, data)
121 if err != nil {
122 return err
Rob Pikeaaa3a622010-03-20 22:32:34 -0700123 }
David Symondsb955ee12015-05-02 04:05:00 +1000124 *x = FOO(value)
125 return nil
126 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700127
David Symondsb955ee12015-05-02 04:05:00 +1000128 type Test struct {
Dave Dayef197e12015-09-02 09:30:00 +1000129 Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
130 Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
131 Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
132 Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
133 // Types that are valid to be assigned to Union:
134 // *Test_Number
135 // *Test_Name
136 Union isTest_Union `protobuf_oneof:"union"`
137 XXX_unrecognized []byte `json:"-"`
David Symondsb955ee12015-05-02 04:05:00 +1000138 }
139 func (m *Test) Reset() { *m = Test{} }
140 func (m *Test) String() string { return proto.CompactTextString(m) }
Dave Dayef197e12015-09-02 09:30:00 +1000141 func (*Test) ProtoMessage() {}
142
143 type isTest_Union interface {
144 isTest_Union()
145 }
146
147 type Test_Number struct {
148 Number int32 `protobuf:"varint,6,opt,name=number"`
149 }
150 type Test_Name struct {
151 Name string `protobuf:"bytes,7,opt,name=name"`
152 }
153
154 func (*Test_Number) isTest_Union() {}
155 func (*Test_Name) isTest_Union() {}
156
157 func (m *Test) GetUnion() isTest_Union {
158 if m != nil {
159 return m.Union
160 }
161 return nil
162 }
David Symondsb955ee12015-05-02 04:05:00 +1000163 const Default_Test_Type int32 = 77
Rob Pikeaaa3a622010-03-20 22:32:34 -0700164
David Symondsb955ee12015-05-02 04:05:00 +1000165 func (m *Test) GetLabel() string {
166 if m != nil && m.Label != nil {
167 return *m.Label
Rob Pikeaaa3a622010-03-20 22:32:34 -0700168 }
David Symondsb955ee12015-05-02 04:05:00 +1000169 return ""
170 }
171
172 func (m *Test) GetType() int32 {
173 if m != nil && m.Type != nil {
174 return *m.Type
Rob Pikeaaa3a622010-03-20 22:32:34 -0700175 }
David Symondsb955ee12015-05-02 04:05:00 +1000176 return Default_Test_Type
177 }
David Symondsefeca9a2012-05-08 10:36:04 +1000178
David Symondsb955ee12015-05-02 04:05:00 +1000179 func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
180 if m != nil {
181 return m.Optionalgroup
Rob Pikeaaa3a622010-03-20 22:32:34 -0700182 }
David Symondsb955ee12015-05-02 04:05:00 +1000183 return nil
184 }
185
186 type Test_OptionalGroup struct {
187 RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
188 }
189 func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
190 func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
191
192 func (m *Test_OptionalGroup) GetRequiredField() string {
193 if m != nil && m.RequiredField != nil {
194 return *m.RequiredField
David Symonds350c58f2011-08-03 12:09:32 +1000195 }
David Symondsb955ee12015-05-02 04:05:00 +1000196 return ""
197 }
198
Dave Dayef197e12015-09-02 09:30:00 +1000199 func (m *Test) GetNumber() int32 {
200 if x, ok := m.GetUnion().(*Test_Number); ok {
201 return x.Number
202 }
203 return 0
204 }
205
206 func (m *Test) GetName() string {
207 if x, ok := m.GetUnion().(*Test_Name); ok {
208 return x.Name
209 }
210 return ""
211 }
212
David Symondsb955ee12015-05-02 04:05:00 +1000213 func init() {
214 proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
215 }
216
217To create and play with a Test object:
218
David Symondse63abb12015-11-04 09:37:32 +1100219 package main
David Symondsb955ee12015-05-02 04:05:00 +1000220
221 import (
222 "log"
223
224 "github.com/golang/protobuf/proto"
225 pb "./example.pb"
226 )
227
228 func main() {
229 test := &pb.Test{
230 Label: proto.String("hello"),
231 Type: proto.Int32(17),
232 Optionalgroup: &pb.Test_OptionalGroup{
233 RequiredField: proto.String("good bye"),
234 },
Dave Dayef197e12015-09-02 09:30:00 +1000235 Union: &pb.Test_Name{"fred"},
David Symonds1e735162015-02-09 11:05:25 +1100236 }
David Symondsb955ee12015-05-02 04:05:00 +1000237 data, err := proto.Marshal(test)
238 if err != nil {
239 log.Fatal("marshaling error: ", err)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700240 }
David Symondsb955ee12015-05-02 04:05:00 +1000241 newTest := &pb.Test{}
242 err = proto.Unmarshal(data, newTest)
243 if err != nil {
244 log.Fatal("unmarshaling error: ", err)
David Symonds87c9bcc2012-06-28 10:42:01 -0700245 }
David Symondsb955ee12015-05-02 04:05:00 +1000246 // Now test and newTest contain the same data.
247 if test.GetLabel() != newTest.GetLabel() {
248 log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
David Symonds87c9bcc2012-06-28 10:42:01 -0700249 }
Dave Dayef197e12015-09-02 09:30:00 +1000250 // Use a type switch to determine which oneof was set.
251 switch u := test.Union.(type) {
252 case *pb.Test_Number: // u.Number contains the number.
253 case *pb.Test_Name: // u.Name contains the string.
254 }
David Symondsb955ee12015-05-02 04:05:00 +1000255 // etc.
256 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700257*/
258package proto
259
260import (
David Symonds62539862012-08-04 10:06:55 +1000261 "encoding/json"
Rob Pikeaaa3a622010-03-20 22:32:34 -0700262 "fmt"
David Symondsb79d99b2011-08-29 16:38:49 +1000263 "log"
264 "reflect"
David Symonds66836542015-07-25 20:00:00 +1000265 "sort"
Rob Pikeaaa3a622010-03-20 22:32:34 -0700266 "strconv"
David Symondsb79d99b2011-08-29 16:38:49 +1000267 "sync"
Rob Pikeaaa3a622010-03-20 22:32:34 -0700268)
269
David Symonds9f60f432012-06-14 09:45:25 +1000270// Message is implemented by generated protocol buffer messages.
271type Message interface {
272 Reset()
273 String() string
274 ProtoMessage()
275}
276
Rob Pikeaaa3a622010-03-20 22:32:34 -0700277// Stats records allocation details about the protocol buffer encoders
278// and decoders. Useful for tuning the library itself.
279type Stats struct {
280 Emalloc uint64 // mallocs in encode
281 Dmalloc uint64 // mallocs in decode
282 Encode uint64 // number of encodes
283 Decode uint64 // number of decodes
284 Chit uint64 // number of cache hits
285 Cmiss uint64 // number of cache misses
David Symonds0bf1ad52013-10-11 09:07:50 +1100286 Size uint64 // number of sizes
Rob Pikeaaa3a622010-03-20 22:32:34 -0700287}
288
David Symonds9f60f432012-06-14 09:45:25 +1000289// Set to true to enable stats collection.
290const collectStats = false
291
Rob Pikeaaa3a622010-03-20 22:32:34 -0700292var stats Stats
293
294// GetStats returns a copy of the global Stats structure.
295func GetStats() Stats { return stats }
296
297// A Buffer is a buffer manager for marshaling and unmarshaling
298// protocol buffers. It may be reused between invocations to
299// reduce memory usage. It is not necessary to use a Buffer;
300// the global functions Marshal and Unmarshal create a
301// temporary Buffer and are fine for most applications.
302type Buffer struct {
David Symonds8b253302014-01-14 16:24:19 +1100303 buf []byte // encode/decode byte stream
304 index int // write point
Russ Coxd4ce3f12012-09-12 10:36:26 +1000305
Rob Pike76f6ee52011-10-20 12:58:28 -0700306 // pools of basic types to amortize allocation.
Russ Coxd4ce3f12012-09-12 10:36:26 +1000307 bools []bool
308 uint32s []uint32
309 uint64s []uint64
310
311 // extra pools, only used with pointer_reflect.go
312 int32s []int32
313 int64s []int64
314 float32s []float32
315 float64s []float64
Rob Pikeaaa3a622010-03-20 22:32:34 -0700316}
317
318// NewBuffer allocates a new Buffer and initializes its internal data to
319// the contents of the argument slice.
320func NewBuffer(e []byte) *Buffer {
David Symonds8b253302014-01-14 16:24:19 +1100321 return &Buffer{buf: e}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700322}
323
324// Reset resets the Buffer, ready for marshaling a new protocol buffer.
325func (p *Buffer) Reset() {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700326 p.buf = p.buf[0:0] // for reading/writing
327 p.index = 0 // for reading
328}
329
330// SetBuf replaces the internal buffer with the slice,
331// ready for unmarshaling the contents of the slice.
332func (p *Buffer) SetBuf(s []byte) {
333 p.buf = s
334 p.index = 0
335}
336
337// Bytes returns the contents of the Buffer.
338func (p *Buffer) Bytes() []byte { return p.buf }
339
Rob Pikeaaa3a622010-03-20 22:32:34 -0700340/*
341 * Helper routines for simplifying the creation of optional fields of basic type.
342 */
343
344// Bool is a helper routine that allocates a new bool value
345// to store v and returns a pointer to it.
346func Bool(v bool) *bool {
David Symondsfff2ec62013-08-08 13:37:09 +1000347 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700348}
349
350// Int32 is a helper routine that allocates a new int32 value
351// to store v and returns a pointer to it.
352func Int32(v int32) *int32 {
David Symondsfff2ec62013-08-08 13:37:09 +1000353 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700354}
355
356// Int is a helper routine that allocates a new int32 value
357// to store v and returns a pointer to it, but unlike Int32
358// its argument value is an int.
359func Int(v int) *int32 {
360 p := new(int32)
361 *p = int32(v)
362 return p
363}
364
365// Int64 is a helper routine that allocates a new int64 value
366// to store v and returns a pointer to it.
367func Int64(v int64) *int64 {
David Symondsfff2ec62013-08-08 13:37:09 +1000368 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700369}
370
371// Float32 is a helper routine that allocates a new float32 value
372// to store v and returns a pointer to it.
373func Float32(v float32) *float32 {
David Symondsfff2ec62013-08-08 13:37:09 +1000374 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700375}
376
377// Float64 is a helper routine that allocates a new float64 value
378// to store v and returns a pointer to it.
379func Float64(v float64) *float64 {
David Symondsfff2ec62013-08-08 13:37:09 +1000380 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700381}
382
383// Uint32 is a helper routine that allocates a new uint32 value
384// to store v and returns a pointer to it.
385func Uint32(v uint32) *uint32 {
David Symonds60976d32015-01-06 07:56:48 +1100386 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700387}
388
389// Uint64 is a helper routine that allocates a new uint64 value
390// to store v and returns a pointer to it.
391func Uint64(v uint64) *uint64 {
David Symondsfff2ec62013-08-08 13:37:09 +1000392 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700393}
394
395// String is a helper routine that allocates a new string value
396// to store v and returns a pointer to it.
397func String(v string) *string {
David Symondsfff2ec62013-08-08 13:37:09 +1000398 return &v
Rob Pikeaaa3a622010-03-20 22:32:34 -0700399}
400
Rob Pikeaaa3a622010-03-20 22:32:34 -0700401// EnumName is a helper function to simplify printing protocol buffer enums
402// by name. Given an enum map and a value, it returns a useful string.
403func EnumName(m map[int32]string, v int32) string {
404 s, ok := m[v]
405 if ok {
406 return s
407 }
David Symondsf8a1fcc2013-05-03 08:51:23 +1000408 return strconv.Itoa(int(v))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700409}
410
David Symonds62539862012-08-04 10:06:55 +1000411// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
412// from their JSON-encoded representation. Given a map from the enum's symbolic
413// names to its int values, and a byte buffer containing the JSON-encoded
414// value, it returns an int32 that can be cast to the enum type by the caller.
415//
David Symonds4af5f1f2013-10-11 10:08:35 +1100416// The function can deal with both JSON representations, numeric and symbolic.
David Symonds62539862012-08-04 10:06:55 +1000417func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
418 if data[0] == '"' {
419 // New style: enums are strings.
420 var repr string
421 if err := json.Unmarshal(data, &repr); err != nil {
422 return -1, err
423 }
424 val, ok := m[repr]
425 if !ok {
426 return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
427 }
428 return val, nil
429 }
430 // Old style: enums are ints.
431 var val int32
432 if err := json.Unmarshal(data, &val); err != nil {
433 return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
434 }
435 return val, nil
436}
437
Rob Pikeaaa3a622010-03-20 22:32:34 -0700438// DebugPrint dumps the encoded data in b in a debugging format with a header
439// including the string s. Used in testing but made available for general debugging.
David Symondsb955ee12015-05-02 04:05:00 +1000440func (p *Buffer) DebugPrint(s string, b []byte) {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700441 var u uint64
442
David Symondsb955ee12015-05-02 04:05:00 +1000443 obuf := p.buf
444 index := p.index
445 p.buf = b
446 p.index = 0
Rob Pikeaaa3a622010-03-20 22:32:34 -0700447 depth := 0
448
449 fmt.Printf("\n--- %s ---\n", s)
450
451out:
452 for {
453 for i := 0; i < depth; i++ {
454 fmt.Print(" ")
455 }
456
David Symondsb955ee12015-05-02 04:05:00 +1000457 index := p.index
458 if index == len(p.buf) {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700459 break
460 }
461
David Symondsb955ee12015-05-02 04:05:00 +1000462 op, err := p.DecodeVarint()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700463 if err != nil {
464 fmt.Printf("%3d: fetching op err %v\n", index, err)
465 break out
466 }
467 tag := op >> 3
468 wire := op & 7
469
470 switch wire {
471 default:
472 fmt.Printf("%3d: t=%3d unknown wire=%d\n",
473 index, tag, wire)
474 break out
475
476 case WireBytes:
477 var r []byte
478
David Symondsb955ee12015-05-02 04:05:00 +1000479 r, err = p.DecodeRawBytes(false)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700480 if err != nil {
481 break out
482 }
483 fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
484 if len(r) <= 6 {
485 for i := 0; i < len(r); i++ {
486 fmt.Printf(" %.2x", r[i])
487 }
488 } else {
489 for i := 0; i < 3; i++ {
490 fmt.Printf(" %.2x", r[i])
491 }
492 fmt.Printf(" ..")
493 for i := len(r) - 3; i < len(r); i++ {
494 fmt.Printf(" %.2x", r[i])
495 }
496 }
497 fmt.Printf("\n")
498
499 case WireFixed32:
David Symondsb955ee12015-05-02 04:05:00 +1000500 u, err = p.DecodeFixed32()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700501 if err != nil {
502 fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
503 break out
504 }
505 fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
506
507 case WireFixed64:
David Symondsb955ee12015-05-02 04:05:00 +1000508 u, err = p.DecodeFixed64()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700509 if err != nil {
510 fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
511 break out
512 }
513 fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700514
515 case WireVarint:
David Symondsb955ee12015-05-02 04:05:00 +1000516 u, err = p.DecodeVarint()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700517 if err != nil {
518 fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
519 break out
520 }
521 fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
522
523 case WireStartGroup:
Rob Pikeaaa3a622010-03-20 22:32:34 -0700524 fmt.Printf("%3d: t=%3d start\n", index, tag)
525 depth++
526
527 case WireEndGroup:
528 depth--
Rob Pikeaaa3a622010-03-20 22:32:34 -0700529 fmt.Printf("%3d: t=%3d end\n", index, tag)
530 }
531 }
532
533 if depth != 0 {
David Symondsb955ee12015-05-02 04:05:00 +1000534 fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700535 }
536 fmt.Printf("\n")
537
David Symondsb955ee12015-05-02 04:05:00 +1000538 p.buf = obuf
539 p.index = index
Rob Pikeaaa3a622010-03-20 22:32:34 -0700540}
David Symondsb79d99b2011-08-29 16:38:49 +1000541
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.
David Symonds9f60f432012-06-14 09:45:25 +1000545func SetDefaults(pb Message) {
546 setDefaults(reflect.ValueOf(pb), true, false)
David Symondsb79d99b2011-08-29 16:38:49 +1000547}
548
549// v is a pointer to a struct.
550func setDefaults(v reflect.Value, recur, zeros bool) {
551 v = v.Elem()
552
David Symonds72607582011-11-01 12:52:01 +1100553 defaultMu.RLock()
David Symondsb79d99b2011-08-29 16:38:49 +1000554 dm, ok := defaults[v.Type()]
David Symonds72607582011-11-01 12:52:01 +1100555 defaultMu.RUnlock()
David Symondsb79d99b2011-08-29 16:38:49 +1000556 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 {
David Symonds814b9362011-12-13 09:10:47 +1100652 f := v.Field(ni)
David Symondsde8c5232015-03-20 16:29:30 +1100653 // f is *T or []*T or map[T]*T
654 switch f.Kind() {
655 case reflect.Ptr:
656 if f.IsNil() {
657 continue
658 }
David Symonds472e2592013-07-15 11:10:07 +1000659 setDefaults(f, recur, zeros)
David Symondsde8c5232015-03-20 16:29:30 +1100660
661 case reflect.Slice:
David Symonds472e2592013-07-15 11:10:07 +1000662 for i := 0; i < f.Len(); i++ {
663 e := f.Index(i)
664 if e.IsNil() {
665 continue
666 }
667 setDefaults(e, recur, zeros)
668 }
David Symondsde8c5232015-03-20 16:29:30 +1100669
670 case reflect.Map:
671 for _, k := range f.MapKeys() {
672 e := f.MapIndex(k)
673 if e.IsNil() {
674 continue
675 }
676 setDefaults(e, recur, zeros)
677 }
David Symonds472e2592013-07-15 11:10:07 +1000678 }
David Symondsb79d99b2011-08-29 16:38:49 +1000679 }
680}
681
682var (
683 // defaults maps a protocol buffer struct type to a slice of the fields,
684 // with its scalar fields set to their proto-declared non-zero default values.
David Symonds72607582011-11-01 12:52:01 +1100685 defaultMu sync.RWMutex
David Symondsb79d99b2011-08-29 16:38:49 +1000686 defaults = make(map[reflect.Type]defaultMessage)
687
688 int32PtrType = reflect.TypeOf((*int32)(nil))
689)
690
691// defaultMessage represents information about the default values of a message.
692type defaultMessage struct {
693 scalars []scalarField
694 nested []int // struct field index of nested messages
695}
696
697type scalarField struct {
698 index int // struct field index
699 kind reflect.Kind // element type (the T in *T or []T)
700 value interface{} // the proto-declared default value, or nil
701}
702
703// t is a struct type.
704func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
705 sprop := GetProperties(t)
706 for _, prop := range sprop.Prop {
David Symonds2bba1b22012-09-26 14:53:08 +1000707 fi, ok := sprop.decoderTags.get(prop.Tag)
David Symonds6a6f82c2012-08-22 09:18:54 +1000708 if !ok {
709 // XXX_unrecognized
710 continue
711 }
David Symondsb79d99b2011-08-29 16:38:49 +1000712 ft := t.Field(fi).Type
713
David Symondsc8ba1152015-05-21 01:23:00 +1000714 sf, nested, err := fieldDefault(ft, prop)
715 switch {
716 case err != nil:
717 log.Print(err)
718 case nested:
719 dm.nested = append(dm.nested, fi)
720 case sf != nil:
721 sf.index = fi
722 dm.scalars = append(dm.scalars, *sf)
David Symondsde8c5232015-03-20 16:29:30 +1100723 }
David Symondsb79d99b2011-08-29 16:38:49 +1000724 }
725
726 return dm
727}
David Symonds7f079252015-01-09 11:09:00 +1100728
David Symondsc8ba1152015-05-21 01:23:00 +1000729// fieldDefault returns the scalarField for field type ft.
730// sf will be nil if the field can not have a default.
731// nestedMessage will be true if this is a nested message.
732// Note that sf.index is not set on return.
733func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
734 var canHaveDefault bool
735 switch ft.Kind() {
736 case reflect.Ptr:
737 if ft.Elem().Kind() == reflect.Struct {
738 nestedMessage = true
739 } else {
740 canHaveDefault = true // proto2 scalar field
741 }
742
743 case reflect.Slice:
744 switch ft.Elem().Kind() {
745 case reflect.Ptr:
746 nestedMessage = true // repeated message
747 case reflect.Uint8:
748 canHaveDefault = true // bytes field
749 }
750
751 case reflect.Map:
752 if ft.Elem().Kind() == reflect.Ptr {
753 nestedMessage = true // map with message values
754 }
755 }
756
757 if !canHaveDefault {
758 if nestedMessage {
759 return nil, true, nil
760 }
761 return nil, false, nil
762 }
763
764 // We now know that ft is a pointer or slice.
765 sf = &scalarField{kind: ft.Elem().Kind()}
766
767 // scalar fields without defaults
768 if !prop.HasDefault {
769 return sf, false, nil
770 }
771
772 // a scalar field: either *T or []byte
773 switch ft.Elem().Kind() {
774 case reflect.Bool:
775 x, err := strconv.ParseBool(prop.Default)
776 if err != nil {
777 return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
778 }
779 sf.value = x
780 case reflect.Float32:
781 x, err := strconv.ParseFloat(prop.Default, 32)
782 if err != nil {
783 return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
784 }
785 sf.value = float32(x)
786 case reflect.Float64:
787 x, err := strconv.ParseFloat(prop.Default, 64)
788 if err != nil {
789 return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
790 }
791 sf.value = x
792 case reflect.Int32:
793 x, err := strconv.ParseInt(prop.Default, 10, 32)
794 if err != nil {
795 return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
796 }
797 sf.value = int32(x)
798 case reflect.Int64:
799 x, err := strconv.ParseInt(prop.Default, 10, 64)
800 if err != nil {
801 return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
802 }
803 sf.value = x
804 case reflect.String:
805 sf.value = prop.Default
806 case reflect.Uint8:
807 // []byte (not *uint8)
808 sf.value = []byte(prop.Default)
809 case reflect.Uint32:
810 x, err := strconv.ParseUint(prop.Default, 10, 32)
811 if err != nil {
812 return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
813 }
814 sf.value = uint32(x)
815 case reflect.Uint64:
816 x, err := strconv.ParseUint(prop.Default, 10, 64)
817 if err != nil {
818 return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
819 }
820 sf.value = x
821 default:
822 return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
823 }
824
825 return sf, false, nil
826}
827
David Symonds7f079252015-01-09 11:09:00 +1100828// Map fields may have key types of non-float scalars, strings and enums.
829// The easiest way to sort them in some deterministic order is to use fmt.
830// If this turns out to be inefficient we can always consider other options,
831// such as doing a Schwartzian transform.
832
David Symonds66836542015-07-25 20:00:00 +1000833func mapKeys(vs []reflect.Value) sort.Interface {
834 s := mapKeySorter{
835 vs: vs,
836 // default Less function: textual comparison
837 less: func(a, b reflect.Value) bool {
838 return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
839 },
840 }
David Symonds7f079252015-01-09 11:09:00 +1100841
David Symonds66836542015-07-25 20:00:00 +1000842 // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
843 // numeric keys are sorted numerically.
844 if len(vs) == 0 {
845 return s
846 }
847 switch vs[0].Kind() {
848 case reflect.Int32, reflect.Int64:
849 s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
850 case reflect.Uint32, reflect.Uint64:
851 s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
852 }
853
854 return s
855}
856
857type mapKeySorter struct {
858 vs []reflect.Value
859 less func(a, b reflect.Value) bool
860}
861
862func (s mapKeySorter) Len() int { return len(s.vs) }
863func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
864func (s mapKeySorter) Less(i, j int) bool {
865 return s.less(s.vs[i], s.vs[j])
David Symonds7f079252015-01-09 11:09:00 +1100866}
David Symondsab974be2015-07-07 21:13:00 -0600867
868// isProto3Zero reports whether v is a zero proto3 value.
869func isProto3Zero(v reflect.Value) bool {
870 switch v.Kind() {
871 case reflect.Bool:
872 return !v.Bool()
873 case reflect.Int32, reflect.Int64:
874 return v.Int() == 0
875 case reflect.Uint32, reflect.Uint64:
876 return v.Uint() == 0
877 case reflect.Float32, reflect.Float64:
878 return v.Float() == 0
879 case reflect.String:
880 return v.String() == ""
881 }
882 return false
883}