blob: 083f104375746d1766e7ea96b307b5af67c6a6cb [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// Go support for Protocol Buffers - Google's data interchange format
2//
3// Copyright 2010 Google Inc. 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 The proto package converts data structures to and from the
34 wire format of protocol buffers. It works in concert with the
35 Go source code generated 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 and get fields; just treat
42 them as structure fields.
43 - The zero value for a struct is its correct initialization state.
44 All desired fields must be set before marshaling.
45 - A Reset() method will restore a protobuf struct to its zero state.
Rob Pikeaaa3a622010-03-20 22:32:34 -070046 - Non-repeated fields are pointers to the values; nil means unset.
47 That is, optional or required field int32 f becomes F *int32.
48 - Repeated fields are slices.
49 - Helper functions are available to simplify the getting and setting of fields:
50 foo.String = proto.String("hello") // set field
51 s := proto.GetString(foo.String) // get field
52 - Constants are defined to hold the default values of all fields that
53 have them. They have the form Default_StructName_FieldName.
54 - Enums are given type names and maps between names to values,
55 plus a helper function to create values. Enum values are prefixed
56 with the enum's type name.
57 - Nested groups and enums have type names prefixed with the name of
58 the surrounding message type.
David Symonds9bd0a832010-04-11 10:02:32 +100059 - Extensions are given descriptor names that start with E_,
60 followed by an underscore-delimited list of the nested messages
61 that contain it (if any) followed by the CamelCased name of the
62 extension field itself. HasExtension, ClearExtension, GetExtension
63 and SetExtension are functions for manipulating extensions.
Rob Pikeaaa3a622010-03-20 22:32:34 -070064 - Marshal and Unmarshal are functions to encode and decode the wire format.
65
66 The simplest way to describe this is to see an example.
67 Given file test.proto, containing
68
69 package example;
70
71 enum FOO { X = 17; };
72
73 message Test {
74 required string label = 1;
75 optional int32 type = 2 [default=77];
76 repeated int64 reps = 3;
77 optional group OptionalGroup = 4 {
78 required string RequiredField = 5;
79 };
80 }
81
82 The resulting file, test.pb.go, is:
83
84 package example
85
86 import "goprotobuf.googlecode.com/hg/proto"
87
88 type FOO int32
89 const (
90 FOO_X = 17
91 )
92 var FOO_name = map[int32] string {
93 17: "X",
94 }
95 var FOO_value = map[string] int32 {
96 "X": 17,
97 }
98 func NewFOO(x int32) *FOO {
99 e := FOO(x)
100 return &e
101 }
102
103 type Test struct {
104 Label *string "PB(bytes,1,req,name=label)"
105 Type *int32 "PB(varint,2,opt,name=type,def=77)"
106 Reps []int64 "PB(varint,3,rep,name=reps)"
107 Optionalgroup *Test_OptionalGroup "PB(group,4,opt,name=optionalgroup)"
108 XXX_unrecognized []byte
109 }
110 func (this *Test) Reset() {
111 *this = Test{}
112 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700113 const Default_Test_Type int32 = 77
114
115 type Test_OptionalGroup struct {
116 RequiredField *string "PB(bytes,5,req)"
117 XXX_unrecognized []byte
118 }
119 func (this *Test_OptionalGroup) Reset() {
120 *this = Test_OptionalGroup{}
121 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700122
123 func init() {
124 proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
125 }
126
127 To create and play with a Test object:
128
129 package main
130
131 import (
132 "log"
133
134 "goprotobuf.googlecode.com/hg/proto"
135 "./example.pb"
136 )
137
138 func main() {
David Symondscc7142e2010-11-06 14:37:15 +1100139 test := &example.Test{
Rob Pikeaaa3a622010-03-20 22:32:34 -0700140 Label: proto.String("hello"),
141 Type: proto.Int32(17),
David Symondscc7142e2010-11-06 14:37:15 +1100142 Optionalgroup: &example.Test_OptionalGroup{
Rob Pikeaaa3a622010-03-20 22:32:34 -0700143 RequiredField: proto.String("good bye"),
144 },
145 }
146 data, err := proto.Marshal(test)
147 if err != nil {
David Symondscc7142e2010-11-06 14:37:15 +1100148 log.Exit("marshaling error:", err)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700149 }
David Symondscc7142e2010-11-06 14:37:15 +1100150 newTest := new(example.Test)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700151 err = proto.Unmarshal(data, newTest)
152 if err != nil {
David Symondscc7142e2010-11-06 14:37:15 +1100153 log.Exit("unmarshaling error:", err)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700154 }
155 // Now test and newTest contain the same data.
156 if proto.GetString(test.Label) != proto.GetString(newTest.Label) {
David Symondscc7142e2010-11-06 14:37:15 +1100157 log.Exit("data mismatch %q %q", proto.GetString(test.Label), proto.GetString(newTest.Label))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700158 }
159 // etc.
160 }
161*/
162package proto
163
164import (
165 "fmt"
166 "strconv"
167)
168
169// Stats records allocation details about the protocol buffer encoders
170// and decoders. Useful for tuning the library itself.
171type Stats struct {
172 Emalloc uint64 // mallocs in encode
173 Dmalloc uint64 // mallocs in decode
174 Encode uint64 // number of encodes
175 Decode uint64 // number of decodes
176 Chit uint64 // number of cache hits
177 Cmiss uint64 // number of cache misses
178}
179
180var stats Stats
181
182// GetStats returns a copy of the global Stats structure.
183func GetStats() Stats { return stats }
184
185// A Buffer is a buffer manager for marshaling and unmarshaling
186// protocol buffers. It may be reused between invocations to
187// reduce memory usage. It is not necessary to use a Buffer;
188// the global functions Marshal and Unmarshal create a
189// temporary Buffer and are fine for most applications.
190type Buffer struct {
191 buf []byte // encode/decode byte stream
192 index int // write point
193 freelist [10][]byte // list of available buffers
194 nfreelist int // number of free buffers
195 ptr uintptr // scratch area for pointers
196}
197
198// NewBuffer allocates a new Buffer and initializes its internal data to
199// the contents of the argument slice.
200func NewBuffer(e []byte) *Buffer {
201 p := new(Buffer)
202 if e == nil {
203 e = p.bufalloc()
204 }
205 p.buf = e
206 p.index = 0
207 return p
208}
209
210// Reset resets the Buffer, ready for marshaling a new protocol buffer.
211func (p *Buffer) Reset() {
212 if p.buf == nil {
213 p.buf = p.bufalloc()
214 }
215 p.buf = p.buf[0:0] // for reading/writing
216 p.index = 0 // for reading
217}
218
219// SetBuf replaces the internal buffer with the slice,
220// ready for unmarshaling the contents of the slice.
221func (p *Buffer) SetBuf(s []byte) {
222 p.buf = s
223 p.index = 0
224}
225
226// Bytes returns the contents of the Buffer.
227func (p *Buffer) Bytes() []byte { return p.buf }
228
229// Allocate a buffer for the Buffer.
230func (p *Buffer) bufalloc() []byte {
231 if p.nfreelist > 0 {
232 // reuse an old one
233 p.nfreelist--
234 s := p.freelist[p.nfreelist]
235 return s[0:0]
236 }
237 // make a new one
238 s := make([]byte, 0, 16)
239 return s
240}
241
242// Free (and remember in freelist) a byte buffer for the Buffer.
243func (p *Buffer) buffree(s []byte) {
244 if p.nfreelist < len(p.freelist) {
245 // Take next slot.
246 p.freelist[p.nfreelist] = s
247 p.nfreelist++
248 return
249 }
250
251 // Find the smallest.
252 besti := -1
253 bestl := len(s)
254 for i, b := range p.freelist {
255 if len(b) < bestl {
256 besti = i
257 bestl = len(b)
258 }
259 }
260
261 // Overwrite the smallest.
262 if besti >= 0 {
263 p.freelist[besti] = s
264 }
265}
266
267/*
268 * Helper routines for simplifying the creation of optional fields of basic type.
269 */
270
271// Bool is a helper routine that allocates a new bool value
272// to store v and returns a pointer to it.
273func Bool(v bool) *bool {
274 p := new(bool)
275 *p = v
276 return p
277}
278
279// Int32 is a helper routine that allocates a new int32 value
280// to store v and returns a pointer to it.
281func Int32(v int32) *int32 {
282 p := new(int32)
283 *p = v
284 return p
285}
286
287// Int is a helper routine that allocates a new int32 value
288// to store v and returns a pointer to it, but unlike Int32
289// its argument value is an int.
290func Int(v int) *int32 {
291 p := new(int32)
292 *p = int32(v)
293 return p
294}
295
296// Int64 is a helper routine that allocates a new int64 value
297// to store v and returns a pointer to it.
298func Int64(v int64) *int64 {
299 p := new(int64)
300 *p = v
301 return p
302}
303
304// Float32 is a helper routine that allocates a new float32 value
305// to store v and returns a pointer to it.
306func Float32(v float32) *float32 {
307 p := new(float32)
308 *p = v
309 return p
310}
311
312// Float64 is a helper routine that allocates a new float64 value
313// to store v and returns a pointer to it.
314func Float64(v float64) *float64 {
315 p := new(float64)
316 *p = v
317 return p
318}
319
320// Uint32 is a helper routine that allocates a new uint32 value
321// to store v and returns a pointer to it.
322func Uint32(v uint32) *uint32 {
323 p := new(uint32)
324 *p = v
325 return p
326}
327
328// Uint64 is a helper routine that allocates a new uint64 value
329// to store v and returns a pointer to it.
330func Uint64(v uint64) *uint64 {
331 p := new(uint64)
332 *p = v
333 return p
334}
335
336// String is a helper routine that allocates a new string value
337// to store v and returns a pointer to it.
338func String(v string) *string {
339 p := new(string)
340 *p = v
341 return p
342}
343
344/*
345 * Helper routines for simplifying the fetching of optional fields of basic type.
346 * If the field is missing, they return the zero for the type.
347 */
348
349// GetBool is a helper routine that returns an optional bool value.
350func GetBool(p *bool) bool {
351 if p == nil {
352 return false
353 }
354 return *p
355}
356
357// GetInt32 is a helper routine that returns an optional int32 value.
358func GetInt32(p *int32) int32 {
359 if p == nil {
360 return 0
361 }
362 return *p
363}
364
365// GetInt64 is a helper routine that returns an optional int64 value.
366func GetInt64(p *int64) int64 {
367 if p == nil {
368 return 0
369 }
370 return *p
371}
372
373// GetFloat32 is a helper routine that returns an optional float32 value.
374func GetFloat32(p *float32) float32 {
375 if p == nil {
376 return 0
377 }
378 return *p
379}
380
381// GetFloat64 is a helper routine that returns an optional float64 value.
382func GetFloat64(p *float64) float64 {
383 if p == nil {
384 return 0
385 }
386 return *p
387}
388
389// GetUint32 is a helper routine that returns an optional uint32 value.
390func GetUint32(p *uint32) uint32 {
391 if p == nil {
392 return 0
393 }
394 return *p
395}
396
397// GetUint64 is a helper routine that returns an optional uint64 value.
398func GetUint64(p *uint64) uint64 {
399 if p == nil {
400 return 0
401 }
402 return *p
403}
404
405// GetString is a helper routine that returns an optional string value.
406func GetString(p *string) string {
407 if p == nil {
408 return ""
409 }
410 return *p
411}
412
413// EnumName is a helper function to simplify printing protocol buffer enums
414// by name. Given an enum map and a value, it returns a useful string.
415func EnumName(m map[int32]string, v int32) string {
416 s, ok := m[v]
417 if ok {
418 return s
419 }
420 return "unknown_enum_" + strconv.Itoa(int(v))
421}
422
423// DebugPrint dumps the encoded data in b in a debugging format with a header
424// including the string s. Used in testing but made available for general debugging.
425func (o *Buffer) DebugPrint(s string, b []byte) {
426 var u uint64
427
428 obuf := o.buf
429 index := o.index
430 o.buf = b
431 o.index = 0
432 depth := 0
433
434 fmt.Printf("\n--- %s ---\n", s)
435
436out:
437 for {
438 for i := 0; i < depth; i++ {
439 fmt.Print(" ")
440 }
441
442 index := o.index
443 if index == len(o.buf) {
444 break
445 }
446
447 op, err := o.DecodeVarint()
448 if err != nil {
449 fmt.Printf("%3d: fetching op err %v\n", index, err)
450 break out
451 }
452 tag := op >> 3
453 wire := op & 7
454
455 switch wire {
456 default:
457 fmt.Printf("%3d: t=%3d unknown wire=%d\n",
458 index, tag, wire)
459 break out
460
461 case WireBytes:
462 var r []byte
463
464 r, err = o.DecodeRawBytes(false)
465 if err != nil {
466 break out
467 }
468 fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
469 if len(r) <= 6 {
470 for i := 0; i < len(r); i++ {
471 fmt.Printf(" %.2x", r[i])
472 }
473 } else {
474 for i := 0; i < 3; i++ {
475 fmt.Printf(" %.2x", r[i])
476 }
477 fmt.Printf(" ..")
478 for i := len(r) - 3; i < len(r); i++ {
479 fmt.Printf(" %.2x", r[i])
480 }
481 }
482 fmt.Printf("\n")
483
484 case WireFixed32:
485 u, err = o.DecodeFixed32()
486 if err != nil {
487 fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
488 break out
489 }
490 fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
491
492 case WireFixed64:
493 u, err = o.DecodeFixed64()
494 if err != nil {
495 fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
496 break out
497 }
498 fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
499 break
500
501 case WireVarint:
502 u, err = o.DecodeVarint()
503 if err != nil {
504 fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
505 break out
506 }
507 fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
508
509 case WireStartGroup:
510 if err != nil {
511 fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
512 break out
513 }
514 fmt.Printf("%3d: t=%3d start\n", index, tag)
515 depth++
516
517 case WireEndGroup:
518 depth--
519 if err != nil {
520 fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
521 break out
522 }
523 fmt.Printf("%3d: t=%3d end\n", index, tag)
524 }
525 }
526
527 if depth != 0 {
528 fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
529 }
530 fmt.Printf("\n")
531
532 o.buf = obuf
533 o.index = index
534}