| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- // Go support for Protocol Buffers - Google's data interchange format
- //
- // Copyright 2010 Google Inc. All rights reserved.
- // http://code.google.com/p/goprotobuf/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- /*
- The proto package converts data structures to and from the
- wire format of protocol buffers. It works in concert with the
- Go source code generated for .proto files by the protocol compiler.
- A summary of the properties of the protocol buffer interface
- for a protocol buffer variable v:
- - Names are turned from camel_case to CamelCase for export.
- - There are no methods on v to set and get fields; just treat
- them as structure fields.
- - The zero value for a struct is its correct initialization state.
- All desired fields must be set before marshaling.
- - A Reset() method will restore a protobuf struct to its zero state.
- - Each type T has a method NewT() to create a new instance. It
- is equivalent to new(T).
- - Non-repeated fields are pointers to the values; nil means unset.
- That is, optional or required field int32 f becomes F *int32.
- - Repeated fields are slices.
- - Helper functions are available to simplify the getting and setting of fields:
- foo.String = proto.String("hello") // set field
- s := proto.GetString(foo.String) // get field
- - Constants are defined to hold the default values of all fields that
- have them. They have the form Default_StructName_FieldName.
- - Enums are given type names and maps between names to values,
- plus a helper function to create values. Enum values are prefixed
- with the enum's type name.
- - Nested groups and enums have type names prefixed with the name of
- the surrounding message type.
- - Extensions are given descriptor names that start with E_,
- followed by an underscore-delimited list of the nested messages
- that contain it (if any) followed by the CamelCased name of the
- extension field itself. HasExtension, ClearExtension, GetExtension
- and SetExtension are functions for manipulating extensions.
- - Marshal and Unmarshal are functions to encode and decode the wire format.
- The simplest way to describe this is to see an example.
- Given file test.proto, containing
- package example;
- enum FOO { X = 17; };
- message Test {
- required string label = 1;
- optional int32 type = 2 [default=77];
- repeated int64 reps = 3;
- optional group OptionalGroup = 4 {
- required string RequiredField = 5;
- };
- }
- The resulting file, test.pb.go, is:
- package example
- import "goprotobuf.googlecode.com/hg/proto"
- type FOO int32
- const (
- FOO_X = 17
- )
- var FOO_name = map[int32] string {
- 17: "X",
- }
- var FOO_value = map[string] int32 {
- "X": 17,
- }
- func NewFOO(x int32) *FOO {
- e := FOO(x)
- return &e
- }
- type Test struct {
- Label *string "PB(bytes,1,req,name=label)"
- Type *int32 "PB(varint,2,opt,name=type,def=77)"
- Reps []int64 "PB(varint,3,rep,name=reps)"
- Optionalgroup *Test_OptionalGroup "PB(group,4,opt,name=optionalgroup)"
- XXX_unrecognized []byte
- }
- func (this *Test) Reset() {
- *this = Test{}
- }
- func NewTest() *Test {
- return new(Test)
- }
- const Default_Test_Type int32 = 77
- type Test_OptionalGroup struct {
- RequiredField *string "PB(bytes,5,req)"
- XXX_unrecognized []byte
- }
- func (this *Test_OptionalGroup) Reset() {
- *this = Test_OptionalGroup{}
- }
- func NewTest_OptionalGroup() *Test_OptionalGroup {
- return new(Test_OptionalGroup)
- }
- func init() {
- proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
- }
- To create and play with a Test object:
- package main
- import (
- "log"
- "goprotobuf.googlecode.com/hg/proto"
- "./example.pb"
- )
- func main() {
- test := &example.Test {
- Label: proto.String("hello"),
- Type: proto.Int32(17),
- Optionalgroup: &example.Test_OptionalGroup {
- RequiredField: proto.String("good bye"),
- },
- }
- data, err := proto.Marshal(test)
- if err != nil {
- log.Exit("marshaling error:", err)
- }
- newTest := example.NewTest()
- err = proto.Unmarshal(data, newTest)
- if err != nil {
- log.Exit("unmarshaling error:", err)
- }
- // Now test and newTest contain the same data.
- if proto.GetString(test.Label) != proto.GetString(newTest.Label) {
- log.Exit("data mismatch %q %q", proto.GetString(test.Label), proto.GetString(newTest.Label))
- }
- // etc.
- }
- */
- package proto
- import (
- "fmt"
- "strconv"
- )
- // Stats records allocation details about the protocol buffer encoders
- // and decoders. Useful for tuning the library itself.
- type Stats struct {
- Emalloc uint64 // mallocs in encode
- Dmalloc uint64 // mallocs in decode
- Encode uint64 // number of encodes
- Decode uint64 // number of decodes
- Chit uint64 // number of cache hits
- Cmiss uint64 // number of cache misses
- }
- var stats Stats
- // GetStats returns a copy of the global Stats structure.
- func GetStats() Stats { return stats }
- // A Buffer is a buffer manager for marshaling and unmarshaling
- // protocol buffers. It may be reused between invocations to
- // reduce memory usage. It is not necessary to use a Buffer;
- // the global functions Marshal and Unmarshal create a
- // temporary Buffer and are fine for most applications.
- type Buffer struct {
- buf []byte // encode/decode byte stream
- index int // write point
- freelist [10][]byte // list of available buffers
- nfreelist int // number of free buffers
- ptr uintptr // scratch area for pointers
- }
- // NewBuffer allocates a new Buffer and initializes its internal data to
- // the contents of the argument slice.
- func NewBuffer(e []byte) *Buffer {
- p := new(Buffer)
- if e == nil {
- e = p.bufalloc()
- }
- p.buf = e
- p.index = 0
- return p
- }
- // Reset resets the Buffer, ready for marshaling a new protocol buffer.
- func (p *Buffer) Reset() {
- if p.buf == nil {
- p.buf = p.bufalloc()
- }
- p.buf = p.buf[0:0] // for reading/writing
- p.index = 0 // for reading
- }
- // SetBuf replaces the internal buffer with the slice,
- // ready for unmarshaling the contents of the slice.
- func (p *Buffer) SetBuf(s []byte) {
- p.buf = s
- p.index = 0
- }
- // Bytes returns the contents of the Buffer.
- func (p *Buffer) Bytes() []byte { return p.buf }
- // Allocate a buffer for the Buffer.
- func (p *Buffer) bufalloc() []byte {
- if p.nfreelist > 0 {
- // reuse an old one
- p.nfreelist--
- s := p.freelist[p.nfreelist]
- return s[0:0]
- }
- // make a new one
- s := make([]byte, 0, 16)
- return s
- }
- // Free (and remember in freelist) a byte buffer for the Buffer.
- func (p *Buffer) buffree(s []byte) {
- if p.nfreelist < len(p.freelist) {
- // Take next slot.
- p.freelist[p.nfreelist] = s
- p.nfreelist++
- return
- }
- // Find the smallest.
- besti := -1
- bestl := len(s)
- for i, b := range p.freelist {
- if len(b) < bestl {
- besti = i
- bestl = len(b)
- }
- }
- // Overwrite the smallest.
- if besti >= 0 {
- p.freelist[besti] = s
- }
- }
- /*
- * Helper routines for simplifying the creation of optional fields of basic type.
- */
- // Bool is a helper routine that allocates a new bool value
- // to store v and returns a pointer to it.
- func Bool(v bool) *bool {
- p := new(bool)
- *p = v
- return p
- }
- // Int32 is a helper routine that allocates a new int32 value
- // to store v and returns a pointer to it.
- func Int32(v int32) *int32 {
- p := new(int32)
- *p = v
- return p
- }
- // Int is a helper routine that allocates a new int32 value
- // to store v and returns a pointer to it, but unlike Int32
- // its argument value is an int.
- func Int(v int) *int32 {
- p := new(int32)
- *p = int32(v)
- return p
- }
- // Int64 is a helper routine that allocates a new int64 value
- // to store v and returns a pointer to it.
- func Int64(v int64) *int64 {
- p := new(int64)
- *p = v
- return p
- }
- // Float32 is a helper routine that allocates a new float32 value
- // to store v and returns a pointer to it.
- func Float32(v float32) *float32 {
- p := new(float32)
- *p = v
- return p
- }
- // Float64 is a helper routine that allocates a new float64 value
- // to store v and returns a pointer to it.
- func Float64(v float64) *float64 {
- p := new(float64)
- *p = v
- return p
- }
- // Uint32 is a helper routine that allocates a new uint32 value
- // to store v and returns a pointer to it.
- func Uint32(v uint32) *uint32 {
- p := new(uint32)
- *p = v
- return p
- }
- // Uint64 is a helper routine that allocates a new uint64 value
- // to store v and returns a pointer to it.
- func Uint64(v uint64) *uint64 {
- p := new(uint64)
- *p = v
- return p
- }
- // String is a helper routine that allocates a new string value
- // to store v and returns a pointer to it.
- func String(v string) *string {
- p := new(string)
- *p = v
- return p
- }
- /*
- * Helper routines for simplifying the fetching of optional fields of basic type.
- * If the field is missing, they return the zero for the type.
- */
- // GetBool is a helper routine that returns an optional bool value.
- func GetBool(p *bool) bool {
- if p == nil {
- return false
- }
- return *p
- }
- // GetInt32 is a helper routine that returns an optional int32 value.
- func GetInt32(p *int32) int32 {
- if p == nil {
- return 0
- }
- return *p
- }
- // GetInt64 is a helper routine that returns an optional int64 value.
- func GetInt64(p *int64) int64 {
- if p == nil {
- return 0
- }
- return *p
- }
- // GetFloat32 is a helper routine that returns an optional float32 value.
- func GetFloat32(p *float32) float32 {
- if p == nil {
- return 0
- }
- return *p
- }
- // GetFloat64 is a helper routine that returns an optional float64 value.
- func GetFloat64(p *float64) float64 {
- if p == nil {
- return 0
- }
- return *p
- }
- // GetUint32 is a helper routine that returns an optional uint32 value.
- func GetUint32(p *uint32) uint32 {
- if p == nil {
- return 0
- }
- return *p
- }
- // GetUint64 is a helper routine that returns an optional uint64 value.
- func GetUint64(p *uint64) uint64 {
- if p == nil {
- return 0
- }
- return *p
- }
- // GetString is a helper routine that returns an optional string value.
- func GetString(p *string) string {
- if p == nil {
- return ""
- }
- return *p
- }
- // EnumName is a helper function to simplify printing protocol buffer enums
- // by name. Given an enum map and a value, it returns a useful string.
- func EnumName(m map[int32]string, v int32) string {
- s, ok := m[v]
- if ok {
- return s
- }
- return "unknown_enum_" + strconv.Itoa(int(v))
- }
- // DebugPrint dumps the encoded data in b in a debugging format with a header
- // including the string s. Used in testing but made available for general debugging.
- func (o *Buffer) DebugPrint(s string, b []byte) {
- var u uint64
- obuf := o.buf
- index := o.index
- o.buf = b
- o.index = 0
- depth := 0
- fmt.Printf("\n--- %s ---\n", s)
- out:
- for {
- for i := 0; i < depth; i++ {
- fmt.Print(" ")
- }
- index := o.index
- if index == len(o.buf) {
- break
- }
- op, err := o.DecodeVarint()
- if err != nil {
- fmt.Printf("%3d: fetching op err %v\n", index, err)
- break out
- }
- tag := op >> 3
- wire := op & 7
- switch wire {
- default:
- fmt.Printf("%3d: t=%3d unknown wire=%d\n",
- index, tag, wire)
- break out
- case WireBytes:
- var r []byte
- r, err = o.DecodeRawBytes(false)
- if err != nil {
- break out
- }
- fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
- if len(r) <= 6 {
- for i := 0; i < len(r); i++ {
- fmt.Printf(" %.2x", r[i])
- }
- } else {
- for i := 0; i < 3; i++ {
- fmt.Printf(" %.2x", r[i])
- }
- fmt.Printf(" ..")
- for i := len(r) - 3; i < len(r); i++ {
- fmt.Printf(" %.2x", r[i])
- }
- }
- fmt.Printf("\n")
- case WireFixed32:
- u, err = o.DecodeFixed32()
- if err != nil {
- fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
- break out
- }
- fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
- case WireFixed64:
- u, err = o.DecodeFixed64()
- if err != nil {
- fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
- break out
- }
- fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
- break
- case WireVarint:
- u, err = o.DecodeVarint()
- if err != nil {
- fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
- break out
- }
- fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
- case WireStartGroup:
- if err != nil {
- fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
- break out
- }
- fmt.Printf("%3d: t=%3d start\n", index, tag)
- depth++
- case WireEndGroup:
- depth--
- if err != nil {
- fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
- break out
- }
- fmt.Printf("%3d: t=%3d end\n", index, tag)
- }
- }
- if depth != 0 {
- fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
- }
- fmt.Printf("\n")
- o.buf = obuf
- o.index = index
- }
|