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