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