--- /dev/null
+repo: ecf73c3ec4286914856b51b4e9cb5c320f528952
+node: bc76a153ffde5de8535b7c2791102ddd0b93f187
+branch: default
+tag: go.r60
+tag: go.weekly.2011-09-21
--- /dev/null
+syntax:glob
+.DS_Store
+.git
+.gitignore
+*.[568ao]
+*.pb.go
+*.ao
+*.so
+*.pyc
+._*
+.nfs.*
+[568a].out
+*~
+*.orig
+core
+_obj
+_test
+_testmain.go
+compiler/protoc-gen-go
+compiler/testdata/extension_test
--- /dev/null
+96dad172ec5b1aa6946f13f9cbf9cfe0fec40f05 weekly.2011-04-04
+37b09d1346b72c73a76672aa9a830bff9e6be014 weekly.2011-04-13
+44f4e3da3f952834d65c7a5fcc1f1a2cc90e1542 weekly.2011-04-27
+097a1c90eb4bf73ecacbcef71c09298f4a596dcd weekly.2011-06-16
+83a0b16ac3234242663b12be19adc030c1cd666a weekly.2011-06-23
+89e4e9b619197f71e60c3ed309474cfd94475061 weekly.2011-07-07
+32017900448961add50b154f63d1f80907285984 weekly.2011-08-10
+c9278633d1eb1c80bc5946eb6724e2d22cd28265 weekly.2011-08-17
+f3ef978cda6fabc10f6039aeed960340547c6d5a release.r56
+fa1080cfc0a4d0fa24844bc50124aed892365059 release.r57.1
+fa1080cfc0a4d0fa24844bc50124aed892365059 release.r57.2
+cfe37a63cede6cd072434965e6ea426b90bcb223 release.r58
+cfe37a63cede6cd072434965e6ea426b90bcb223 release.r58.1
+da17c98c73d8801baa1d2e493c9ac0844470ef0a release.r59
+5a487ccac6f7fd6cba5deee5d5d0908c7f1d6a53 go.r60
+5a487ccac6f7fd6cba5deee5d5d0908c7f1d6a53 go.weekly.2011-09-07
--- /dev/null
+# This is a list of contributors to the Go protobuf repository.
+
+# Names should be added to this file like so:
+# Name <email address>
+
+# Please keep the list sorted.
+
+
+Dave Cheney <dave@cheney.net>
+David Symonds <dsymonds@golang.org>
+Ken Thompson <ken@golang.org>
+Mikkel Krautz <mikkel@krautz.dk> <krautz@gmail.com>
+Nigel Tao <nigeltao@golang.org>
+Rob Pike <r@golang.org>
--- /dev/null
+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.
+
--- /dev/null
+# 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.
+
+# Includable Makefile to add a rule for generating .pb.go files from .proto files
+# (Google protocol buffer descriptions).
+# Typical use if myproto.proto is a file in package mypackage in this directory:
+#
+# include $(GOROOT)/src/Make.inc
+# TARG=mypackage
+# GOFILES=\
+# myproto.pb.go
+#
+# include $(GOROOT)/src/Make.pkg
+# include $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/Make.protobuf
+
+%.pb.go: %.proto
+ protoc --go_out=. $<
+
--- /dev/null
+# 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.
+
+
+include $(GOROOT)/src/Make.inc
+
+all: install
+
+install:
+ cd proto && gomake install
+ cd compiler/descriptor && gomake install
+ cd compiler/plugin && gomake install
+ cd compiler && gomake install
+
+test:
+ cd proto && gomake test
+ cd compiler && gomake test
+
+clean:
+ cd proto && gomake clean
+ cd proto/testdata && gomake clean
+ cd compiler && gomake clean
+ cd compiler/descriptor && gomake clean
+ cd compiler/plugin && gomake clean
+ cd compiler/testdata && gomake clean
+ cd compiler/descriptor && gomake clean
+ cd compiler/plugin && gomake clean
+
+nuke:
+ cd proto && gomake nuke
+ cd proto/testdata && gomake nuke
+ cd compiler/descriptor && gomake nuke
+ cd compiler/plugin && gomake nuke
+ cd compiler && gomake nuke
+ cd compiler/testdata && gomake nuke
+ cd compiler/descriptor && gomake nuke
+ cd compiler/plugin && gomake nuke
--- /dev/null
+Go support for Protocol Buffers - Google's data interchange format
+Copyright 2010 Google Inc.
+http://code.google.com/p/goprotobuf/
+
+This software implements Go bindings for protocol buffers. For
+information about protocol buffers themselves, see
+ http://code.google.com/apis/protocolbuffers/
+To use this software, you must first install the standard C++
+implementation of protocol buffers from
+ http://code.google.com/p/protobuf/
+And of course you must also install the Go compiler and tools from
+ http://code.google.com/p/go/
+See
+ http://golang.org/doc/install.html
+for details or, if you are using gccgo, follow the instructions at
+ http://golang.org/doc/gccgo_install.html
+
+This software has two parts: a 'protocol compiler plugin' that
+generates Go source files that, once compiled, can access and manage
+protocol buffers; and a library that implements run-time support for
+encoding (marshaling), decoding (unmarshaling), and accessing protocol
+buffers.
+
+There is no support for RPC in Go using protocol buffers. It may come
+once a standard RPC protocol develops for protobufs.
+
+There are no insertion points in the plugin.
+
+To install this code:
+
+The simplest way is to run goinstall.
+
+ # Grab the code from the repository and install the proto package.
+ goinstall goprotobuf.googlecode.com/hg/proto
+
+ # Compile and install the compiler plugin
+ cd $GOROOT/src/pkg/goprotobuf.googlecode.com/hg/compiler
+ make install
+
+The compiler plugin, protoc-gen-go, will be installed in $GOBIN,
+defaulting to $HOME/bin. It must be in your $PATH for the protocol
+compiler, protoc, to find it.
+
+Once the software is installed, there are two steps to using it.
+First you must compile the protocol buffer definitions and then import
+them, with the support library, into your program.
+
+To compile the protocol buffer definition, write a Makefile in the
+style shown in the comment in the file Make.protobuf. If your Makefile
+includes Make.protobuf, the rest should follow automatically. The
+generated code can be compiled separately or as part of a normal Go
+package.
+
+The generated files will be suffixed .pb.go. See the Test code below
+for an example using such a file.
+
+This repository uses the same code review mechanism as Go, so
+if you wish to submit changes add the equivalent of these two lines
+to $GOROOT/src/pkg/goprotobuf.googlecode.com/hg/.hg/hgrc
+
+ [extensions]
+ codereview = $GOROOT/lib/codereview/codereview.py
+
+*where $GOROOT is the expanded text, such as /usr/foo/go*.
+
+The package comment for the proto library contains text describing
+the interface provided in Go for protocol buffers. Here is an edited
+version.
+
+==========
+
+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.
+ - 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.
+ - Marshal and Unmarshal are functions to encode and decode the wire format.
+
+Consider 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;
+ };
+ }
+
+To build a package from test.proto and some other Go files, write a
+Makefile like this:
+
+ include $(GOROOT)/src/Make.$(GOARCH)
+
+ TARG=path/to/example
+ GOFILES=\
+ test.pb.go\
+ other.go
+
+ include $(GOROOT)/src/Make.pkg
+ include $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/Make.protobuf
+
+
+To create and play with a Test object from the example package,
+
+ package main
+
+ import (
+ "log"
+
+ "goprotobuf.googlecode.com/hg/proto"
+ "path/to/example"
+ )
+
+ 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.Fatal("marshaling error: ", err)
+ }
+ newTest := &example.Test{}
+ err = proto.Unmarshal(data, newTest)
+ if err != nil {
+ log.Fatal("unmarshaling error: ", err)
+ }
+ // Now test and newTest contain the same data.
+ if proto.GetString(test.Label) != proto.GetString(newTest.Label) {
+ log.Fatalf("data mismatch %q != %q", proto.GetString(test.Label), proto.GetString(newTest.Label))
+ }
+ // etc.
+ }
--- /dev/null
+# 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.
+
+
+include $(GOROOT)/src/Make.inc
+
+TARG=protoc-gen-go
+GOFILES=\
+ main.go\
+
+DEPS=generator descriptor plugin
+
+include $(GOROOT)/src/Make.cmd
+
+test:
+ cd testdata && make test
--- /dev/null
+# 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.
+
+include $(GOROOT)/src/Make.inc
+
+TARG=goprotobuf.googlecode.com/hg/compiler/descriptor
+GOFILES=\
+ descriptor.pb.go\
+
+DEPS=../../proto
+
+include $(GOROOT)/src/Make.pkg
+
+# Not stored here, but descriptor.proto is in http://code.google.com/p/protobuf
+# at protobuf-2.3.0/src/google/protobuf/descriptor.proto
+regenerate:
+ echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
+ cd $(HOME)/protobuf-2.3.0/src && \
+ protoc --go_out=. ./google/protobuf/descriptor.proto && \
+ cp ./google/protobuf/descriptor.pb.go $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/compiler/descriptor/descriptor.pb.go
+
+restore:
+ cp descriptor.pb.golden descriptor.pb.go
+
+preserve:
+ cp descriptor.pb.go descriptor.pb.golden
--- /dev/null
+// Code generated by protoc-gen-go from "google/protobuf/descriptor.proto"
+// DO NOT EDIT!
+
+package google_protobuf
+
+import proto "goprotobuf.googlecode.com/hg/proto"
+import "math"
+import "os"
+
+// Reference proto, math & os imports to suppress error if they are not otherwise used.
+var _ = proto.GetString
+var _ = math.Inf
+var _ os.Error
+
+
+type FieldDescriptorProto_Type int32
+
+const (
+ FieldDescriptorProto_TYPE_DOUBLE = 1
+ FieldDescriptorProto_TYPE_FLOAT = 2
+ FieldDescriptorProto_TYPE_INT64 = 3
+ FieldDescriptorProto_TYPE_UINT64 = 4
+ FieldDescriptorProto_TYPE_INT32 = 5
+ FieldDescriptorProto_TYPE_FIXED64 = 6
+ FieldDescriptorProto_TYPE_FIXED32 = 7
+ FieldDescriptorProto_TYPE_BOOL = 8
+ FieldDescriptorProto_TYPE_STRING = 9
+ FieldDescriptorProto_TYPE_GROUP = 10
+ FieldDescriptorProto_TYPE_MESSAGE = 11
+ FieldDescriptorProto_TYPE_BYTES = 12
+ FieldDescriptorProto_TYPE_UINT32 = 13
+ FieldDescriptorProto_TYPE_ENUM = 14
+ FieldDescriptorProto_TYPE_SFIXED32 = 15
+ FieldDescriptorProto_TYPE_SFIXED64 = 16
+ FieldDescriptorProto_TYPE_SINT32 = 17
+ FieldDescriptorProto_TYPE_SINT64 = 18
+)
+
+var FieldDescriptorProto_Type_name = map[int32]string{
+ 1: "TYPE_DOUBLE",
+ 2: "TYPE_FLOAT",
+ 3: "TYPE_INT64",
+ 4: "TYPE_UINT64",
+ 5: "TYPE_INT32",
+ 6: "TYPE_FIXED64",
+ 7: "TYPE_FIXED32",
+ 8: "TYPE_BOOL",
+ 9: "TYPE_STRING",
+ 10: "TYPE_GROUP",
+ 11: "TYPE_MESSAGE",
+ 12: "TYPE_BYTES",
+ 13: "TYPE_UINT32",
+ 14: "TYPE_ENUM",
+ 15: "TYPE_SFIXED32",
+ 16: "TYPE_SFIXED64",
+ 17: "TYPE_SINT32",
+ 18: "TYPE_SINT64",
+}
+var FieldDescriptorProto_Type_value = map[string]int32{
+ "TYPE_DOUBLE": 1,
+ "TYPE_FLOAT": 2,
+ "TYPE_INT64": 3,
+ "TYPE_UINT64": 4,
+ "TYPE_INT32": 5,
+ "TYPE_FIXED64": 6,
+ "TYPE_FIXED32": 7,
+ "TYPE_BOOL": 8,
+ "TYPE_STRING": 9,
+ "TYPE_GROUP": 10,
+ "TYPE_MESSAGE": 11,
+ "TYPE_BYTES": 12,
+ "TYPE_UINT32": 13,
+ "TYPE_ENUM": 14,
+ "TYPE_SFIXED32": 15,
+ "TYPE_SFIXED64": 16,
+ "TYPE_SINT32": 17,
+ "TYPE_SINT64": 18,
+}
+
+func NewFieldDescriptorProto_Type(x int32) *FieldDescriptorProto_Type {
+ e := FieldDescriptorProto_Type(x)
+ return &e
+}
+func (x FieldDescriptorProto_Type) String() string {
+ return proto.EnumName(FieldDescriptorProto_Type_name, int32(x))
+}
+
+type FieldDescriptorProto_Label int32
+
+const (
+ FieldDescriptorProto_LABEL_OPTIONAL = 1
+ FieldDescriptorProto_LABEL_REQUIRED = 2
+ FieldDescriptorProto_LABEL_REPEATED = 3
+)
+
+var FieldDescriptorProto_Label_name = map[int32]string{
+ 1: "LABEL_OPTIONAL",
+ 2: "LABEL_REQUIRED",
+ 3: "LABEL_REPEATED",
+}
+var FieldDescriptorProto_Label_value = map[string]int32{
+ "LABEL_OPTIONAL": 1,
+ "LABEL_REQUIRED": 2,
+ "LABEL_REPEATED": 3,
+}
+
+func NewFieldDescriptorProto_Label(x int32) *FieldDescriptorProto_Label {
+ e := FieldDescriptorProto_Label(x)
+ return &e
+}
+func (x FieldDescriptorProto_Label) String() string {
+ return proto.EnumName(FieldDescriptorProto_Label_name, int32(x))
+}
+
+type FileOptions_OptimizeMode int32
+
+const (
+ FileOptions_SPEED = 1
+ FileOptions_CODE_SIZE = 2
+ FileOptions_LITE_RUNTIME = 3
+)
+
+var FileOptions_OptimizeMode_name = map[int32]string{
+ 1: "SPEED",
+ 2: "CODE_SIZE",
+ 3: "LITE_RUNTIME",
+}
+var FileOptions_OptimizeMode_value = map[string]int32{
+ "SPEED": 1,
+ "CODE_SIZE": 2,
+ "LITE_RUNTIME": 3,
+}
+
+func NewFileOptions_OptimizeMode(x int32) *FileOptions_OptimizeMode {
+ e := FileOptions_OptimizeMode(x)
+ return &e
+}
+func (x FileOptions_OptimizeMode) String() string {
+ return proto.EnumName(FileOptions_OptimizeMode_name, int32(x))
+}
+
+type FieldOptions_CType int32
+
+const (
+ FieldOptions_STRING = 0
+ FieldOptions_CORD = 1
+ FieldOptions_STRING_PIECE = 2
+)
+
+var FieldOptions_CType_name = map[int32]string{
+ 0: "STRING",
+ 1: "CORD",
+ 2: "STRING_PIECE",
+}
+var FieldOptions_CType_value = map[string]int32{
+ "STRING": 0,
+ "CORD": 1,
+ "STRING_PIECE": 2,
+}
+
+func NewFieldOptions_CType(x int32) *FieldOptions_CType {
+ e := FieldOptions_CType(x)
+ return &e
+}
+func (x FieldOptions_CType) String() string {
+ return proto.EnumName(FieldOptions_CType_name, int32(x))
+}
+
+type FileDescriptorSet struct {
+ File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file"`
+ XXX_unrecognized []byte
+}
+
+func (this *FileDescriptorSet) Reset() { *this = FileDescriptorSet{} }
+func (this *FileDescriptorSet) String() string { return proto.CompactTextString(this) }
+
+type FileDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Package *string `protobuf:"bytes,2,opt,name=package"`
+ Dependency []string `protobuf:"bytes,3,rep,name=dependency"`
+ PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency"`
+ MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type"`
+ Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension"`
+ Options *FileOptions `protobuf:"bytes,8,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *FileDescriptorProto) Reset() { *this = FileDescriptorProto{} }
+func (this *FileDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type DescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension"`
+ NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type"`
+ ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range"`
+ Options *MessageOptions `protobuf:"bytes,7,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *DescriptorProto) Reset() { *this = DescriptorProto{} }
+func (this *DescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type DescriptorProto_ExtensionRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start"`
+ End *int32 `protobuf:"varint,2,opt,name=end"`
+ XXX_unrecognized []byte
+}
+
+func (this *DescriptorProto_ExtensionRange) Reset() { *this = DescriptorProto_ExtensionRange{} }
+func (this *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(this) }
+
+type FieldDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Number *int32 `protobuf:"varint,3,opt,name=number"`
+ Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google_protobuf.FieldDescriptorProto_Label"`
+ Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google_protobuf.FieldDescriptorProto_Type"`
+ TypeName *string `protobuf:"bytes,6,opt,name=type_name"`
+ Extendee *string `protobuf:"bytes,2,opt,name=extendee"`
+ DefaultValue *string `protobuf:"bytes,7,opt,name=default_value"`
+ Options *FieldOptions `protobuf:"bytes,8,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *FieldDescriptorProto) Reset() { *this = FieldDescriptorProto{} }
+func (this *FieldDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type EnumDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value"`
+ Options *EnumOptions `protobuf:"bytes,3,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *EnumDescriptorProto) Reset() { *this = EnumDescriptorProto{} }
+func (this *EnumDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type EnumValueDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Number *int32 `protobuf:"varint,2,opt,name=number"`
+ Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *EnumValueDescriptorProto) Reset() { *this = EnumValueDescriptorProto{} }
+func (this *EnumValueDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type ServiceDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method"`
+ Options *ServiceOptions `protobuf:"bytes,3,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *ServiceDescriptorProto) Reset() { *this = ServiceDescriptorProto{} }
+func (this *ServiceDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type MethodDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ InputType *string `protobuf:"bytes,2,opt,name=input_type"`
+ OutputType *string `protobuf:"bytes,3,opt,name=output_type"`
+ Options *MethodOptions `protobuf:"bytes,4,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *MethodDescriptorProto) Reset() { *this = MethodDescriptorProto{} }
+func (this *MethodDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type FileOptions struct {
+ JavaPackage *string `protobuf:"bytes,1,opt,name=java_package"`
+ JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname"`
+ JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,def=0"`
+ OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,enum=google_protobuf.FileOptions_OptimizeMode,def=1"`
+ CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,def=1"`
+ JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,def=1"`
+ PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,def=1"`
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *FileOptions) Reset() { *this = FileOptions{} }
+func (this *FileOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_FileOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FileOptions
+}
+func (this *FileOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+const Default_FileOptions_JavaMultipleFiles bool = false
+const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED
+const Default_FileOptions_CcGenericServices bool = true
+const Default_FileOptions_JavaGenericServices bool = true
+const Default_FileOptions_PyGenericServices bool = true
+
+type MessageOptions struct {
+ MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,def=0"`
+ NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,def=0"`
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *MessageOptions) Reset() { *this = MessageOptions{} }
+func (this *MessageOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_MessageOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MessageOptions
+}
+func (this *MessageOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+const Default_MessageOptions_MessageSetWireFormat bool = false
+const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
+
+type FieldOptions struct {
+ Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google_protobuf.FieldOptions_CType,def=0"`
+ Packed *bool `protobuf:"varint,2,opt,name=packed"`
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0"`
+ ExperimentalMapKey *string `protobuf:"bytes,9,opt,name=experimental_map_key"`
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *FieldOptions) Reset() { *this = FieldOptions{} }
+func (this *FieldOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_FieldOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FieldOptions
+}
+func (this *FieldOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
+const Default_FieldOptions_Deprecated bool = false
+
+type EnumOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *EnumOptions) Reset() { *this = EnumOptions{} }
+func (this *EnumOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_EnumOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumOptions
+}
+func (this *EnumOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type EnumValueOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *EnumValueOptions) Reset() { *this = EnumValueOptions{} }
+func (this *EnumValueOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_EnumValueOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumValueOptions
+}
+func (this *EnumValueOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type ServiceOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *ServiceOptions) Reset() { *this = ServiceOptions{} }
+func (this *ServiceOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_ServiceOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ServiceOptions
+}
+func (this *ServiceOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type MethodOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *MethodOptions) Reset() { *this = MethodOptions{} }
+func (this *MethodOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_MethodOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MethodOptions
+}
+func (this *MethodOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type UninterpretedOption struct {
+ Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name"`
+ IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value"`
+ PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value"`
+ NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value"`
+ DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value"`
+ StringValue []byte `protobuf:"bytes,7,opt,name=string_value"`
+ XXX_unrecognized []byte
+}
+
+func (this *UninterpretedOption) Reset() { *this = UninterpretedOption{} }
+func (this *UninterpretedOption) String() string { return proto.CompactTextString(this) }
+
+type UninterpretedOption_NamePart struct {
+ NamePart *string `protobuf:"bytes,1,req,name=name_part"`
+ IsExtension *bool `protobuf:"varint,2,req,name=is_extension"`
+ XXX_unrecognized []byte
+}
+
+func (this *UninterpretedOption_NamePart) Reset() { *this = UninterpretedOption_NamePart{} }
+func (this *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(this) }
+
+func init() {
+ proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value)
+ proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value)
+ proto.RegisterEnum("google_protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
+ proto.RegisterEnum("google_protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
+}
--- /dev/null
+// Code generated by protoc-gen-go from "google/protobuf/descriptor.proto"
+// DO NOT EDIT!
+
+package google_protobuf
+
+import proto "goprotobuf.googlecode.com/hg/proto"
+import "math"
+import "os"
+
+// Reference proto, math & os imports to suppress error if they are not otherwise used.
+var _ = proto.GetString
+var _ = math.Inf
+var _ os.Error
+
+
+type FieldDescriptorProto_Type int32
+
+const (
+ FieldDescriptorProto_TYPE_DOUBLE = 1
+ FieldDescriptorProto_TYPE_FLOAT = 2
+ FieldDescriptorProto_TYPE_INT64 = 3
+ FieldDescriptorProto_TYPE_UINT64 = 4
+ FieldDescriptorProto_TYPE_INT32 = 5
+ FieldDescriptorProto_TYPE_FIXED64 = 6
+ FieldDescriptorProto_TYPE_FIXED32 = 7
+ FieldDescriptorProto_TYPE_BOOL = 8
+ FieldDescriptorProto_TYPE_STRING = 9
+ FieldDescriptorProto_TYPE_GROUP = 10
+ FieldDescriptorProto_TYPE_MESSAGE = 11
+ FieldDescriptorProto_TYPE_BYTES = 12
+ FieldDescriptorProto_TYPE_UINT32 = 13
+ FieldDescriptorProto_TYPE_ENUM = 14
+ FieldDescriptorProto_TYPE_SFIXED32 = 15
+ FieldDescriptorProto_TYPE_SFIXED64 = 16
+ FieldDescriptorProto_TYPE_SINT32 = 17
+ FieldDescriptorProto_TYPE_SINT64 = 18
+)
+
+var FieldDescriptorProto_Type_name = map[int32]string{
+ 1: "TYPE_DOUBLE",
+ 2: "TYPE_FLOAT",
+ 3: "TYPE_INT64",
+ 4: "TYPE_UINT64",
+ 5: "TYPE_INT32",
+ 6: "TYPE_FIXED64",
+ 7: "TYPE_FIXED32",
+ 8: "TYPE_BOOL",
+ 9: "TYPE_STRING",
+ 10: "TYPE_GROUP",
+ 11: "TYPE_MESSAGE",
+ 12: "TYPE_BYTES",
+ 13: "TYPE_UINT32",
+ 14: "TYPE_ENUM",
+ 15: "TYPE_SFIXED32",
+ 16: "TYPE_SFIXED64",
+ 17: "TYPE_SINT32",
+ 18: "TYPE_SINT64",
+}
+var FieldDescriptorProto_Type_value = map[string]int32{
+ "TYPE_DOUBLE": 1,
+ "TYPE_FLOAT": 2,
+ "TYPE_INT64": 3,
+ "TYPE_UINT64": 4,
+ "TYPE_INT32": 5,
+ "TYPE_FIXED64": 6,
+ "TYPE_FIXED32": 7,
+ "TYPE_BOOL": 8,
+ "TYPE_STRING": 9,
+ "TYPE_GROUP": 10,
+ "TYPE_MESSAGE": 11,
+ "TYPE_BYTES": 12,
+ "TYPE_UINT32": 13,
+ "TYPE_ENUM": 14,
+ "TYPE_SFIXED32": 15,
+ "TYPE_SFIXED64": 16,
+ "TYPE_SINT32": 17,
+ "TYPE_SINT64": 18,
+}
+
+func NewFieldDescriptorProto_Type(x int32) *FieldDescriptorProto_Type {
+ e := FieldDescriptorProto_Type(x)
+ return &e
+}
+func (x FieldDescriptorProto_Type) String() string {
+ return proto.EnumName(FieldDescriptorProto_Type_name, int32(x))
+}
+
+type FieldDescriptorProto_Label int32
+
+const (
+ FieldDescriptorProto_LABEL_OPTIONAL = 1
+ FieldDescriptorProto_LABEL_REQUIRED = 2
+ FieldDescriptorProto_LABEL_REPEATED = 3
+)
+
+var FieldDescriptorProto_Label_name = map[int32]string{
+ 1: "LABEL_OPTIONAL",
+ 2: "LABEL_REQUIRED",
+ 3: "LABEL_REPEATED",
+}
+var FieldDescriptorProto_Label_value = map[string]int32{
+ "LABEL_OPTIONAL": 1,
+ "LABEL_REQUIRED": 2,
+ "LABEL_REPEATED": 3,
+}
+
+func NewFieldDescriptorProto_Label(x int32) *FieldDescriptorProto_Label {
+ e := FieldDescriptorProto_Label(x)
+ return &e
+}
+func (x FieldDescriptorProto_Label) String() string {
+ return proto.EnumName(FieldDescriptorProto_Label_name, int32(x))
+}
+
+type FileOptions_OptimizeMode int32
+
+const (
+ FileOptions_SPEED = 1
+ FileOptions_CODE_SIZE = 2
+ FileOptions_LITE_RUNTIME = 3
+)
+
+var FileOptions_OptimizeMode_name = map[int32]string{
+ 1: "SPEED",
+ 2: "CODE_SIZE",
+ 3: "LITE_RUNTIME",
+}
+var FileOptions_OptimizeMode_value = map[string]int32{
+ "SPEED": 1,
+ "CODE_SIZE": 2,
+ "LITE_RUNTIME": 3,
+}
+
+func NewFileOptions_OptimizeMode(x int32) *FileOptions_OptimizeMode {
+ e := FileOptions_OptimizeMode(x)
+ return &e
+}
+func (x FileOptions_OptimizeMode) String() string {
+ return proto.EnumName(FileOptions_OptimizeMode_name, int32(x))
+}
+
+type FieldOptions_CType int32
+
+const (
+ FieldOptions_STRING = 0
+ FieldOptions_CORD = 1
+ FieldOptions_STRING_PIECE = 2
+)
+
+var FieldOptions_CType_name = map[int32]string{
+ 0: "STRING",
+ 1: "CORD",
+ 2: "STRING_PIECE",
+}
+var FieldOptions_CType_value = map[string]int32{
+ "STRING": 0,
+ "CORD": 1,
+ "STRING_PIECE": 2,
+}
+
+func NewFieldOptions_CType(x int32) *FieldOptions_CType {
+ e := FieldOptions_CType(x)
+ return &e
+}
+func (x FieldOptions_CType) String() string {
+ return proto.EnumName(FieldOptions_CType_name, int32(x))
+}
+
+type FileDescriptorSet struct {
+ File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file"`
+ XXX_unrecognized []byte
+}
+
+func (this *FileDescriptorSet) Reset() { *this = FileDescriptorSet{} }
+func (this *FileDescriptorSet) String() string { return proto.CompactTextString(this) }
+
+type FileDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Package *string `protobuf:"bytes,2,opt,name=package"`
+ Dependency []string `protobuf:"bytes,3,rep,name=dependency"`
+ PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency"`
+ MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type"`
+ Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension"`
+ Options *FileOptions `protobuf:"bytes,8,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *FileDescriptorProto) Reset() { *this = FileDescriptorProto{} }
+func (this *FileDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type DescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension"`
+ NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type"`
+ ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range"`
+ Options *MessageOptions `protobuf:"bytes,7,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *DescriptorProto) Reset() { *this = DescriptorProto{} }
+func (this *DescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type DescriptorProto_ExtensionRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start"`
+ End *int32 `protobuf:"varint,2,opt,name=end"`
+ XXX_unrecognized []byte
+}
+
+func (this *DescriptorProto_ExtensionRange) Reset() { *this = DescriptorProto_ExtensionRange{} }
+func (this *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(this) }
+
+type FieldDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Number *int32 `protobuf:"varint,3,opt,name=number"`
+ Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google_protobuf.FieldDescriptorProto_Label"`
+ Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google_protobuf.FieldDescriptorProto_Type"`
+ TypeName *string `protobuf:"bytes,6,opt,name=type_name"`
+ Extendee *string `protobuf:"bytes,2,opt,name=extendee"`
+ DefaultValue *string `protobuf:"bytes,7,opt,name=default_value"`
+ Options *FieldOptions `protobuf:"bytes,8,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *FieldDescriptorProto) Reset() { *this = FieldDescriptorProto{} }
+func (this *FieldDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type EnumDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value"`
+ Options *EnumOptions `protobuf:"bytes,3,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *EnumDescriptorProto) Reset() { *this = EnumDescriptorProto{} }
+func (this *EnumDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type EnumValueDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Number *int32 `protobuf:"varint,2,opt,name=number"`
+ Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *EnumValueDescriptorProto) Reset() { *this = EnumValueDescriptorProto{} }
+func (this *EnumValueDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type ServiceDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method"`
+ Options *ServiceOptions `protobuf:"bytes,3,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *ServiceDescriptorProto) Reset() { *this = ServiceDescriptorProto{} }
+func (this *ServiceDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type MethodDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ InputType *string `protobuf:"bytes,2,opt,name=input_type"`
+ OutputType *string `protobuf:"bytes,3,opt,name=output_type"`
+ Options *MethodOptions `protobuf:"bytes,4,opt,name=options"`
+ XXX_unrecognized []byte
+}
+
+func (this *MethodDescriptorProto) Reset() { *this = MethodDescriptorProto{} }
+func (this *MethodDescriptorProto) String() string { return proto.CompactTextString(this) }
+
+type FileOptions struct {
+ JavaPackage *string `protobuf:"bytes,1,opt,name=java_package"`
+ JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname"`
+ JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,def=0"`
+ OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,enum=google_protobuf.FileOptions_OptimizeMode,def=1"`
+ CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,def=1"`
+ JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,def=1"`
+ PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,def=1"`
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *FileOptions) Reset() { *this = FileOptions{} }
+func (this *FileOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_FileOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FileOptions
+}
+func (this *FileOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+const Default_FileOptions_JavaMultipleFiles bool = false
+const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED
+const Default_FileOptions_CcGenericServices bool = true
+const Default_FileOptions_JavaGenericServices bool = true
+const Default_FileOptions_PyGenericServices bool = true
+
+type MessageOptions struct {
+ MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,def=0"`
+ NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,def=0"`
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *MessageOptions) Reset() { *this = MessageOptions{} }
+func (this *MessageOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_MessageOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MessageOptions
+}
+func (this *MessageOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+const Default_MessageOptions_MessageSetWireFormat bool = false
+const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
+
+type FieldOptions struct {
+ Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google_protobuf.FieldOptions_CType,def=0"`
+ Packed *bool `protobuf:"varint,2,opt,name=packed"`
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0"`
+ ExperimentalMapKey *string `protobuf:"bytes,9,opt,name=experimental_map_key"`
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *FieldOptions) Reset() { *this = FieldOptions{} }
+func (this *FieldOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_FieldOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FieldOptions
+}
+func (this *FieldOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
+const Default_FieldOptions_Deprecated bool = false
+
+type EnumOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *EnumOptions) Reset() { *this = EnumOptions{} }
+func (this *EnumOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_EnumOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumOptions
+}
+func (this *EnumOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type EnumValueOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *EnumValueOptions) Reset() { *this = EnumValueOptions{} }
+func (this *EnumValueOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_EnumValueOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumValueOptions
+}
+func (this *EnumValueOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type ServiceOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *ServiceOptions) Reset() { *this = ServiceOptions{} }
+func (this *ServiceOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_ServiceOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ServiceOptions
+}
+func (this *ServiceOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type MethodOptions struct {
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *MethodOptions) Reset() { *this = MethodOptions{} }
+func (this *MethodOptions) String() string { return proto.CompactTextString(this) }
+
+var extRange_MethodOptions = []proto.ExtensionRange{
+ proto.ExtensionRange{1000, 536870911},
+}
+
+func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MethodOptions
+}
+func (this *MethodOptions) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type UninterpretedOption struct {
+ Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name"`
+ IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value"`
+ PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value"`
+ NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value"`
+ DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value"`
+ StringValue []byte `protobuf:"bytes,7,opt,name=string_value"`
+ XXX_unrecognized []byte
+}
+
+func (this *UninterpretedOption) Reset() { *this = UninterpretedOption{} }
+func (this *UninterpretedOption) String() string { return proto.CompactTextString(this) }
+
+type UninterpretedOption_NamePart struct {
+ NamePart *string `protobuf:"bytes,1,req,name=name_part"`
+ IsExtension *bool `protobuf:"varint,2,req,name=is_extension"`
+ XXX_unrecognized []byte
+}
+
+func (this *UninterpretedOption_NamePart) Reset() { *this = UninterpretedOption_NamePart{} }
+func (this *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(this) }
+
+func init() {
+ proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value)
+ proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value)
+ proto.RegisterEnum("google_protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
+ proto.RegisterEnum("google_protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
+}
--- /dev/null
+// 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.
+
+/*
+ A plugin for the Google protocol buffer compiler to generate Go code.
+ Run it by building this program and putting it in your path with the name
+ protoc-gen-go
+ That word 'go' at the end becomes part of the option string set for the
+ protocol compiler, so once the protocol compiler (protoc) is installed
+ you can run
+ protoc --go_out=output_directory input_directory/file.proto
+ to generate Go bindings for the protocol defined by file.proto.
+ With that input, the output will be written to
+ output_directory/file.pb.go
+
+ The generated code is documented in the package comment for
+ the library.
+
+ See the README and documentation for protocol buffers to learn more:
+ http://code.google.com/p/protobuf/
+
+*/
+package documentation
--- /dev/null
+# 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.
+
+include $(GOROOT)/src/Make.inc
+
+TARG=goprotobuf.googlecode.com/hg/compiler/generator
+GOFILES=\
+ generator.go\
+
+DEPS=../descriptor ../plugin ../../proto
+
+include $(GOROOT)/src/Make.pkg
--- /dev/null
+// 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 code generator for the plugin for the Google protocol buffer compiler.
+ It generates Go code from the protocol buffer description files read by the
+ main routine.
+*/
+package generator
+
+import (
+ "bytes"
+ "fmt"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "log"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+
+ "goprotobuf.googlecode.com/hg/proto"
+ plugin "goprotobuf.googlecode.com/hg/compiler/plugin"
+ descriptor "goprotobuf.googlecode.com/hg/compiler/descriptor"
+)
+
+// A Plugin provides functionality to add to the output during Go code generation,
+// such as to produce RPC stubs.
+type Plugin interface {
+ // Name identifies the plugin.
+ Name() string
+ // Init is called once after data structures are built but before
+ // code generation begins.
+ Init(g *Generator)
+ // Generate produces the code generated by the plugin for this file,
+ // except for the imports, by calling the generator's methods P, In, and Out.
+ Generate(file *FileDescriptor)
+ // GenerateImports produces the import declarations for this file.
+ // It is called after Generate.
+ GenerateImports(file *FileDescriptor)
+}
+
+var plugins []Plugin
+
+// RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated.
+// It is typically called during initialization.
+func RegisterPlugin(p Plugin) {
+ plugins = append(plugins, p)
+}
+
+// Each type we import as a protocol buffer (other than FileDescriptorProto) needs
+// a pointer to the FileDescriptorProto that represents it. These types achieve that
+// wrapping by placing each Proto inside a struct with the pointer to its File. The
+// structs have the same names as their contents, with "Proto" removed.
+// FileDescriptor is used to store the things that it points to.
+
+// The file and package name method are common to messages and enums.
+type common struct {
+ file *descriptor.FileDescriptorProto // File this object comes from.
+}
+
+// PackageName is name in the package clause in the generated file.
+func (c *common) PackageName() string { return uniquePackageOf(c.file) }
+
+func (c *common) File() *descriptor.FileDescriptorProto { return c.file }
+
+// Descriptor represents a protocol buffer message.
+type Descriptor struct {
+ common
+ *descriptor.DescriptorProto
+ parent *Descriptor // The containing message, if any.
+ nested []*Descriptor // Inner messages, if any.
+ ext []*ExtensionDescriptor // Extensions, if any.
+ typename []string // Cached typename vector.
+}
+
+// TypeName returns the elements of the dotted type name.
+// The package name is not part of this name.
+func (d *Descriptor) TypeName() []string {
+ if d.typename != nil {
+ return d.typename
+ }
+ n := 0
+ for parent := d; parent != nil; parent = parent.parent {
+ n++
+ }
+ s := make([]string, n, n)
+ for parent := d; parent != nil; parent = parent.parent {
+ n--
+ s[n] = proto.GetString(parent.Name)
+ }
+ d.typename = s
+ return s
+}
+
+// EnumDescriptor describes an enum. If it's at top level, its parent will be nil.
+// Otherwise it will be the descriptor of the message in which it is defined.
+type EnumDescriptor struct {
+ common
+ *descriptor.EnumDescriptorProto
+ parent *Descriptor // The containing message, if any.
+ typename []string // Cached typename vector.
+}
+
+// TypeName returns the elements of the dotted type name.
+// The package name is not part of this name.
+func (e *EnumDescriptor) TypeName() (s []string) {
+ if e.typename != nil {
+ return e.typename
+ }
+ name := proto.GetString(e.Name)
+ if e.parent == nil {
+ s = make([]string, 1)
+ } else {
+ pname := e.parent.TypeName()
+ s = make([]string, len(pname)+1)
+ copy(s, pname)
+ }
+ s[len(s)-1] = name
+ e.typename = s
+ return s
+}
+
+// Everything but the last element of the full type name, CamelCased.
+// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
+func (e *EnumDescriptor) prefix() string {
+ typeName := e.TypeName()
+ ccPrefix := CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
+ if e.parent == nil {
+ // If the enum is not part of a message, the prefix is just the type name.
+ ccPrefix = CamelCase(*e.Name) + "_"
+ }
+ return ccPrefix
+}
+
+// The integer value of the named constant in this enumerated type.
+func (e *EnumDescriptor) integerValueAsString(name string) string {
+ for _, c := range e.Value {
+ if proto.GetString(c.Name) == name {
+ return fmt.Sprint(proto.GetInt32(c.Number))
+ }
+ }
+ log.Fatal("cannot find value for enum constant")
+ return ""
+}
+
+// ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil.
+// Otherwise it will be the descriptor of the message in which it is defined.
+type ExtensionDescriptor struct {
+ common
+ *descriptor.FieldDescriptorProto
+ parent *Descriptor // The containing message, if any.
+}
+
+// TypeName returns the elements of the dotted type name.
+// The package name is not part of this name.
+func (e *ExtensionDescriptor) TypeName() (s []string) {
+ name := proto.GetString(e.Name)
+ if e.parent == nil {
+ // top-level extension
+ s = make([]string, 1)
+ } else {
+ pname := e.parent.TypeName()
+ s = make([]string, len(pname)+1)
+ copy(s, pname)
+ }
+ s[len(s)-1] = name
+ return s
+}
+
+// DescName returns the variable name used for the generated descriptor.
+func (e *ExtensionDescriptor) DescName() string {
+ // The full type name.
+ typeName := e.TypeName()
+ // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix.
+ for i, s := range typeName {
+ typeName[i] = CamelCase(s)
+ }
+ return "E_" + strings.Join(typeName, "_")
+}
+
+// ImportedDescriptor describes a type that has been publicly imported from another file.
+type ImportedDescriptor struct {
+ common
+ o Object
+}
+
+func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() }
+
+// FileDescriptor describes an protocol buffer descriptor file (.proto).
+// It includes slices of all the messages and enums defined within it.
+// Those slices are constructed by WrapTypes.
+type FileDescriptor struct {
+ *descriptor.FileDescriptorProto
+ desc []*Descriptor // All the messages defined in this file.
+ enum []*EnumDescriptor // All the enums defined in this file.
+ ext []*ExtensionDescriptor // All the top-level extensions defined in this file.
+ imp []*ImportedDescriptor // All types defined in files publicly imported by this file.
+
+ // The full list of symbols that are exported,
+ // as a map from the exported object to its symbols.
+ // This is used for supporting public imports.
+ exported map[Object][]Symbol
+}
+
+// PackageName is the package name we'll use in the generated code to refer to this file.
+func (d *FileDescriptor) PackageName() string { return uniquePackageOf(d.FileDescriptorProto) }
+
+// The package named defined in the input for this file, possibly dotted.
+// If the file does not define a package, use the base of the file name.
+func (d *FileDescriptor) originalPackageName() string {
+ // Does the file have a package clause?
+ if pkg := proto.GetString(d.Package); pkg != "" {
+ return pkg
+ }
+ // Use the file base name.
+ return BaseName(proto.GetString(d.Name))
+}
+
+func (d *FileDescriptor) addExport(obj Object, symbol Symbol) {
+ d.exported[obj] = append(d.exported[obj], symbol)
+}
+
+// Symbol is an interface representing an exported Go symbol.
+type Symbol interface {
+ // GenerateAlias should generate an appropriate alias
+ // for the symbol from the named package.
+ GenerateAlias(g *Generator, pkg string)
+}
+
+type messageSymbol struct {
+ sym string
+ hasExtensions, isMessageSet bool
+}
+
+func (ms messageSymbol) GenerateAlias(g *Generator, pkg string) {
+ remoteSym := pkg + "." + ms.sym
+
+ g.P("type ", ms.sym, " ", remoteSym)
+ g.P("func (this *", ms.sym, ") Reset() { (*", remoteSym, ")(this).Reset() }")
+ g.P("func (this *", ms.sym, ") String() string { return (*", remoteSym, ")(this).String() }")
+ if ms.hasExtensions {
+ g.P("func (*", ms.sym, ") ExtensionRangeArray() []", g.ProtoPkg, ".ExtensionRange ",
+ "{ return (*", remoteSym, ")(nil).ExtensionRangeArray() }")
+ g.P("func (this *", ms.sym, ") ExtensionMap() map[int32]", g.ProtoPkg, ".Extension ",
+ "{ return (*", remoteSym, ")(this).ExtensionMap() }")
+ if ms.isMessageSet {
+ g.P("func (this *", ms.sym, ") Marshal() ([]byte, os.Error) ",
+ "{ return (*", remoteSym, ")(this).Marshal() }")
+ g.P("func (this *", ms.sym, ") Unmarshal(buf []byte) os.Error ",
+ "{ return (*", remoteSym, ")(this).Unmarshal(buf) }")
+ }
+ }
+}
+
+type enumSymbol string
+
+func (es enumSymbol) GenerateAlias(g *Generator, pkg string) {
+ s := string(es)
+ g.P("type ", s, " ", pkg, ".", s)
+ g.P("var ", s, "_name = ", pkg, ".", s, "_name")
+ g.P("var ", s, "_value = ", pkg, ".", s, "_value")
+ g.P("func New", s, "(x ", s, ") *", s, " { e := ", s, "(x); return &e }")
+}
+
+type constOrVarSymbol struct {
+ sym string
+ typ string // either "const" or "var"
+}
+
+func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) {
+ g.P(cs.typ, " ", cs.sym, " = ", pkg, ".", cs.sym)
+}
+
+// Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
+type Object interface {
+ PackageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness.
+ TypeName() []string
+ File() *descriptor.FileDescriptorProto
+}
+
+// Each package name we generate must be unique. The package we're generating
+// gets its own name but every other package must have a unique name that does
+// not conflict in the code we generate. These names are chosen globally (although
+// they don't have to be, it simplifies things to do them globally).
+func uniquePackageOf(fd *descriptor.FileDescriptorProto) string {
+ s, ok := uniquePackageName[fd]
+ if !ok {
+ log.Fatal("internal error: no package name defined for", proto.GetString(fd.Name))
+ }
+ return s
+}
+
+// Generator is the type whose methods generate the output, stored in the associated response structure.
+type Generator struct {
+ *bytes.Buffer
+
+ Request *plugin.CodeGeneratorRequest // The input.
+ Response *plugin.CodeGeneratorResponse // The output.
+
+ Param map[string]string // Command-line parameters.
+ ImportPrefix string // String to prefix to imported package file names.
+ ImportMap map[string]string // Mapping from import name to generated name
+
+ ProtoPkg string // The name under which we import the library's package proto.
+
+ packageName string // What we're calling ourselves.
+ allFiles []*FileDescriptor // All files in the tree
+ genFiles []*FileDescriptor // Those files we will generate output for.
+ file *FileDescriptor // The file we are compiling now.
+ usedPackages map[string]bool // Names of packages used in current file.
+ typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
+ indent string
+}
+
+// New creates a new generator and allocates the request and response protobufs.
+func New() *Generator {
+ g := new(Generator)
+ g.Buffer = new(bytes.Buffer)
+ g.Request = new(plugin.CodeGeneratorRequest)
+ g.Response = new(plugin.CodeGeneratorResponse)
+ return g
+}
+
+// Error reports a problem, including an os.Error, and exits the program.
+func (g *Generator) Error(err os.Error, msgs ...string) {
+ s := strings.Join(msgs, " ") + ":" + err.String()
+ log.Println("protoc-gen-go: error:", s)
+ g.Response.Error = proto.String(s)
+ os.Exit(1)
+}
+
+// Fail reports a problem and exits the program.
+func (g *Generator) Fail(msgs ...string) {
+ s := strings.Join(msgs, " ")
+ log.Println("protoc-gen-go: error:", s)
+ g.Response.Error = proto.String(s)
+ os.Exit(1)
+}
+
+// CommandLineParameters breaks the comma-separated list of key=value pairs
+// in the parameter (a member of the request protobuf) into a key/value map.
+// It then sets file name mappings defined by those entries.
+func (g *Generator) CommandLineParameters(parameter string) {
+ g.Param = make(map[string]string)
+ for _, p := range strings.Split(parameter, ",") {
+ if i := strings.Index(p, "="); i < 0 {
+ g.Param[p] = ""
+ } else {
+ g.Param[p[0:i]] = p[i+1:]
+ }
+ }
+
+ g.ImportMap = make(map[string]string)
+ for k, v := range g.Param {
+ if k == "import_prefix" {
+ g.ImportPrefix = v
+ } else if len(k) > 0 && k[0] == 'M' {
+ g.ImportMap[k[1:]] = v
+ }
+ }
+}
+
+// DefaultPackageName returns the package name printed for the object.
+// If its file is in a different package, it returns the package name we're using for this file, plus ".".
+// Otherwise it returns the empty string.
+func (g *Generator) DefaultPackageName(obj Object) string {
+ pkg := obj.PackageName()
+ if pkg == g.packageName {
+ return ""
+ }
+ return pkg + "."
+}
+
+// For each input file, the unique package name to use, underscored.
+var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string)
+// Package names already registered. Key is the name from the .proto file;
+// value is the name that appears in the generated code.
+var pkgNamesInUse = make(map[string]bool)
+
+// Create and remember a guaranteed unique package name for this file descriptor.
+// Pkg is the candidate name. If f is nil, it's a builtin package like "proto" and
+// has no file descriptor.
+func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
+ // Convert dots to underscores before finding a unique alias.
+ pkg = strings.Map(DotToUnderscore, pkg)
+
+ for i, orig := 1, pkg; pkgNamesInUse[pkg]; i++ {
+ // It's a duplicate; must rename.
+ pkg = orig + strconv.Itoa(i)
+ }
+ // Install it.
+ pkgNamesInUse[pkg] = true
+ if f != nil {
+ uniquePackageName[f.FileDescriptorProto] = pkg
+ }
+ return pkg
+}
+
+// SetPackageNames sets the package name for this run.
+// The package name must agree across all files being generated.
+// It also defines unique package names for all imported files.
+func (g *Generator) SetPackageNames() {
+ // Register the name for this package. It will be the first name
+ // registered so is guaranteed to be unmodified.
+ pkg := g.genFiles[0].originalPackageName()
+ g.packageName = RegisterUniquePackageName(pkg, g.genFiles[0])
+ // Register the proto package name. It might collide with the
+ // name of a package we import.
+ g.ProtoPkg = RegisterUniquePackageName("proto", nil)
+ // Verify that we are generating output for a single package.
+ for _, f := range g.genFiles {
+ thisPkg := f.originalPackageName()
+ if thisPkg != pkg {
+ g.Fail("inconsistent package names:", thisPkg, pkg)
+ }
+ }
+AllFiles:
+ for _, f := range g.allFiles {
+ for _, genf := range g.genFiles {
+ if f == genf {
+ // In this package already.
+ uniquePackageName[f.FileDescriptorProto] = g.packageName
+ continue AllFiles
+ }
+ }
+ // The file is a dependency, so we want to ignore its go_package option
+ // because that is only relevant for its specific generated output.
+ pkg := proto.GetString(f.Package)
+ if pkg == "" {
+ pkg = BaseName(*f.Name)
+ }
+ RegisterUniquePackageName(pkg, f)
+ }
+}
+
+// WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos
+// and FileDescriptorProtos into file-referenced objects within the Generator.
+// It also creates the list of files to generate and so should be called before GenerateAllFiles.
+func (g *Generator) WrapTypes() {
+ g.allFiles = make([]*FileDescriptor, len(g.Request.ProtoFile))
+ for i, f := range g.Request.ProtoFile {
+ // We must wrap the descriptors before we wrap the enums
+ descs := wrapDescriptors(f)
+ g.buildNestedDescriptors(descs)
+ enums := wrapEnumDescriptors(f, descs)
+ exts := wrapExtensions(f)
+ imps := wrapImported(f, g)
+ g.allFiles[i] = &FileDescriptor{
+ FileDescriptorProto: f,
+ desc: descs,
+ enum: enums,
+ ext: exts,
+ imp: imps,
+ exported: make(map[Object][]Symbol),
+ }
+ }
+
+ g.genFiles = make([]*FileDescriptor, len(g.Request.FileToGenerate))
+FindFiles:
+ for i, fileName := range g.Request.FileToGenerate {
+ // Search the list. This algorithm is n^2 but n is tiny.
+ for _, file := range g.allFiles {
+ if fileName == proto.GetString(file.Name) {
+ g.genFiles[i] = file
+ continue FindFiles
+ }
+ }
+ g.Fail("could not find file named", fileName)
+ }
+ g.Response.File = make([]*plugin.CodeGeneratorResponse_File, len(g.genFiles))
+}
+
+// Scan the descriptors in this file. For each one, build the slice of nested descriptors
+func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
+ for _, desc := range descs {
+ if len(desc.NestedType) != 0 {
+ desc.nested = make([]*Descriptor, len(desc.NestedType))
+ n := 0
+ for _, nest := range descs {
+ if nest.parent == desc {
+ desc.nested[n] = nest
+ n++
+ }
+ }
+ if n != len(desc.NestedType) {
+ g.Fail("internal error: nesting failure for", proto.GetString(desc.Name))
+ }
+ }
+ }
+}
+
+// Construct the Descriptor and add it to the slice
+func addDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
+ d := &Descriptor{common{file}, desc, parent, nil, nil, nil}
+
+ d.ext = make([]*ExtensionDescriptor, len(desc.Extension))
+ for i, field := range desc.Extension {
+ d.ext[i] = &ExtensionDescriptor{common{file}, field, d}
+ }
+
+ return append(sl, d)
+}
+
+// Return a slice of all the Descriptors defined within this file
+func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
+ sl := make([]*Descriptor, 0, len(file.MessageType)+10)
+ for _, desc := range file.MessageType {
+ sl = wrapThisDescriptor(sl, desc, nil, file)
+ }
+ return sl
+}
+
+// Wrap this Descriptor, recursively
+func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
+ sl = addDescriptor(sl, desc, parent, file)
+ me := sl[len(sl)-1]
+ for _, nested := range desc.NestedType {
+ sl = wrapThisDescriptor(sl, nested, me, file)
+ }
+ return sl
+}
+
+// Construct the EnumDescriptor and add it to the slice
+func addEnumDescriptor(sl []*EnumDescriptor, desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*EnumDescriptor {
+ return append(sl, &EnumDescriptor{common{file}, desc, parent, nil})
+}
+
+// Return a slice of all the EnumDescriptors defined within this file
+func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor {
+ sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
+ // Top-level enums.
+ for _, enum := range file.EnumType {
+ sl = addEnumDescriptor(sl, enum, nil, file)
+ }
+ // Enums within messages. Enums within embedded messages appear in the outer-most message.
+ for _, nested := range descs {
+ for _, enum := range nested.EnumType {
+ sl = addEnumDescriptor(sl, enum, nested, file)
+ }
+ }
+ return sl
+}
+
+// Return a slice of all the top-level ExtensionDescriptors defined within this file.
+func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor {
+ sl := make([]*ExtensionDescriptor, len(file.Extension))
+ for i, field := range file.Extension {
+ sl[i] = &ExtensionDescriptor{common{file}, field, nil}
+ }
+ return sl
+}
+
+// Return a slice of all the types that are publicly imported into this file.
+func wrapImported(file *descriptor.FileDescriptorProto, g *Generator) (sl []*ImportedDescriptor) {
+ for _, index := range file.PublicDependency {
+ df := g.fileByName(file.Dependency[index])
+ for _, d := range df.desc {
+ sl = append(sl, &ImportedDescriptor{common{file}, d})
+ }
+ for _, e := range df.enum {
+ sl = append(sl, &ImportedDescriptor{common{file}, e})
+ }
+ for _, ext := range df.ext {
+ sl = append(sl, &ImportedDescriptor{common{file}, ext})
+ }
+ }
+ return
+}
+
+// BuildTypeNameMap builds the map from fully qualified type names to objects.
+// The key names for the map come from the input data, which puts a period at the beginning.
+// It should be called after SetPackageNames and before GenerateAllFiles.
+func (g *Generator) BuildTypeNameMap() {
+ g.typeNameToObject = make(map[string]Object)
+ for _, f := range g.allFiles {
+ // The names in this loop are defined by the proto world, not us, so the
+ // package name may be empty. If so, the dotted package name of X will
+ // be ".X"; otherwise it will be ".pkg.X".
+ dottedPkg := "." + proto.GetString(f.Package)
+ if dottedPkg != "." {
+ dottedPkg += "."
+ }
+ for _, enum := range f.enum {
+ name := dottedPkg + dottedSlice(enum.TypeName())
+ g.typeNameToObject[name] = enum
+ }
+ for _, desc := range f.desc {
+ name := dottedPkg + dottedSlice(desc.TypeName())
+ g.typeNameToObject[name] = desc
+ }
+ }
+}
+
+// ObjectNamed, given a fully-qualified input type name as it appears in the input data,
+// returns the descriptor for the message or enum with that name.
+func (g *Generator) ObjectNamed(typeName string) Object {
+ o, ok := g.typeNameToObject[typeName]
+ if !ok {
+ g.Fail("can't find object with type", typeName)
+ }
+
+ // If the file of this object isn't a direct dependency of the current file,
+ // or in the current file, then this object has been publicly imported into
+ // a dependency of the current file.
+ // We should return the ImportedDescriptor object for it instead.
+ direct := *o.File().Name == *g.file.Name
+ if !direct {
+ for _, dep := range g.file.Dependency {
+ if *g.fileByName(dep).Name == *o.File().Name {
+ direct = true
+ break
+ }
+ }
+ }
+ if !direct {
+ found := false
+ Loop:
+ for _, dep := range g.file.Dependency {
+ df := g.fileByName(*g.fileByName(dep).Name)
+ for _, td := range df.imp {
+ if td.o == o {
+ // Found it!
+ o = td
+ found = true
+ break Loop
+ }
+ }
+ }
+ if !found {
+ log.Printf("protoc-gen-go: WARNING: failed finding publicly imported dependency for %v, used in %v", typeName, *g.file.Name)
+ }
+ }
+
+ return o
+}
+
+// P prints the arguments to the generated output. It handles strings and int32s, plus
+// handling indirections because they may be *string, etc.
+func (g *Generator) P(str ...interface{}) {
+ g.WriteString(g.indent)
+ for _, v := range str {
+ switch s := v.(type) {
+ case string:
+ g.WriteString(s)
+ case *string:
+ g.WriteString(*s)
+ case bool:
+ g.WriteString(fmt.Sprintf("%t", s))
+ case *bool:
+ g.WriteString(fmt.Sprintf("%t", *s))
+ case *int32:
+ g.WriteString(fmt.Sprintf("%d", *s))
+ case float64:
+ g.WriteString(fmt.Sprintf("%g", s))
+ case *float64:
+ g.WriteString(fmt.Sprintf("%g", *s))
+ default:
+ g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
+ }
+ }
+ g.WriteByte('\n')
+}
+
+// In Indents the output one tab stop.
+func (g *Generator) In() { g.indent += "\t" }
+
+// Out unindents the output one tab stop.
+func (g *Generator) Out() {
+ if len(g.indent) > 0 {
+ g.indent = g.indent[1:]
+ }
+}
+
+// GenerateAllFiles generates the output for all the files we're outputting.
+func (g *Generator) GenerateAllFiles() {
+ // Initialize the plugins
+ for _, p := range plugins {
+ p.Init(g)
+ }
+ // Generate the output. The generator runs for every file, even the files
+ // that we don't generate output for, so that we can collate the full list
+ // of exported symbols to support public imports.
+ genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
+ for _, file := range g.genFiles {
+ genFileMap[file] = true
+ }
+ i := 0
+ for _, file := range g.allFiles {
+ g.Reset()
+ g.generate(file)
+ if _, ok := genFileMap[file]; !ok {
+ continue
+ }
+ g.Response.File[i] = new(plugin.CodeGeneratorResponse_File)
+ g.Response.File[i].Name = proto.String(goFileName(*file.Name))
+ g.Response.File[i].Content = proto.String(g.String())
+ i++
+ }
+}
+
+// Run all the plugins associated with the file.
+func (g *Generator) runPlugins(file *FileDescriptor) {
+ for _, p := range plugins {
+ p.Generate(file)
+ }
+}
+
+// FileOf return the FileDescriptor for this FileDescriptorProto.
+func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor {
+ for _, file := range g.allFiles {
+ if file.FileDescriptorProto == fd {
+ return file
+ }
+ }
+ g.Fail("could not find file in table:", proto.GetString(fd.Name))
+ return nil
+}
+
+// Fill the response protocol buffer with the generated output for all the files we're
+// supposed to generate.
+func (g *Generator) generate(file *FileDescriptor) {
+ g.file = g.FileOf(file.FileDescriptorProto)
+ g.usedPackages = make(map[string]bool)
+
+ for _, td := range g.file.imp {
+ g.generateImported(td)
+ }
+ for _, enum := range g.file.enum {
+ g.generateEnum(enum)
+ }
+ for _, desc := range g.file.desc {
+ g.generateMessage(desc)
+ }
+ for _, ext := range g.file.ext {
+ g.generateExtension(ext)
+ }
+ g.generateInitFunction()
+
+ // Run the plugins before the imports so we know which imports are necessary.
+ g.runPlugins(file)
+
+ // Generate header and imports last, though they appear first in the output.
+ rem := g.Buffer
+ g.Buffer = new(bytes.Buffer)
+ g.generateHeader()
+ g.generateImports()
+ g.Write(rem.Bytes())
+
+ // Reformat generated code.
+ fset := token.NewFileSet()
+ ast, err := parser.ParseFile(fset, "", g, parser.ParseComments)
+ if err != nil {
+ g.Fail("bad Go source code was generated:", err.String())
+ return
+ }
+ g.Reset()
+ _, err = (&printer.Config{printer.TabIndent | printer.UseSpaces, 8}).Fprint(g, fset, ast)
+ if err != nil {
+ g.Fail("generated Go source code could not be reformatted:", err.String())
+ }
+}
+
+// Generate the header, including package definition and imports
+func (g *Generator) generateHeader() {
+ g.P("// Code generated by protoc-gen-go from ", Quote(*g.file.Name))
+ g.P("// DO NOT EDIT!")
+ g.P()
+ g.P("package ", g.file.PackageName())
+ g.P()
+}
+
+func (g *Generator) fileByName(filename string) *FileDescriptor {
+ for _, fd := range g.allFiles {
+ if proto.GetString(fd.Name) == filename {
+ return fd
+ }
+ }
+ return nil
+}
+
+// Generate the header, including package definition and imports
+func (g *Generator) generateImports() {
+ // We almost always need a proto import. Rather than computing when we
+ // do, which is tricky when there's a plugin, just import it and
+ // reference it later. The same argument applies to the os package.
+ g.P("import " + g.ProtoPkg + " " + Quote(g.ImportPrefix+"goprotobuf.googlecode.com/hg/proto"))
+ g.P(`import "math"`)
+ g.P(`import "os"`)
+ for _, s := range g.file.Dependency {
+ fd := g.fileByName(s)
+ // Do not import our own package.
+ if fd.PackageName() == g.packageName {
+ continue
+ }
+ filename := goFileName(s)
+ if substitution, ok := g.ImportMap[s]; ok {
+ filename = substitution
+ }
+ filename = g.ImportPrefix + filename
+ if strings.HasSuffix(filename, ".go") {
+ filename = filename[0 : len(filename)-3]
+ }
+ if _, ok := g.usedPackages[fd.PackageName()]; ok {
+ g.P("import ", fd.PackageName(), " ", Quote(filename))
+ } else {
+ // TODO: Re-enable this when we are more feature-complete.
+ // For instance, some protos use foreign field extensions, which we don't support.
+ // Until then, this is just annoying spam.
+ //log.Printf("protoc-gen-go: discarding unused import from %v: %v", *g.file.Name, s)
+ g.P("// discarding unused import ", fd.PackageName(), " ", Quote(filename))
+ }
+ }
+ g.P()
+ // TODO: may need to worry about uniqueness across plugins
+ for _, p := range plugins {
+ p.GenerateImports(g.file)
+ g.P()
+ }
+ g.P("// Reference proto, math & os imports to suppress error if they are not otherwise used.")
+ g.P("var _ = ", g.ProtoPkg, ".GetString")
+ g.P("var _ = math.Inf")
+ g.P("var _ os.Error")
+ g.P()
+}
+
+func (g *Generator) generateImported(id *ImportedDescriptor) {
+ // Don't generate public import symbols for files that we are generating
+ // code for, since those symbols will already be in this package.
+ // We can't simply avoid creating the ImportedDescriptor objects,
+ // because g.genFiles isn't populated at that stage.
+ tn := id.TypeName()
+ sn := tn[len(tn)-1]
+ df := g.FileOf(id.o.File())
+ filename := *df.Name
+ for _, fd := range g.genFiles {
+ if *fd.Name == filename {
+ g.P("// Ignoring public import of ", sn, " from ", filename)
+ g.P()
+ return
+ }
+ }
+ g.P("// ", sn, " from public import ", filename)
+ g.usedPackages[df.PackageName()] = true
+
+ for _, sym := range df.exported[id.o] {
+ sym.GenerateAlias(g, df.PackageName())
+ }
+
+ g.P()
+}
+
+// Generate the enum definitions for this EnumDescriptor.
+func (g *Generator) generateEnum(enum *EnumDescriptor) {
+ // The full type name
+ typeName := enum.TypeName()
+ // The full type name, CamelCased.
+ ccTypeName := CamelCaseSlice(typeName)
+ ccPrefix := enum.prefix()
+ g.P("type ", ccTypeName, " int32")
+ g.file.addExport(enum, enumSymbol(ccTypeName))
+ g.P("const (")
+ g.In()
+ for _, e := range enum.Value {
+ name := ccPrefix + *e.Name
+ g.P(name, " ", ccTypeName, " = ", e.Number)
+ g.file.addExport(enum, constOrVarSymbol{name, "const"})
+ }
+ g.Out()
+ g.P(")")
+ g.P("var ", ccTypeName, "_name = map[int32]string{")
+ g.In()
+ generated := make(map[int32]bool) // avoid duplicate values
+ for _, e := range enum.Value {
+ duplicate := ""
+ if _, present := generated[*e.Number]; present {
+ duplicate = "// Duplicate value: "
+ }
+ g.P(duplicate, e.Number, ": ", Quote(*e.Name), ",")
+ generated[*e.Number] = true
+ }
+ g.Out()
+ g.P("}")
+ g.P("var ", ccTypeName, "_value = map[string]int32{")
+ g.In()
+ for _, e := range enum.Value {
+ g.P(Quote(*e.Name), ": ", e.Number, ",")
+ }
+ g.Out()
+ g.P("}")
+
+ g.P("func New", ccTypeName, "(x ", ccTypeName, ") *", ccTypeName, " {")
+ g.In()
+ g.P("e := ", ccTypeName, "(x)")
+ g.P("return &e")
+ g.Out()
+ g.P("}")
+
+ g.P("func (x ", ccTypeName, ") String() string {")
+ g.In()
+ g.P("return ", g.ProtoPkg, ".EnumName(", ccTypeName, "_name, int32(x))")
+ g.Out()
+ g.P("}")
+
+ g.P()
+}
+
+// The tag is a string like "varint,2,opt,name=fieldname,def=7" that
+// identifies details of the field for the protocol buffer marshaling and unmarshaling
+// code. The fields are:
+// wire encoding
+// protocol tag number
+// opt,req,rep for optional, required, or repeated
+// packed whether the encoding is "packed" (optional; repeated primitives only)
+// name= the original declared name
+// enum= the name of the enum type if it is an enum-typed field.
+// def= string representation of the default value, if any.
+// The default value must be in a representation that can be used at run-time
+// to generate the default value. Thus bools become 0 and 1, for instance.
+func (g *Generator) goTag(field *descriptor.FieldDescriptorProto, wiretype string) string {
+ optrepreq := ""
+ switch {
+ case isOptional(field):
+ optrepreq = "opt"
+ case isRequired(field):
+ optrepreq = "req"
+ case isRepeated(field):
+ optrepreq = "rep"
+ }
+ defaultValue := proto.GetString(field.DefaultValue)
+ if defaultValue != "" {
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ if defaultValue == "true" {
+ defaultValue = "1"
+ } else {
+ defaultValue = "0"
+ }
+ case descriptor.FieldDescriptorProto_TYPE_STRING,
+ descriptor.FieldDescriptorProto_TYPE_BYTES:
+ // Nothing to do. Quoting is done for the whole tag.
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ // For enums we need to provide the integer constant.
+ obj := g.ObjectNamed(proto.GetString(field.TypeName))
+ enum, ok := obj.(*EnumDescriptor)
+ if !ok {
+ g.Fail("enum type inconsistent for", CamelCaseSlice(obj.TypeName()))
+ }
+ defaultValue = enum.integerValueAsString(defaultValue)
+ }
+ defaultValue = ",def=" + defaultValue
+ }
+ enum := ""
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
+ // We avoid using obj.PackageName(), because we want to use the
+ // original (proto-world) package name.
+ obj := g.ObjectNamed(proto.GetString(field.TypeName))
+ enum = ",enum="
+ if pkg := proto.GetString(obj.File().Package); pkg != "" {
+ enum += pkg + "."
+ }
+ enum += CamelCaseSlice(obj.TypeName())
+ }
+ packed := ""
+ if field.Options != nil && proto.GetBool(field.Options.Packed) {
+ packed = ",packed"
+ }
+ fieldName := proto.GetString(field.Name)
+ name := fieldName
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
+ // We must use the type name for groups instead of
+ // the field name to preserve capitalization.
+ // type_name in FieldDescriptorProto is fully-qualified,
+ // but we only want the local part.
+ name = *field.TypeName
+ if i := strings.LastIndex(name, "."); i >= 0 {
+ name = name[i+1:]
+ }
+ }
+ if name == CamelCase(fieldName) {
+ name = ""
+ } else {
+ name = ",name=" + name
+ }
+ return Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s",
+ wiretype,
+ proto.GetInt32(field.Number),
+ optrepreq,
+ packed,
+ name,
+ enum,
+ defaultValue))
+}
+
+func needsStar(typ descriptor.FieldDescriptorProto_Type) bool {
+ switch typ {
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ return false
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ return false
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ return false
+ }
+ return true
+}
+
+// TypeName is the printed name appropriate for an item. If the object is in the current file,
+// TypeName drops the package name and underscores the rest.
+// Otherwise the object is from another package; and the result is the underscored
+// package name followed by the item name.
+// The result always has an initial capital.
+func (g *Generator) TypeName(obj Object) string {
+ return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
+}
+
+// TypeNameWithPackage is like TypeName, but always includes the package
+// name even if the object is in our own package.
+func (g *Generator) TypeNameWithPackage(obj Object) string {
+ return obj.PackageName() + CamelCaseSlice(obj.TypeName())
+}
+
+// GoType returns a string representing the type name, and the wire type
+func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
+ // TODO: Options.
+ switch *field.Type {
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ typ, wire = "float64", "fixed64"
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ typ, wire = "float32", "fixed32"
+ case descriptor.FieldDescriptorProto_TYPE_INT64:
+ typ, wire = "int64", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_UINT64:
+ typ, wire = "uint64", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_INT32:
+ typ, wire = "int32", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_UINT32:
+ typ, wire = "uint32", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ typ, wire = "uint64", "fixed64"
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ typ, wire = "uint32", "fixed32"
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ typ, wire = "bool", "varint"
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ typ, wire = "string", "bytes"
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ desc := g.ObjectNamed(proto.GetString(field.TypeName))
+ typ, wire = "*"+g.TypeName(desc), "group"
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ desc := g.ObjectNamed(proto.GetString(field.TypeName))
+ typ, wire = "*"+g.TypeName(desc), "bytes"
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ typ, wire = "[]byte", "bytes"
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ desc := g.ObjectNamed(proto.GetString(field.TypeName))
+ typ, wire = g.TypeName(desc), "varint"
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ typ, wire = "int32", "fixed32"
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ typ, wire = "int64", "fixed64"
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ typ, wire = "int32", "zigzag32"
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ typ, wire = "int64", "zigzag64"
+ default:
+ g.Fail("unknown type for", proto.GetString(field.Name))
+ }
+ if isRepeated(field) {
+ typ = "[]" + typ
+ } else if needsStar(*field.Type) {
+ typ = "*" + typ
+ }
+ return
+}
+
+func (g *Generator) RecordTypeUse(t string) {
+ if obj, ok := g.typeNameToObject[t]; ok {
+ // Call ObjectNamed to get the true object to record the use.
+ obj = g.ObjectNamed(t)
+ g.usedPackages[obj.PackageName()] = true
+ }
+}
+
+// Generate the type and default constant definitions for this Descriptor.
+func (g *Generator) generateMessage(message *Descriptor) {
+ // The full type name
+ typeName := message.TypeName()
+ // The full type name, CamelCased.
+ ccTypeName := CamelCaseSlice(typeName)
+
+ g.P("type ", ccTypeName, " struct {")
+ g.In()
+ for _, field := range message.Field {
+ fieldname := CamelCase(*field.Name)
+ typename, wiretype := g.GoType(message, field)
+ jsonName := *field.Name
+ tag := fmt.Sprintf("`protobuf:%s json:%q`", g.goTag(field, wiretype), jsonName+",omitempty")
+ g.P(fieldname, "\t", typename, "\t", tag)
+ g.RecordTypeUse(proto.GetString(field.TypeName))
+ }
+ // TODO: Use `json:"-"` for these XXX_ fields when that makes it into a Go release.
+ if len(message.ExtensionRange) > 0 {
+ g.P("XXX_extensions\t\tmap[int32]", g.ProtoPkg, ".Extension `json:\",omitempty\"`")
+ }
+ g.P("XXX_unrecognized\t[]byte `json:\",omitempty\"`")
+ g.Out()
+ g.P("}")
+
+ // Reset and String functions
+ g.P("func (this *", ccTypeName, ") Reset() { *this = ", ccTypeName, "{} }")
+ g.P("func (this *", ccTypeName, ") String() string { return ", g.ProtoPkg, ".CompactTextString(this) }")
+
+ // Extension support methods
+ var hasExtensions, isMessageSet bool
+ if len(message.ExtensionRange) > 0 {
+ hasExtensions = true
+ // message_set_wire_format only makes sense when extensions are defined.
+ if opts := message.Options; opts != nil && proto.GetBool(opts.MessageSetWireFormat) {
+ isMessageSet = true
+ g.P()
+ g.P("func (this *", ccTypeName, ") Marshal() ([]byte, os.Error) {")
+ g.In()
+ g.P("return ", g.ProtoPkg, ".MarshalMessageSet(this.ExtensionMap())")
+ g.Out()
+ g.P("}")
+ g.P("func (this *", ccTypeName, ") Unmarshal(buf []byte) os.Error {")
+ g.In()
+ g.P("return ", g.ProtoPkg, ".UnmarshalMessageSet(buf, this.ExtensionMap())")
+ g.Out()
+ g.P("}")
+ g.P("// ensure ", ccTypeName, " satisfies proto.Marshaler and proto.Unmarshaler")
+ g.P("var _ ", g.ProtoPkg, ".Marshaler = (*", ccTypeName, ")(nil)")
+ g.P("var _ ", g.ProtoPkg, ".Unmarshaler = (*", ccTypeName, ")(nil)")
+ }
+
+ g.P()
+ g.P("var extRange_", ccTypeName, " = []", g.ProtoPkg, ".ExtensionRange{")
+ g.In()
+ for _, r := range message.ExtensionRange {
+ end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
+ g.P("{", r.Start, ", ", end, "},")
+ }
+ g.Out()
+ g.P("}")
+ g.P("func (*", ccTypeName, ") ExtensionRangeArray() []", g.ProtoPkg, ".ExtensionRange {")
+ g.In()
+ g.P("return extRange_", ccTypeName)
+ g.Out()
+ g.P("}")
+ g.P("func (this *", ccTypeName, ") ExtensionMap() map[int32]", g.ProtoPkg, ".Extension {")
+ g.In()
+ g.P("if this.XXX_extensions == nil {")
+ g.In()
+ g.P("this.XXX_extensions = make(map[int32]", g.ProtoPkg, ".Extension)")
+ g.Out()
+ g.P("}")
+ g.P("return this.XXX_extensions")
+ g.Out()
+ g.P("}")
+ }
+
+ g.file.addExport(message, messageSymbol{ccTypeName, hasExtensions, isMessageSet})
+
+ // Default constants
+ for _, field := range message.Field {
+ def := proto.GetString(field.DefaultValue)
+ if def == "" {
+ continue
+ }
+ fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name)
+ typename, _ := g.GoType(message, field)
+ if typename[0] == '*' {
+ typename = typename[1:]
+ }
+ kind := "const "
+ switch {
+ case typename == "bool":
+ case typename == "string":
+ def = Quote(def)
+ case typename == "[]byte":
+ def = "[]byte(" + Quote(def) + ")"
+ kind = "var "
+ case def == "inf", def == "-inf", def == "nan":
+ // These names are known to, and defined by, the protocol language.
+ switch def {
+ case "inf":
+ def = "math.Inf(1)"
+ case "-inf":
+ def = "math.Inf(-1)"
+ case "nan":
+ def = "math.NaN()"
+ }
+ if *field.Type == descriptor.FieldDescriptorProto_TYPE_FLOAT {
+ def = "float32(" + def + ")"
+ }
+ kind = "var "
+ case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM:
+ // Must be an enum. Need to construct the prefixed name.
+ obj := g.ObjectNamed(proto.GetString(field.TypeName))
+ enum, ok := obj.(*EnumDescriptor)
+ if !ok {
+ log.Println("don't know how to generate constant for", fieldname)
+ continue
+ }
+ def = g.DefaultPackageName(enum) + enum.prefix() + def
+ }
+ g.P(kind, fieldname, " ", typename, " = ", def)
+ g.file.addExport(message, constOrVarSymbol{fieldname, kind})
+ }
+ g.P()
+
+ for _, ext := range message.ext {
+ g.generateExtension(ext)
+ }
+}
+
+func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
+ ccTypeName := ext.DescName()
+
+ extendedType := "*" + g.TypeName(g.ObjectNamed(*ext.Extendee))
+ field := ext.FieldDescriptorProto
+ fieldType, wireType := g.GoType(ext.parent, field)
+ tag := g.goTag(field, wireType)
+ g.RecordTypeUse(*ext.Extendee)
+ if n := ext.FieldDescriptorProto.TypeName; n != nil {
+ // foreign extension type
+ g.RecordTypeUse(*n)
+ }
+
+ g.P("var ", ccTypeName, " = &", g.ProtoPkg, ".ExtensionDesc{")
+ g.In()
+ g.P("ExtendedType: (", extendedType, ")(nil),")
+ g.P("ExtensionType: (", fieldType, ")(nil),")
+ g.P("Field: ", field.Number, ",")
+ g.P(`Name: "`, g.packageName, ".", strings.Join(ext.TypeName(), "."), `",`)
+ g.P("Tag: ", tag, ",")
+
+ g.Out()
+ g.P("}")
+ g.P()
+
+ g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var"})
+}
+
+func (g *Generator) generateInitFunction() {
+ g.P("func init() {")
+ g.In()
+ for _, enum := range g.file.enum {
+ g.generateEnumRegistration(enum)
+ }
+ for _, d := range g.file.desc {
+ for _, ext := range d.ext {
+ g.generateExtensionRegistration(ext)
+ }
+ }
+ for _, ext := range g.file.ext {
+ g.generateExtensionRegistration(ext)
+ }
+ g.Out()
+ g.P("}")
+}
+
+func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
+ // // We always print the full (proto-world) package name here.
+ pkg := proto.GetString(enum.File().Package)
+ if pkg != "" {
+ pkg += "."
+ }
+ // The full type name
+ typeName := enum.TypeName()
+ // The full type name, CamelCased.
+ ccTypeName := CamelCaseSlice(typeName)
+ g.P(g.ProtoPkg+".RegisterEnum(", Quote(pkg+ccTypeName), ", ", ccTypeName+"_name, ", ccTypeName+"_value)")
+}
+
+func (g *Generator) generateExtensionRegistration(ext *ExtensionDescriptor) {
+ g.P(g.ProtoPkg+".RegisterExtension(", ext.DescName(), ")")
+}
+
+// And now lots of helper functions.
+
+// Is c an ASCII lower-case letter?
+func isASCIILower(c byte) bool {
+ return 'a' <= c && c <= 'z'
+}
+
+// Is c an ASCII digit?
+func isASCIIDigit(c byte) bool {
+ return '0' <= c && c <= '9'
+}
+
+// CamelCase returns the CamelCased name.
+// If there is an interior underscore followed by a lower case letter,
+// drop the underscore and convert the letter to upper case.
+// There is a remote possibility of this rewrite causing a name collision,
+// but it's so remote we're prepared to pretend it's nonexistent - since the
+// C++ generator lowercases names, it's extremely unlikely to have two fields
+// with different capitalizations.
+// In short, _my_field_name_2 becomes XMyFieldName2.
+func CamelCase(s string) string {
+ if s == "" {
+ return ""
+ }
+ t := make([]byte, 0, 32)
+ i := 0
+ if s[0] == '_' {
+ // Need a capital letter; drop the '_'.
+ t = append(t, 'X')
+ i++
+ }
+ // Invariant: if the next letter is lower case, it must be converted
+ // to upper case.
+ // That is, we process a word at a time, where words are marked by _ or
+ // upper case letter. Digits are treated as words.
+ for ; i < len(s); i++ {
+ c := s[i]
+ if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
+ continue // Skip the underscore in s.
+ }
+ if isASCIIDigit(c) {
+ t = append(t, c)
+ continue
+ }
+ // Assume we have a letter now - if not, it's a bogus identifier.
+ // The next word is a sequence of characters that must start upper case.
+ if isASCIILower(c) {
+ c ^= ' ' // Make it a capital letter.
+ }
+ t = append(t, c) // Guaranteed not lower case.
+ // Accept lower case sequence that follows.
+ for i+1 < len(s) && isASCIILower(s[i+1]) {
+ i++
+ t = append(t, s[i])
+ }
+ }
+ return string(t)
+}
+
+// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
+// be joined with "_".
+func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
+
+// dottedSlice turns a sliced name into a dotted name.
+func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
+
+// Quote returns a Go-source quoted string representation of s.
+func Quote(s string) string { return fmt.Sprintf("%q", s) }
+
+// Given a .proto file name, return the output name for the generated Go program.
+func goFileName(name string) string {
+ ext := path.Ext(name)
+ if ext == ".proto" || ext == ".protodevel" {
+ name = name[0 : len(name)-len(ext)]
+ }
+ return name + ".pb.go"
+}
+
+// Is this field optional?
+func isOptional(field *descriptor.FieldDescriptorProto) bool {
+ return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
+}
+
+// Is this field required?
+func isRequired(field *descriptor.FieldDescriptorProto) bool {
+ return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
+}
+
+// Is this field repeated?
+func isRepeated(field *descriptor.FieldDescriptorProto) bool {
+ return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
+}
+
+// DotToUnderscore is the mapping function used to generate Go names from package names,
+// which can be dotted in the input .proto file. It maps dots to underscores.
+// Because we also get here from package names generated from file names, it also maps
+// minus signs to underscores.
+func DotToUnderscore(rune int) int {
+ switch rune {
+ case '.', '-':
+ return '_'
+ }
+ return rune
+}
+
+// BaseName returns the last path element of the name, with the last dotted suffix removed.
+func BaseName(name string) string {
+ // First, find the last element
+ if i := strings.LastIndex(name, "/"); i >= 0 {
+ name = name[i+1:]
+ }
+ // Now drop the suffix
+ if i := strings.LastIndex(name, "."); i >= 0 {
+ name = name[0:i]
+ }
+ return name
+}
--- /dev/null
+// 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.
+
+/*
+ A plugin for the Google protocol buffer compiler to generate Go code.
+
+ This plugin takes no options and the protocol buffer file syntax does
+ not yet define any options for Go, so program does no option evaluation.
+ That may change.
+*/
+
+package main
+
+import (
+ "io/ioutil"
+ "os"
+
+ "goprotobuf.googlecode.com/hg/proto"
+ "goprotobuf.googlecode.com/hg/compiler/generator"
+)
+
+func main() {
+ // Begin by allocating a generator. The request and response structures are stored there
+ // so we can do error handling easily - the response structure contains the field to
+ // report failure.
+ g := generator.New()
+
+ data, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ g.Error(err, "reading input")
+ }
+
+ if err := proto.Unmarshal(data, g.Request); err != nil {
+ g.Error(err, "parsing input proto")
+ }
+
+ if len(g.Request.FileToGenerate) == 0 {
+ g.Fail("no files to generate")
+ }
+
+ g.CommandLineParameters(proto.GetString(g.Request.Parameter))
+
+ // Create a wrapped version of the Descriptors and EnumDescriptors that
+ // point to the file that defines them.
+ g.WrapTypes()
+
+ g.SetPackageNames()
+ g.BuildTypeNameMap()
+
+ g.GenerateAllFiles()
+
+ // Send back the results.
+ data, err = proto.Marshal(g.Response)
+ if err != nil {
+ g.Error(err, "failed to marshal output proto")
+ }
+ _, err = os.Stdout.Write(data)
+ if err != nil {
+ g.Error(err, "failed to write output proto")
+ }
+}
--- /dev/null
+# 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.
+
+include $(GOROOT)/src/Make.inc
+
+TARG=goprotobuf.googlecode.com/hg/compiler/plugin
+GOFILES=\
+ plugin.pb.go\
+
+DEPS=../../proto ../descriptor
+
+include $(GOROOT)/src/Make.pkg
+
+# Not stored here, but plugin.proto is in http://code.google.com/p/protobuf
+# at protobuf-2.3.0/src/google/protobuf/compiler/plugin.proto
+# Also we need to fix an import.
+regenerate:
+ echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
+ cd $(HOME)/protobuf-2.3.0/src && \
+ protoc --go_out=. ./google/protobuf/compiler/plugin.proto && \
+ cat ./google/protobuf/compiler/plugin.pb.go | \
+ sed '/^import/s;google/protobuf/descriptor.pb;goprotobuf.googlecode.com/hg/compiler/descriptor;' >$(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/compiler/plugin/plugin.pb.go
+
+restore:
+ cp plugin.pb.golden plugin.pb.go
+
+preserve:
+ cp plugin.pb.go plugin.pb.golden
--- /dev/null
+// Code generated by protoc-gen-go from "google/protobuf/compiler/plugin.proto"
+// DO NOT EDIT!
+
+package google_protobuf_compiler
+
+import proto "goprotobuf.googlecode.com/hg/proto"
+import "math"
+import "os"
+import google_protobuf "goprotobuf.googlecode.com/hg/compiler/descriptor"
+
+// Reference proto, math & os imports to suppress error if they are not otherwise used.
+var _ = proto.GetString
+var _ = math.Inf
+var _ os.Error
+
+
+type CodeGeneratorRequest struct {
+ FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate"`
+ Parameter *string `protobuf:"bytes,2,opt,name=parameter"`
+ ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file"`
+ XXX_unrecognized []byte
+}
+
+func (this *CodeGeneratorRequest) Reset() { *this = CodeGeneratorRequest{} }
+func (this *CodeGeneratorRequest) String() string { return proto.CompactTextString(this) }
+
+type CodeGeneratorResponse struct {
+ Error *string `protobuf:"bytes,1,opt,name=error"`
+ File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file"`
+ XXX_unrecognized []byte
+}
+
+func (this *CodeGeneratorResponse) Reset() { *this = CodeGeneratorResponse{} }
+func (this *CodeGeneratorResponse) String() string { return proto.CompactTextString(this) }
+
+type CodeGeneratorResponse_File struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point"`
+ Content *string `protobuf:"bytes,15,opt,name=content"`
+ XXX_unrecognized []byte
+}
+
+func (this *CodeGeneratorResponse_File) Reset() { *this = CodeGeneratorResponse_File{} }
+func (this *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(this) }
+
+func init() {
+}
--- /dev/null
+// Code generated by protoc-gen-go from "google/protobuf/compiler/plugin.proto"
+// DO NOT EDIT!
+
+package google_protobuf_compiler
+
+import proto "goprotobuf.googlecode.com/hg/proto"
+import "math"
+import "os"
+import google_protobuf "goprotobuf.googlecode.com/hg/compiler/descriptor"
+
+// Reference proto, math & os imports to suppress error if they are not otherwise used.
+var _ = proto.GetString
+var _ = math.Inf
+var _ os.Error
+
+
+type CodeGeneratorRequest struct {
+ FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate"`
+ Parameter *string `protobuf:"bytes,2,opt,name=parameter"`
+ ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file"`
+ XXX_unrecognized []byte
+}
+
+func (this *CodeGeneratorRequest) Reset() { *this = CodeGeneratorRequest{} }
+func (this *CodeGeneratorRequest) String() string { return proto.CompactTextString(this) }
+
+type CodeGeneratorResponse struct {
+ Error *string `protobuf:"bytes,1,opt,name=error"`
+ File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file"`
+ XXX_unrecognized []byte
+}
+
+func (this *CodeGeneratorResponse) Reset() { *this = CodeGeneratorResponse{} }
+func (this *CodeGeneratorResponse) String() string { return proto.CompactTextString(this) }
+
+type CodeGeneratorResponse_File struct {
+ Name *string `protobuf:"bytes,1,opt,name=name"`
+ InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point"`
+ Content *string `protobuf:"bytes,15,opt,name=content"`
+ XXX_unrecognized []byte
+}
+
+func (this *CodeGeneratorResponse_File) Reset() { *this = CodeGeneratorResponse_File{} }
+func (this *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(this) }
+
+func init() {
+}
--- /dev/null
+# 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.
+
+include $(GOROOT)/src/Make.inc
+
+all:
+ @echo run make test
+
+include $(GOROOT)/src/Make.common
+include ../../Make.protobuf
+
+CLEANFILES+=*.pb.go extension_test
+
+test: golden testbuild extension_test
+ ./extension_test
+ @echo PASS
+
+golden:
+ $(QUOTED_GOBIN)/gomake -B test.pb.go
+ diff -w test.pb.go test.pb.go.golden
+
+nuke: clean
+
+testbuild: main.$O
+ $(LD) -L. main.$O
+
+extension_test: extension_test.$O
+ $(LD) -L. -o $@ $<
+
+multi.a: multi3.pb.$O multi2.pb.$O multi1.pb.$O
+ rm -f multi.a
+ $(QUOTED_GOBIN)/gopack grc $@ $<
+
+%.$O: %.go
+ $(QUOTED_GOBIN)/$(GC) -I . -o $@ $<
+
+test.pb.go: imp.pb.go
+multi1.pb.go: multi2.pb.go multi3.pb.go
+main.$O: imp.pb.$O test.pb.$O multi.a
+extension_test.$O: extension_base.pb.$O extension_extra.pb.$O extension_user.pb.$O
--- /dev/null
+// 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.
+
+package extension_base;
+
+message BaseMessage {
+ optional int32 height = 1;
+ extensions 4 to 9;
+ extensions 16 to max;
+}
+
+// Another message that may be extended, using message_set_wire_format.
+message OldStyleMessage {
+ option message_set_wire_format = true;
+ extensions 100 to max;
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 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.
+
+syntax = "proto2";
+
+package extension_extra;
+
+message ExtraMessage {
+ optional int32 width = 1;
+}
--- /dev/null
+// 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.
+
+// Test that we can use protocol buffers that use extensions.
+
+package main
+
+import (
+ "bytes"
+ "regexp"
+ "testing"
+
+ "goprotobuf.googlecode.com/hg/proto"
+ base "extension_base.pb"
+ user "extension_user.pb"
+)
+
+func TestSingleFieldExtension(t *testing.T) {
+ bm := &base.BaseMessage{
+ Height: proto.Int32(178),
+ }
+
+ // Use extension within scope of another type.
+ vol := proto.Uint32(11)
+ err := proto.SetExtension(bm, user.E_LoudMessage_Volume, vol)
+ if err != nil {
+ t.Fatal("Failed setting extension:", err)
+ }
+ buf, err := proto.Marshal(bm)
+ if err != nil {
+ t.Fatal("Failed encoding message with extension:", err)
+ }
+ bm_new := new(base.BaseMessage)
+ if err := proto.Unmarshal(buf, bm_new); err != nil {
+ t.Fatal("Failed decoding message with extension:", err)
+ }
+ if !proto.HasExtension(bm_new, user.E_LoudMessage_Volume) {
+ t.Fatal("Decoded message didn't contain extension.")
+ }
+ vol_out, err := proto.GetExtension(bm_new, user.E_LoudMessage_Volume)
+ if err != nil {
+ t.Fatal("Failed getting extension:", err)
+ }
+ if v := vol_out.(*uint32); *v != *vol {
+ t.Errorf("vol_out = %v, expected %v", *v, *vol)
+ }
+ proto.ClearExtension(bm_new, user.E_LoudMessage_Volume)
+ if proto.HasExtension(bm_new, user.E_LoudMessage_Volume) {
+ t.Fatal("Failed clearing extension.")
+ }
+}
+
+func TestMessageExtension(t *testing.T) {
+ bm := &base.BaseMessage{
+ Height: proto.Int32(179),
+ }
+
+ // Use extension that is itself a message.
+ um := &user.UserMessage{
+ Name: proto.String("Dave"),
+ Rank: proto.String("Major"),
+ }
+ err := proto.SetExtension(bm, user.E_LoginMessage_UserMessage, um)
+ if err != nil {
+ t.Fatal("Failed setting extension:", err)
+ }
+ buf, err := proto.Marshal(bm)
+ if err != nil {
+ t.Fatal("Failed encoding message with extension:", err)
+ }
+ bm_new := new(base.BaseMessage)
+ if err := proto.Unmarshal(buf, bm_new); err != nil {
+ t.Fatal("Failed decoding message with extension:", err)
+ }
+ if !proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) {
+ t.Fatal("Decoded message didn't contain extension.")
+ }
+ um_out, err := proto.GetExtension(bm_new, user.E_LoginMessage_UserMessage)
+ if err != nil {
+ t.Fatal("Failed getting extension:", err)
+ }
+ if n := um_out.(*user.UserMessage).Name; *n != *um.Name {
+ t.Errorf("um_out.Name = %q, expected %q", *n, *um.Name)
+ }
+ if r := um_out.(*user.UserMessage).Rank; *r != *um.Rank {
+ t.Errorf("um_out.Rank = %q, expected %q", *r, *um.Rank)
+ }
+ proto.ClearExtension(bm_new, user.E_LoginMessage_UserMessage)
+ if proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) {
+ t.Fatal("Failed clearing extension.")
+ }
+}
+
+func TestTopLevelExtension(t *testing.T) {
+ bm := &base.BaseMessage{
+ Height: proto.Int32(179),
+ }
+
+ width := proto.Int32(17)
+ err := proto.SetExtension(bm, user.E_Width, width)
+ if err != nil {
+ t.Fatal("Failed setting extension:", err)
+ }
+ buf, err := proto.Marshal(bm)
+ if err != nil {
+ t.Fatal("Failed encoding message with extension:", err)
+ }
+ bm_new := new(base.BaseMessage)
+ if err := proto.Unmarshal(buf, bm_new); err != nil {
+ t.Fatal("Failed decoding message with extension:", err)
+ }
+ if !proto.HasExtension(bm_new, user.E_Width) {
+ t.Fatal("Decoded message didn't contain extension.")
+ }
+ width_out, err := proto.GetExtension(bm_new, user.E_Width)
+ if err != nil {
+ t.Fatal("Failed getting extension:", err)
+ }
+ if w := width_out.(*int32); *w != *width {
+ t.Errorf("width_out = %v, expected %v", *w, *width)
+ }
+ proto.ClearExtension(bm_new, user.E_Width)
+ if proto.HasExtension(bm_new, user.E_Width) {
+ t.Fatal("Failed clearing extension.")
+ }
+}
+
+func TestMessageSetWireFormat(t *testing.T) {
+ osm := new(base.OldStyleMessage)
+ osp := &user.OldStyleParcel{
+ Name: proto.String("Dave"),
+ Height: proto.Int32(178),
+ }
+
+ err := proto.SetExtension(osm, user.E_OldStyleParcel_MessageSetExtension, osp)
+ if err != nil {
+ t.Fatal("Failed setting extension:", err)
+ }
+
+ buf, err := proto.Marshal(osm)
+ if err != nil {
+ t.Fatal("Failed encoding message:", err)
+ }
+
+ // Data generated from Python implementation.
+ expected := []byte{
+ 11, 16, 209, 15, 26, 9, 10, 4, 68, 97, 118, 101, 16, 178, 1, 12,
+ }
+
+ if !bytes.Equal(expected, buf) {
+ t.Errorf("Encoding mismatch.\nwant %+v\n got %+v", expected, buf)
+ }
+
+ // Check that it is restored correctly.
+ osm = new(base.OldStyleMessage)
+ if err := proto.Unmarshal(buf, osm); err != nil {
+ t.Fatal("Failed decoding message:", err)
+ }
+ osp_out, err := proto.GetExtension(osm, user.E_OldStyleParcel_MessageSetExtension)
+ if err != nil {
+ t.Fatal("Failed getting extension:", err)
+ }
+ osp = osp_out.(*user.OldStyleParcel)
+ if *osp.Name != "Dave" || *osp.Height != 178 {
+ t.Errorf("Retrieved extension from decoded message is not correct: %+v", osp)
+ }
+}
+
+func main() {
+ // simpler than rigging up gotest
+ testing.Main(regexp.MatchString, []testing.InternalTest{
+ {"TestSingleFieldExtension", TestSingleFieldExtension},
+ {"TestMessageExtension", TestMessageExtension},
+ {"TestTopLevelExtension", TestTopLevelExtension},
+ },
+ []testing.InternalBenchmark{})
+}
--- /dev/null
+// 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.
+
+import "extension_base.proto";
+import "extension_extra.proto";
+
+package extension_user;
+
+message UserMessage {
+ optional string name = 1;
+ optional string rank = 2;
+}
+
+// Extend with a message
+extend extension_base.BaseMessage {
+ optional UserMessage user_message = 5;
+}
+
+// Extend with a foreign message
+extend extension_base.BaseMessage {
+ optional extension_extra.ExtraMessage extra_message = 9;
+}
+
+// Extend with some primitive types
+extend extension_base.BaseMessage {
+ optional int32 width = 6;
+ optional int64 area = 7;
+}
+
+// Extend inside the scope of another type
+message LoudMessage {
+ extend extension_base.BaseMessage {
+ optional uint32 volume = 8;
+ }
+ extensions 100 to max;
+}
+
+// Extend inside the scope of another type, using a message.
+message LoginMessage {
+ extend extension_base.BaseMessage {
+ required UserMessage user_message = 16;
+ }
+}
+
+// An extension of an extension
+message Announcement {
+ optional string words = 1;
+ extend LoudMessage {
+ optional Announcement loud_ext = 100;
+ }
+}
+
+// Something that can be put in a message set.
+message OldStyleParcel {
+ extend extension_base.OldStyleMessage {
+ optional OldStyleParcel message_set_extension = 2001;
+ }
+
+ required string name = 1;
+ optional int32 height = 2;
+}
--- /dev/null
+// Code generated by protoc-gen-go from "imp.proto"
+// DO NOT EDIT!
+
+package imp
+
+import proto "goprotobuf.googlecode.com/hg/proto"
+import "math"
+import "os"
+import imp1 "imp2.pb"
+
+// Reference proto, math & os imports to suppress error if they are not otherwise used.
+var _ = proto.GetString
+var _ = math.Inf
+var _ os.Error
+
+// Types from public import imp2.proto
+type PubliclyImportedMessage imp1.PubliclyImportedMessage
+
+func (this *PubliclyImportedMessage) Reset() { (*imp1.PubliclyImportedMessage)(this).Reset() }
+func (this *PubliclyImportedMessage) String() string {
+ return (*imp1.PubliclyImportedMessage)(this).String()
+}
+
+// PubliclyImportedMessage from public import imp.proto
+
+type ImportedMessage_Owner int32
+
+const (
+ ImportedMessage_DAVE ImportedMessage_Owner = 1
+ ImportedMessage_MIKE ImportedMessage_Owner = 2
+)
+
+var ImportedMessage_Owner_name = map[int32]string{
+ 1: "DAVE",
+ 2: "MIKE",
+}
+var ImportedMessage_Owner_value = map[string]int32{
+ "DAVE": 1,
+ "MIKE": 2,
+}
+
+func NewImportedMessage_Owner(x ImportedMessage_Owner) *ImportedMessage_Owner {
+ e := ImportedMessage_Owner(x)
+ return &e
+}
+func (x ImportedMessage_Owner) String() string {
+ return proto.EnumName(ImportedMessage_Owner_name, int32(x))
+}
+
+type ImportedMessage struct {
+ Field *int64 `protobuf:"varint,1,req,name=field" json:"field,omitempty"`
+ XXX_extensions map[int32][]byte `json:",omitempty"`
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *ImportedMessage) Reset() { *this = ImportedMessage{} }
+func (this *ImportedMessage) String() string { return proto.CompactTextString(this) }
+
+var extRange_ImportedMessage = []proto.ExtensionRange{
+ proto.ExtensionRange{90, 100},
+}
+
+func (*ImportedMessage) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ImportedMessage
+}
+func (this *ImportedMessage) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type ImportedExtendable struct {
+ XXX_extensions map[int32][]byte `json:",omitempty"`
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *ImportedExtendable) Reset() { *this = ImportedExtendable{} }
+func (this *ImportedExtendable) String() string { return proto.CompactTextString(this) }
+
+func (this *ImportedExtendable) Marshal() ([]byte, os.Error) {
+ return proto.MarshalMessageSet(this.ExtensionMap())
+}
+func (this *ImportedExtendable) Unmarshal(buf []byte) os.Error {
+ return proto.UnmarshalMessageSet(buf, this.ExtensionMap())
+}
+// ensure ImportedExtendable satisfies proto.Marshaler and proto.Unmarshaler
+var _ proto.Marshaler = (*ImportedExtendable)(nil)
+var _ proto.Unmarshaler = (*ImportedExtendable)(nil)
+
+var extRange_ImportedExtendable = []proto.ExtensionRange{
+ proto.ExtensionRange{100, 536870911},
+}
+
+func (*ImportedExtendable) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ImportedExtendable
+}
+func (this *ImportedExtendable) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+func init() {
+ proto.RegisterEnum("imp.ImportedMessage_Owner", ImportedMessage_Owner_name, ImportedMessage_Owner_value)
+}
--- /dev/null
+// 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.
+
+package imp;
+
+import "imp2.proto";
+
+message ImportedMessage {
+ required int64 field = 1;
+
+ enum Owner {
+ DAVE = 1;
+ MIKE = 2;
+ }
+
+ extensions 90 to 100;
+}
+
+message ImportedExtendable {
+ option message_set_wire_format = true;
+ extensions 100 to max;
+}
--- /dev/null
+//
+// Copyright 2011 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.
+
+package imp;
+
+message PubliclyImportedMessage {
+ optional int64 field = 1;
+}
--- /dev/null
+// 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.
+
+// A simple binary to link together the protocol buffers in this test.
+
+package main
+
+import (
+ "./test.pb"
+ "./multi1.pb"
+)
+
+func main() {
+ _ = &my_test.Request{}
+ _ = &multitest.Multi1{}
+}
--- /dev/null
+// 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.
+
+import "multi2.proto";
+import "multi3.proto";
+
+package multitest;
+
+message Multi1 {
+ required Multi2 multi2 = 1;
+ optional Multi2.Color color = 2;
+ optional Multi3.HatType hat_type = 3;
+}
+
--- /dev/null
+// 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.
+
+package multitest;
+
+message Multi2 {
+ required int32 required_value = 1;
+
+ enum Color {
+ BLUE = 1;
+ GREEN = 2;
+ RED = 3;
+ };
+ optional Color color = 2;
+}
+
--- /dev/null
+// 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.
+
+package multitest;
+
+message Multi3 {
+ enum HatType {
+ FEDORA = 1;
+ FEZ = 2;
+ };
+ optional HatType hat_type = 1;
+}
+
--- /dev/null
+// Code generated by protoc-gen-go from "test.proto"
+// DO NOT EDIT!
+
+package my_test
+
+import proto "goprotobuf.googlecode.com/hg/proto"
+import "math"
+import "os"
+import imp1 "imp.pb"
+// discarding unused import multitest2 "multi1.pb"
+
+// Reference proto, math & os imports to suppress error if they are not otherwise used.
+var _ = proto.GetString
+var _ = math.Inf
+var _ os.Error
+
+type HatType int32
+
+const (
+ HatType_FEDORA HatType = 1
+ HatType_FEZ HatType = 2
+)
+
+var HatType_name = map[int32]string{
+ 1: "FEDORA",
+ 2: "FEZ",
+}
+var HatType_value = map[string]int32{
+ "FEDORA": 1,
+ "FEZ": 2,
+}
+
+func NewHatType(x HatType) *HatType {
+ e := HatType(x)
+ return &e
+}
+func (x HatType) String() string {
+ return proto.EnumName(HatType_name, int32(x))
+}
+
+type Days int32
+
+const (
+ Days_MONDAY Days = 1
+ Days_TUESDAY Days = 2
+ Days_LUNDI Days = 1
+)
+
+var Days_name = map[int32]string{
+ 1: "MONDAY",
+ 2: "TUESDAY",
+ // Duplicate value: 1: "LUNDI",
+}
+var Days_value = map[string]int32{
+ "MONDAY": 1,
+ "TUESDAY": 2,
+ "LUNDI": 1,
+}
+
+func NewDays(x Days) *Days {
+ e := Days(x)
+ return &e
+}
+func (x Days) String() string {
+ return proto.EnumName(Days_name, int32(x))
+}
+
+type Request_Color int32
+
+const (
+ Request_RED Request_Color = 0
+ Request_GREEN Request_Color = 1
+ Request_BLUE Request_Color = 2
+)
+
+var Request_Color_name = map[int32]string{
+ 0: "RED",
+ 1: "GREEN",
+ 2: "BLUE",
+}
+var Request_Color_value = map[string]int32{
+ "RED": 0,
+ "GREEN": 1,
+ "BLUE": 2,
+}
+
+func NewRequest_Color(x Request_Color) *Request_Color {
+ e := Request_Color(x)
+ return &e
+}
+func (x Request_Color) String() string {
+ return proto.EnumName(Request_Color_name, int32(x))
+}
+
+type Reply_Entry_Game int32
+
+const (
+ Reply_Entry_FOOTBALL Reply_Entry_Game = 1
+ Reply_Entry_TENNIS Reply_Entry_Game = 2
+)
+
+var Reply_Entry_Game_name = map[int32]string{
+ 1: "FOOTBALL",
+ 2: "TENNIS",
+}
+var Reply_Entry_Game_value = map[string]int32{
+ "FOOTBALL": 1,
+ "TENNIS": 2,
+}
+
+func NewReply_Entry_Game(x Reply_Entry_Game) *Reply_Entry_Game {
+ e := Reply_Entry_Game(x)
+ return &e
+}
+func (x Reply_Entry_Game) String() string {
+ return proto.EnumName(Reply_Entry_Game_name, int32(x))
+}
+
+type Request struct {
+ Key []int64 `protobuf:"varint,1,rep,name=key" json:"key,omitempty"`
+ ImportedMessage *imp1.ImportedMessage `protobuf:"bytes,2,opt,name=imported_message" json:"imported_message,omitempty"`
+ Hue *Request_Color `protobuf:"varint,3,opt,name=hue,enum=my.test.Request_Color" json:"hue,omitempty"`
+ Hat *HatType `protobuf:"varint,4,opt,name=hat,enum=my.test.HatType,def=1" json:"hat,omitempty"`
+ Owner *imp1.ImportedMessage_Owner `protobuf:"varint,6,opt,name=owner,enum=imp.ImportedMessage_Owner" json:"owner,omitempty"`
+ Deadline *float32 `protobuf:"fixed32,7,opt,name=deadline,def=inf" json:"deadline,omitempty"`
+ Somegroup *Request_SomeGroup `protobuf:"group,8,opt,name=SomeGroup" json:"somegroup,omitempty"`
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *Request) Reset() { *this = Request{} }
+func (this *Request) String() string { return proto.CompactTextString(this) }
+
+const Default_Request_Hat HatType = HatType_FEDORA
+
+var Default_Request_Deadline float32 = float32(math.Inf(1))
+
+type Request_SomeGroup struct {
+ GroupField *int32 `protobuf:"varint,9,opt,name=group_field" json:"group_field,omitempty"`
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *Request_SomeGroup) Reset() { *this = Request_SomeGroup{} }
+func (this *Request_SomeGroup) String() string { return proto.CompactTextString(this) }
+
+type Reply struct {
+ Found []*Reply_Entry `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"`
+ CompactKeys []int32 `protobuf:"varint,2,rep,packed,name=compact_keys" json:"compact_keys,omitempty"`
+ XXX_extensions map[int32]proto.Extension `json:",omitempty"`
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *Reply) Reset() { *this = Reply{} }
+func (this *Reply) String() string { return proto.CompactTextString(this) }
+
+var extRange_Reply = []proto.ExtensionRange{
+ {100, 536870911},
+}
+
+func (*Reply) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_Reply
+}
+func (this *Reply) ExtensionMap() map[int32]proto.Extension {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32]proto.Extension)
+ }
+ return this.XXX_extensions
+}
+
+type Reply_Entry struct {
+ KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng" json:"key_that_needs_1234camel_CasIng,omitempty"`
+ Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"`
+ XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2" json:"_my_field_name_2,omitempty"`
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *Reply_Entry) Reset() { *this = Reply_Entry{} }
+func (this *Reply_Entry) String() string { return proto.CompactTextString(this) }
+
+const Default_Reply_Entry_Value int64 = 7
+
+type ReplyExtensions struct {
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *ReplyExtensions) Reset() { *this = ReplyExtensions{} }
+func (this *ReplyExtensions) String() string { return proto.CompactTextString(this) }
+
+var E_ReplyExtensions_Time = &proto.ExtensionDesc{
+ ExtendedType: (*Reply)(nil),
+ ExtensionType: (*float64)(nil),
+ Field: 101,
+ Name: "my_test.ReplyExtensions.time",
+ Tag: "fixed64,101,opt,name=time",
+}
+
+type OldReply struct {
+ XXX_extensions map[int32]proto.Extension `json:",omitempty"`
+ XXX_unrecognized []byte `json:",omitempty"`
+}
+
+func (this *OldReply) Reset() { *this = OldReply{} }
+func (this *OldReply) String() string { return proto.CompactTextString(this) }
+
+func (this *OldReply) Marshal() ([]byte, os.Error) {
+ return proto.MarshalMessageSet(this.ExtensionMap())
+}
+func (this *OldReply) Unmarshal(buf []byte) os.Error {
+ return proto.UnmarshalMessageSet(buf, this.ExtensionMap())
+}
+// ensure OldReply satisfies proto.Marshaler and proto.Unmarshaler
+var _ proto.Marshaler = (*OldReply)(nil)
+var _ proto.Unmarshaler = (*OldReply)(nil)
+
+var extRange_OldReply = []proto.ExtensionRange{
+ {100, 536870911},
+}
+
+func (*OldReply) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_OldReply
+}
+func (this *OldReply) ExtensionMap() map[int32]proto.Extension {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32]proto.Extension)
+ }
+ return this.XXX_extensions
+}
+
+var E_Tag = &proto.ExtensionDesc{
+ ExtendedType: (*Reply)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 103,
+ Name: "my_test.tag",
+ Tag: "bytes,103,opt,name=tag",
+}
+
+func init() {
+ proto.RegisterEnum("my.test.HatType", HatType_name, HatType_value)
+ proto.RegisterEnum("my.test.Days", Days_name, Days_value)
+ proto.RegisterEnum("my.test.Request_Color", Request_Color_name, Request_Color_value)
+ proto.RegisterEnum("my.test.Reply_Entry_Game", Reply_Entry_Game_name, Reply_Entry_Game_value)
+ proto.RegisterExtension(E_ReplyExtensions_Time)
+ proto.RegisterExtension(E_Tag)
+}
--- /dev/null
+// 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.
+
+package my.test; // dotted package name
+
+import "imp.proto";
+import "multi1.proto"; // unused import
+
+enum HatType {
+ // deliberately skipping 0
+ FEDORA = 1;
+ FEZ = 2;
+}
+
+enum Days {
+ MONDAY = 1;
+ TUESDAY = 2;
+ LUNDI = 1; // same value as MONDAY
+}
+
+message Request {
+ enum Color {
+ RED = 0;
+ GREEN = 1;
+ BLUE = 2;
+ }
+ repeated int64 key = 1;
+ optional imp.ImportedMessage imported_message = 2;
+ optional Color hue = 3;
+ optional HatType hat = 4 [default=FEDORA];
+ optional imp.ImportedMessage.Owner owner = 6;
+ optional float deadline = 7 [default=inf];
+ optional group SomeGroup = 8 {
+ optional int32 group_field = 9;
+ }
+
+ // This foreign message type is in imp2.proto,
+ // which is publicly imported by imp.proto.
+ // optional imp.PubliclyImportedMessage pub = 10;
+}
+
+message Reply {
+ message Entry {
+ required int64 key_that_needs_1234camel_CasIng = 1;
+ optional int64 value = 2 [default=7];
+ optional int64 _my_field_name_2 = 3;
+ enum Game {
+ FOOTBALL = 1;
+ TENNIS = 2;
+ }
+ }
+ repeated Entry found = 1;
+ repeated int32 compact_keys = 2 [packed=true];
+ extensions 100 to max;
+}
+
+message ReplyExtensions {
+ extend Reply {
+ optional double time = 101;
+ }
+}
+
+// top-level extension
+extend Reply {
+ optional string tag = 103;
+}
+
+message OldReply {
+ // Extensions will be encoded in MessageSet wire format.
+ option message_set_wire_format = true;
+ extensions 100 to max;
+}
+
--- /dev/null
+defaultcc: golang-dev@googlegroups.com
--- /dev/null
+# 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.
+
+
+include $(GOROOT)/src/Make.inc
+
+TARG=goprotobuf.googlecode.com/hg/proto
+GOFILES=\
+ clone.go\
+ decode.go\
+ encode.go\
+ equal.go\
+ extensions.go\
+ lib.go\
+ message_set.go\
+ properties.go\
+ text.go\
+ text_parser.go\
+
+include $(GOROOT)/src/Make.pkg
+
+# We need to compile the .pb.gos, which import this package, so
+# to run the test we must make install here and then make in the
+# testdata directory.
+test: compile-test-pbs
+
+testshort: compile-test-pbs
+
+compile-test-pbs:
+ make install && cd testdata && make nuke && make
--- /dev/null
+// 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.
+
+
+package proto_test
+
+import (
+ "bytes"
+ "fmt"
+ "json"
+ "math"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+
+ . "goprotobuf.googlecode.com/hg/proto"
+ . "./testdata/_obj/test_proto"
+)
+
+var globalO *Buffer
+
+func old() *Buffer {
+ if globalO == nil {
+ globalO = NewBuffer(nil)
+ }
+ globalO.Reset()
+ return globalO
+}
+
+func equalbytes(b1, b2 []byte, t *testing.T) {
+ if len(b1) != len(b2) {
+ t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2))
+ return
+ }
+ for i := 0; i < len(b1); i++ {
+ if b1[i] != b2[i] {
+ t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2)
+ }
+ }
+}
+
+func initGoTestField() *GoTestField {
+ f := new(GoTestField)
+ f.Label = String("label")
+ f.Type = String("type")
+ return f
+}
+
+// These are all structurally equivalent but the tag numbers differ.
+// (It's remarkable that required, optional, and repeated all have
+// 8 letters.)
+func initGoTest_RequiredGroup() *GoTest_RequiredGroup {
+ return &GoTest_RequiredGroup{
+ RequiredField: String("required"),
+ }
+}
+
+func initGoTest_OptionalGroup() *GoTest_OptionalGroup {
+ return &GoTest_OptionalGroup{
+ RequiredField: String("optional"),
+ }
+}
+
+func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup {
+ return &GoTest_RepeatedGroup{
+ RequiredField: String("repeated"),
+ }
+}
+
+func initGoTest(setdefaults bool) *GoTest {
+ pb := new(GoTest)
+ if setdefaults {
+ pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted)
+ pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted)
+ pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted)
+ pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted)
+ pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted)
+ pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted)
+ pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted)
+ pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted)
+ pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted)
+ pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted)
+ pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted
+ pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted)
+ pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted)
+ }
+
+ pb.Kind = NewGoTest_KIND(GoTest_TIME)
+ pb.RequiredField = initGoTestField()
+ pb.F_BoolRequired = Bool(true)
+ pb.F_Int32Required = Int32(3)
+ pb.F_Int64Required = Int64(6)
+ pb.F_Fixed32Required = Uint32(32)
+ pb.F_Fixed64Required = Uint64(64)
+ pb.F_Uint32Required = Uint32(3232)
+ pb.F_Uint64Required = Uint64(6464)
+ pb.F_FloatRequired = Float32(3232)
+ pb.F_DoubleRequired = Float64(6464)
+ pb.F_StringRequired = String("string")
+ pb.F_BytesRequired = []byte("bytes")
+ pb.F_Sint32Required = Int32(-32)
+ pb.F_Sint64Required = Int64(-64)
+ pb.Requiredgroup = initGoTest_RequiredGroup()
+
+ return pb
+}
+
+func fail(msg string, b *bytes.Buffer, s string, t *testing.T) {
+ data := b.Bytes()
+ ld := len(data)
+ ls := len(s) / 2
+
+ fmt.Printf("fail %s ld=%d ls=%d\n", msg, ld, ls)
+
+ // find the interesting spot - n
+ n := ls
+ if ld < ls {
+ n = ld
+ }
+ j := 0
+ for i := 0; i < n; i++ {
+ bs := hex(s[j])*16 + hex(s[j+1])
+ j += 2
+ if data[i] == bs {
+ continue
+ }
+ n = i
+ break
+ }
+ l := n - 10
+ if l < 0 {
+ l = 0
+ }
+ h := n + 10
+
+ // find the interesting spot - n
+ fmt.Printf("is[%d]:", l)
+ for i := l; i < h; i++ {
+ if i >= ld {
+ fmt.Printf(" --")
+ continue
+ }
+ fmt.Printf(" %.2x", data[i])
+ }
+ fmt.Printf("\n")
+
+ fmt.Printf("sb[%d]:", l)
+ for i := l; i < h; i++ {
+ if i >= ls {
+ fmt.Printf(" --")
+ continue
+ }
+ bs := hex(s[j])*16 + hex(s[j+1])
+ j += 2
+ fmt.Printf(" %.2x", bs)
+ }
+ fmt.Printf("\n")
+
+ t.Fail()
+
+ // t.Errorf("%s: \ngood: %s\nbad: %x", msg, s, b.Bytes())
+ // Print the output in a partially-decoded format; can
+ // be helpful when updating the test. It produces the output
+ // that is pasted, with minor edits, into the argument to verify().
+ // data := b.Bytes()
+ // nesting := 0
+ // for b.Len() > 0 {
+ // start := len(data) - b.Len()
+ // var u uint64
+ // u, err := DecodeVarint(b)
+ // if err != nil {
+ // fmt.Printf("decode error on varint:", err)
+ // return
+ // }
+ // wire := u & 0x7
+ // tag := u >> 3
+ // switch wire {
+ // case WireVarint:
+ // v, err := DecodeVarint(b)
+ // if err != nil {
+ // fmt.Printf("decode error on varint:", err)
+ // return
+ // }
+ // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n",
+ // data[start:len(data)-b.Len()], tag, wire, v)
+ // case WireFixed32:
+ // v, err := DecodeFixed32(b)
+ // if err != nil {
+ // fmt.Printf("decode error on fixed32:", err)
+ // return
+ // }
+ // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n",
+ // data[start:len(data)-b.Len()], tag, wire, v)
+ // case WireFixed64:
+ // v, err := DecodeFixed64(b)
+ // if err != nil {
+ // fmt.Printf("decode error on fixed64:", err)
+ // return
+ // }
+ // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n",
+ // data[start:len(data)-b.Len()], tag, wire, v)
+ // case WireBytes:
+ // nb, err := DecodeVarint(b)
+ // if err != nil {
+ // fmt.Printf("decode error on bytes:", err)
+ // return
+ // }
+ // after_tag := len(data) - b.Len()
+ // str := make([]byte, nb)
+ // _, err = b.Read(str)
+ // if err != nil {
+ // fmt.Printf("decode error on bytes:", err)
+ // return
+ // }
+ // fmt.Printf("\t\t\"%x\" \"%x\" // field %d, encoding %d (FIELD)\n",
+ // data[start:after_tag], str, tag, wire)
+ // case WireStartGroup:
+ // nesting++
+ // fmt.Printf("\t\t\"%x\"\t\t// start group field %d level %d\n",
+ // data[start:len(data)-b.Len()], tag, nesting)
+ // case WireEndGroup:
+ // fmt.Printf("\t\t\"%x\"\t\t// end group field %d level %d\n",
+ // data[start:len(data)-b.Len()], tag, nesting)
+ // nesting--
+ // default:
+ // fmt.Printf("unrecognized wire type %d\n", wire)
+ // return
+ // }
+ // }
+}
+
+func hex(c uint8) uint8 {
+ if '0' <= c && c <= '9' {
+ return c - '0'
+ }
+ if 'a' <= c && c <= 'f' {
+ return 10 + c - 'a'
+ }
+ if 'A' <= c && c <= 'F' {
+ return 10 + c - 'A'
+ }
+ return 0
+}
+
+func equal(b []byte, s string, t *testing.T) bool {
+ if 2*len(b) != len(s) {
+ // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t)
+ fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s))
+ return false
+ }
+ for i, j := 0, 0; i < len(b); i, j = i+1, j+2 {
+ x := hex(s[j])*16 + hex(s[j+1])
+ if b[i] != x {
+ // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t)
+ fmt.Printf("bad byte[%d]:%x %x", i, b[i], x)
+ return false
+ }
+ }
+ return true
+}
+
+func overify(t *testing.T, pb *GoTest, expected string) {
+ o := old()
+ err := o.Marshal(pb)
+ if err != nil {
+ fmt.Printf("overify marshal-1 err = %v", err)
+ o.DebugPrint("", o.Bytes())
+ t.Fatalf("expected = %s", expected)
+ }
+ if !equal(o.Bytes(), expected, t) {
+ o.DebugPrint("overify neq 1", o.Bytes())
+ t.Fatalf("expected = %s", expected)
+ }
+
+ // Now test Unmarshal by recreating the original buffer.
+ pbd := new(GoTest)
+ err = o.Unmarshal(pbd)
+ if err != nil {
+ t.Fatalf("overify unmarshal err = %v", err)
+ o.DebugPrint("", o.Bytes())
+ t.Fatalf("string = %s", expected)
+ }
+ o.Reset()
+ err = o.Marshal(pbd)
+ if err != nil {
+ t.Errorf("overify marshal-2 err = %v", err)
+ o.DebugPrint("", o.Bytes())
+ t.Fatalf("string = %s", expected)
+ }
+ if !equal(o.Bytes(), expected, t) {
+ o.DebugPrint("overify neq 2", o.Bytes())
+ t.Fatalf("string = %s", expected)
+ }
+}
+
+// Simple tests for numeric encode/decode primitives (varint, etc.)
+func TestNumericPrimitives(t *testing.T) {
+ for i := uint64(0); i < 1e6; i += 111 {
+ o := old()
+ if o.EncodeVarint(i) != nil {
+ t.Error("EncodeVarint")
+ break
+ }
+ x, e := o.DecodeVarint()
+ if e != nil {
+ t.Fatal("DecodeVarint")
+ }
+ if x != i {
+ t.Fatal("varint decode fail:", i, x)
+ }
+
+ o = old()
+ if o.EncodeFixed32(i) != nil {
+ t.Fatal("encFixed32")
+ }
+ x, e = o.DecodeFixed32()
+ if e != nil {
+ t.Fatal("decFixed32")
+ }
+ if x != i {
+ t.Fatal("fixed32 decode fail:", i, x)
+ }
+
+ o = old()
+ if o.EncodeFixed64(i*1234567) != nil {
+ t.Error("encFixed64")
+ break
+ }
+ x, e = o.DecodeFixed64()
+ if e != nil {
+ t.Error("decFixed64")
+ break
+ }
+ if x != i*1234567 {
+ t.Error("fixed64 decode fail:", i*1234567, x)
+ break
+ }
+
+ o = old()
+ i32 := int32(i - 12345)
+ if o.EncodeZigzag32(uint64(i32)) != nil {
+ t.Fatal("EncodeZigzag32")
+ }
+ x, e = o.DecodeZigzag32()
+ if e != nil {
+ t.Fatal("DecodeZigzag32")
+ }
+ if x != uint64(uint32(i32)) {
+ t.Fatal("zigzag32 decode fail:", i32, x)
+ }
+
+ o = old()
+ i64 := int64(i - 12345)
+ if o.EncodeZigzag64(uint64(i64)) != nil {
+ t.Fatal("EncodeZigzag64")
+ }
+ x, e = o.DecodeZigzag64()
+ if e != nil {
+ t.Fatal("DecodeZigzag64")
+ }
+ if x != uint64(i64) {
+ t.Fatal("zigzag64 decode fail:", i64, x)
+ }
+ }
+}
+
+// Simple tests for bytes
+func TestBytesPrimitives(t *testing.T) {
+ o := old()
+ bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'}
+ if o.EncodeRawBytes(bytes) != nil {
+ t.Error("EncodeRawBytes")
+ }
+ decb, e := o.DecodeRawBytes(false)
+ if e != nil {
+ t.Error("DecodeRawBytes")
+ }
+ equalbytes(bytes, decb, t)
+}
+
+// Simple tests for strings
+func TestStringPrimitives(t *testing.T) {
+ o := old()
+ s := "now is the time"
+ if o.EncodeStringBytes(s) != nil {
+ t.Error("enc_string")
+ }
+ decs, e := o.DecodeStringBytes()
+ if e != nil {
+ t.Error("dec_string")
+ }
+ if s != decs {
+ t.Error("string encode/decode fail:", s, decs)
+ }
+}
+
+// Do we catch the "required bit not set" case?
+func TestRequiredBit(t *testing.T) {
+ o := old()
+ pb := new(GoTest)
+ err := o.Marshal(pb)
+ if err == nil {
+ t.Error("did not catch missing required fields")
+ } else if strings.Index(err.String(), "GoTest") < 0 {
+ t.Error("wrong error type:", err)
+ }
+}
+
+// Check that all fields are nil.
+// Clearly silly, and a residue from a more interesting test with an earlier,
+// different initialization property, but it once caught a compiler bug so
+// it lives.
+func checkInitialized(pb *GoTest, t *testing.T) {
+ if pb.F_BoolDefaulted != nil {
+ t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted)
+ }
+ if pb.F_Int32Defaulted != nil {
+ t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted)
+ }
+ if pb.F_Int64Defaulted != nil {
+ t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted)
+ }
+ if pb.F_Fixed32Defaulted != nil {
+ t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted)
+ }
+ if pb.F_Fixed64Defaulted != nil {
+ t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted)
+ }
+ if pb.F_Uint32Defaulted != nil {
+ t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted)
+ }
+ if pb.F_Uint64Defaulted != nil {
+ t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted)
+ }
+ if pb.F_FloatDefaulted != nil {
+ t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted)
+ }
+ if pb.F_DoubleDefaulted != nil {
+ t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted)
+ }
+ if pb.F_StringDefaulted != nil {
+ t.Error("New or Reset did not set string:", *pb.F_StringDefaulted)
+ }
+ if pb.F_BytesDefaulted != nil {
+ t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted))
+ }
+ if pb.F_Sint32Defaulted != nil {
+ t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted)
+ }
+ if pb.F_Sint64Defaulted != nil {
+ t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted)
+ }
+}
+
+// Does Reset() reset?
+func TestReset(t *testing.T) {
+ pb := initGoTest(true)
+ // muck with some values
+ pb.F_BoolDefaulted = Bool(false)
+ pb.F_Int32Defaulted = Int32(237)
+ pb.F_Int64Defaulted = Int64(12346)
+ pb.F_Fixed32Defaulted = Uint32(32000)
+ pb.F_Fixed64Defaulted = Uint64(666)
+ pb.F_Uint32Defaulted = Uint32(323232)
+ pb.F_Uint64Defaulted = nil
+ pb.F_FloatDefaulted = nil
+ pb.F_DoubleDefaulted = Float64(0)
+ pb.F_StringDefaulted = String("gotcha")
+ pb.F_BytesDefaulted = []byte("asdfasdf")
+ pb.F_Sint32Defaulted = Int32(123)
+ pb.F_Sint64Defaulted = Int64(789)
+ pb.Reset()
+ checkInitialized(pb, t)
+}
+
+// All required fields set, no defaults provided.
+func TestEncodeDecode1(t *testing.T) {
+ pb := initGoTest(false)
+ overify(t, pb,
+ "0807"+ // field 1, encoding 0, value 7
+ "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField)
+ "5001"+ // field 10, encoding 0, value 1
+ "5803"+ // field 11, encoding 0, value 3
+ "6006"+ // field 12, encoding 0, value 6
+ "6d20000000"+ // field 13, encoding 5, value 0x20
+ "714000000000000000"+ // field 14, encoding 1, value 0x40
+ "78a019"+ // field 15, encoding 0, value 0xca0 = 3232
+ "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464
+ "8d0100004a45"+ // field 17, encoding 5, value 3232.0
+ "9101000000000040b940"+ // field 18, encoding 1, value 6464.0
+ "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string"
+ "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes"
+ "b0063f"+ // field 102, encoding 0, 0x3f zigzag32
+ "b8067f"+ // field 103, encoding 0, 0x7f zigzag64
+ "b304"+ // field 70, encoding 3, start group
+ "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required"
+ "b404") // field 70, encoding 4, end group
+}
+
+// All required fields set, defaults provided.
+func TestEncodeDecode2(t *testing.T) {
+ pb := initGoTest(true)
+ overify(t, pb,
+ "0807"+ // field 1, encoding 0, value 7
+ "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField)
+ "5001"+ // field 10, encoding 0, value 1
+ "5803"+ // field 11, encoding 0, value 3
+ "6006"+ // field 12, encoding 0, value 6
+ "6d20000000"+ // field 13, encoding 5, value 32
+ "714000000000000000"+ // field 14, encoding 1, value 64
+ "78a019"+ // field 15, encoding 0, value 3232
+ "8001c032"+ // field 16, encoding 0, value 6464
+ "8d0100004a45"+ // field 17, encoding 5, value 3232.0
+ "9101000000000040b940"+ // field 18, encoding 1, value 6464.0
+ "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string"
+ "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
+ "b0063f"+ // field 102, encoding 0, 0x3f zigzag32
+ "b8067f"+ // field 103, encoding 0, 0x7f zigzag64
+ "c00201"+ // field 40, encoding 0, value 1
+ "c80220"+ // field 41, encoding 0, value 32
+ "d00240"+ // field 42, encoding 0, value 64
+ "dd0240010000"+ // field 43, encoding 5, value 320
+ "e1028002000000000000"+ // field 44, encoding 1, value 640
+ "e8028019"+ // field 45, encoding 0, value 3200
+ "f0028032"+ // field 46, encoding 0, value 6400
+ "fd02e0659948"+ // field 47, encoding 5, value 314159.0
+ "81030000000050971041"+ // field 48, encoding 1, value 271828.0
+ "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n"
+ "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
+ "90193f"+ // field 402, encoding 0, value 63
+ "98197f"+ // field 403, encoding 0, value 127
+ "b304"+ // start group field 70 level 1
+ "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required"
+ "b404") // end group field 70 level 1
+
+}
+
+// All default fields set to their default value by hand
+func TestEncodeDecode3(t *testing.T) {
+ pb := initGoTest(false)
+ pb.F_BoolDefaulted = Bool(true)
+ pb.F_Int32Defaulted = Int32(32)
+ pb.F_Int64Defaulted = Int64(64)
+ pb.F_Fixed32Defaulted = Uint32(320)
+ pb.F_Fixed64Defaulted = Uint64(640)
+ pb.F_Uint32Defaulted = Uint32(3200)
+ pb.F_Uint64Defaulted = Uint64(6400)
+ pb.F_FloatDefaulted = Float32(314159)
+ pb.F_DoubleDefaulted = Float64(271828)
+ pb.F_StringDefaulted = String("hello, \"world!\"\n")
+ pb.F_BytesDefaulted = []byte("Bignose")
+ pb.F_Sint32Defaulted = Int32(-32)
+ pb.F_Sint64Defaulted = Int64(-64)
+
+ overify(t, pb,
+ "0807"+ // field 1, encoding 0, value 7
+ "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField)
+ "5001"+ // field 10, encoding 0, value 1
+ "5803"+ // field 11, encoding 0, value 3
+ "6006"+ // field 12, encoding 0, value 6
+ "6d20000000"+ // field 13, encoding 5, value 32
+ "714000000000000000"+ // field 14, encoding 1, value 64
+ "78a019"+ // field 15, encoding 0, value 3232
+ "8001c032"+ // field 16, encoding 0, value 6464
+ "8d0100004a45"+ // field 17, encoding 5, value 3232.0
+ "9101000000000040b940"+ // field 18, encoding 1, value 6464.0
+ "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string"
+ "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
+ "b0063f"+ // field 102, encoding 0, 0x3f zigzag32
+ "b8067f"+ // field 103, encoding 0, 0x7f zigzag64
+ "c00201"+ // field 40, encoding 0, value 1
+ "c80220"+ // field 41, encoding 0, value 32
+ "d00240"+ // field 42, encoding 0, value 64
+ "dd0240010000"+ // field 43, encoding 5, value 320
+ "e1028002000000000000"+ // field 44, encoding 1, value 640
+ "e8028019"+ // field 45, encoding 0, value 3200
+ "f0028032"+ // field 46, encoding 0, value 6400
+ "fd02e0659948"+ // field 47, encoding 5, value 314159.0
+ "81030000000050971041"+ // field 48, encoding 1, value 271828.0
+ "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n"
+ "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
+ "90193f"+ // field 402, encoding 0, value 63
+ "98197f"+ // field 403, encoding 0, value 127
+ "b304"+ // start group field 70 level 1
+ "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required"
+ "b404") // end group field 70 level 1
+
+}
+
+// All required fields set, defaults provided, all non-defaulted optional fields have values.
+func TestEncodeDecode4(t *testing.T) {
+ pb := initGoTest(true)
+ pb.Table = String("hello")
+ pb.Param = Int32(7)
+ pb.OptionalField = initGoTestField()
+ pb.F_BoolOptional = Bool(true)
+ pb.F_Int32Optional = Int32(32)
+ pb.F_Int64Optional = Int64(64)
+ pb.F_Fixed32Optional = Uint32(3232)
+ pb.F_Fixed64Optional = Uint64(6464)
+ pb.F_Uint32Optional = Uint32(323232)
+ pb.F_Uint64Optional = Uint64(646464)
+ pb.F_FloatOptional = Float32(32.)
+ pb.F_DoubleOptional = Float64(64.)
+ pb.F_StringOptional = String("hello")
+ pb.F_BytesOptional = []byte("Bignose")
+ pb.F_Sint32Optional = Int32(-32)
+ pb.F_Sint64Optional = Int64(-64)
+ pb.Optionalgroup = initGoTest_OptionalGroup()
+
+ overify(t, pb,
+ "0807"+ // field 1, encoding 0, value 7
+ "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello"
+ "1807"+ // field 3, encoding 0, value 7
+ "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField)
+ "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField)
+ "5001"+ // field 10, encoding 0, value 1
+ "5803"+ // field 11, encoding 0, value 3
+ "6006"+ // field 12, encoding 0, value 6
+ "6d20000000"+ // field 13, encoding 5, value 32
+ "714000000000000000"+ // field 14, encoding 1, value 64
+ "78a019"+ // field 15, encoding 0, value 3232
+ "8001c032"+ // field 16, encoding 0, value 6464
+ "8d0100004a45"+ // field 17, encoding 5, value 3232.0
+ "9101000000000040b940"+ // field 18, encoding 1, value 6464.0
+ "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string"
+ "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
+ "b0063f"+ // field 102, encoding 0, 0x3f zigzag32
+ "b8067f"+ // field 103, encoding 0, 0x7f zigzag64
+ "f00101"+ // field 30, encoding 0, value 1
+ "f80120"+ // field 31, encoding 0, value 32
+ "800240"+ // field 32, encoding 0, value 64
+ "8d02a00c0000"+ // field 33, encoding 5, value 3232
+ "91024019000000000000"+ // field 34, encoding 1, value 6464
+ "9802a0dd13"+ // field 35, encoding 0, value 323232
+ "a002c0ba27"+ // field 36, encoding 0, value 646464
+ "ad0200000042"+ // field 37, encoding 5, value 32.0
+ "b1020000000000005040"+ // field 38, encoding 1, value 64.0
+ "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello"
+ "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose"
+ "f0123f"+ // field 302, encoding 0, value 63
+ "f8127f"+ // field 303, encoding 0, value 127
+ "c00201"+ // field 40, encoding 0, value 1
+ "c80220"+ // field 41, encoding 0, value 32
+ "d00240"+ // field 42, encoding 0, value 64
+ "dd0240010000"+ // field 43, encoding 5, value 320
+ "e1028002000000000000"+ // field 44, encoding 1, value 640
+ "e8028019"+ // field 45, encoding 0, value 3200
+ "f0028032"+ // field 46, encoding 0, value 6400
+ "fd02e0659948"+ // field 47, encoding 5, value 314159.0
+ "81030000000050971041"+ // field 48, encoding 1, value 271828.0
+ "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n"
+ "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
+ "90193f"+ // field 402, encoding 0, value 63
+ "98197f"+ // field 403, encoding 0, value 127
+ "b304"+ // start group field 70 level 1
+ "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required"
+ "b404"+ // end group field 70 level 1
+ "d305"+ // start group field 90 level 1
+ "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional"
+ "d405") // end group field 90 level 1
+
+}
+
+// All required fields set, defaults provided, all repeated fields given two values.
+func TestEncodeDecode5(t *testing.T) {
+ pb := initGoTest(true)
+ pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()}
+ pb.F_BoolRepeated = []bool{false, true}
+ pb.F_Int32Repeated = []int32{32, 33}
+ pb.F_Int64Repeated = []int64{64, 65}
+ pb.F_Fixed32Repeated = []uint32{3232, 3333}
+ pb.F_Fixed64Repeated = []uint64{6464, 6565}
+ pb.F_Uint32Repeated = []uint32{323232, 333333}
+ pb.F_Uint64Repeated = []uint64{646464, 656565}
+ pb.F_FloatRepeated = []float32{32., 33.}
+ pb.F_DoubleRepeated = []float64{64., 65.}
+ pb.F_StringRepeated = []string{"hello", "sailor"}
+ pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")}
+ pb.F_Sint32Repeated = []int32{32, -32}
+ pb.F_Sint64Repeated = []int64{64, -64}
+ pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()}
+
+ overify(t, pb,
+ "0807"+ // field 1, encoding 0, value 7
+ "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField)
+ "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField)
+ "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField)
+ "5001"+ // field 10, encoding 0, value 1
+ "5803"+ // field 11, encoding 0, value 3
+ "6006"+ // field 12, encoding 0, value 6
+ "6d20000000"+ // field 13, encoding 5, value 32
+ "714000000000000000"+ // field 14, encoding 1, value 64
+ "78a019"+ // field 15, encoding 0, value 3232
+ "8001c032"+ // field 16, encoding 0, value 6464
+ "8d0100004a45"+ // field 17, encoding 5, value 3232.0
+ "9101000000000040b940"+ // field 18, encoding 1, value 6464.0
+ "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string"
+ "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
+ "b0063f"+ // field 102, encoding 0, 0x3f zigzag32
+ "b8067f"+ // field 103, encoding 0, 0x7f zigzag64
+ "a00100"+ // field 20, encoding 0, value 0
+ "a00101"+ // field 20, encoding 0, value 1
+ "a80120"+ // field 21, encoding 0, value 32
+ "a80121"+ // field 21, encoding 0, value 33
+ "b00140"+ // field 22, encoding 0, value 64
+ "b00141"+ // field 22, encoding 0, value 65
+ "bd01a00c0000"+ // field 23, encoding 5, value 3232
+ "bd01050d0000"+ // field 23, encoding 5, value 3333
+ "c1014019000000000000"+ // field 24, encoding 1, value 6464
+ "c101a519000000000000"+ // field 24, encoding 1, value 6565
+ "c801a0dd13"+ // field 25, encoding 0, value 323232
+ "c80195ac14"+ // field 25, encoding 0, value 333333
+ "d001c0ba27"+ // field 26, encoding 0, value 646464
+ "d001b58928"+ // field 26, encoding 0, value 656565
+ "dd0100000042"+ // field 27, encoding 5, value 32.0
+ "dd0100000442"+ // field 27, encoding 5, value 33.0
+ "e1010000000000005040"+ // field 28, encoding 1, value 64.0
+ "e1010000000000405040"+ // field 28, encoding 1, value 65.0
+ "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello"
+ "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor"
+ "ca0c03"+"626967"+ // field 201, encoding 2, string "big"
+ "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose"
+ "d00c40"+ // field 202, encoding 0, value 32
+ "d00c3f"+ // field 202, encoding 0, value -32
+ "d80c8001"+ // field 203, encoding 0, value 64
+ "d80c7f"+ // field 203, encoding 0, value -64
+ "c00201"+ // field 40, encoding 0, value 1
+ "c80220"+ // field 41, encoding 0, value 32
+ "d00240"+ // field 42, encoding 0, value 64
+ "dd0240010000"+ // field 43, encoding 5, value 320
+ "e1028002000000000000"+ // field 44, encoding 1, value 640
+ "e8028019"+ // field 45, encoding 0, value 3200
+ "f0028032"+ // field 46, encoding 0, value 6400
+ "fd02e0659948"+ // field 47, encoding 5, value 314159.0
+ "81030000000050971041"+ // field 48, encoding 1, value 271828.0
+ "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n"
+ "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
+ "90193f"+ // field 402, encoding 0, value 63
+ "98197f"+ // field 403, encoding 0, value 127
+ "b304"+ // start group field 70 level 1
+ "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required"
+ "b404"+ // end group field 70 level 1
+ "8305"+ // start group field 80 level 1
+ "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated"
+ "8405"+ // end group field 80 level 1
+ "8305"+ // start group field 80 level 1
+ "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated"
+ "8405") // end group field 80 level 1
+
+}
+
+// All required fields set, all packed repeated fields given two values.
+func TestEncodeDecode6(t *testing.T) {
+ pb := initGoTest(false)
+ pb.F_BoolRepeatedPacked = []bool{false, true}
+ pb.F_Int32RepeatedPacked = []int32{32, 33}
+ pb.F_Int64RepeatedPacked = []int64{64, 65}
+ pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333}
+ pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565}
+ pb.F_Uint32RepeatedPacked = []uint32{323232, 333333}
+ pb.F_Uint64RepeatedPacked = []uint64{646464, 656565}
+ pb.F_FloatRepeatedPacked = []float32{32., 33.}
+ pb.F_DoubleRepeatedPacked = []float64{64., 65.}
+ pb.F_Sint32RepeatedPacked = []int32{32, -32}
+ pb.F_Sint64RepeatedPacked = []int64{64, -64}
+
+ overify(t, pb,
+ "0807"+ // field 1, encoding 0, value 7
+ "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField)
+ "5001"+ // field 10, encoding 0, value 1
+ "5803"+ // field 11, encoding 0, value 3
+ "6006"+ // field 12, encoding 0, value 6
+ "6d20000000"+ // field 13, encoding 5, value 32
+ "714000000000000000"+ // field 14, encoding 1, value 64
+ "78a019"+ // field 15, encoding 0, value 3232
+ "8001c032"+ // field 16, encoding 0, value 6464
+ "8d0100004a45"+ // field 17, encoding 5, value 3232.0
+ "9101000000000040b940"+ // field 18, encoding 1, value 6464.0
+ "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string"
+ "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
+ "b0063f"+ // field 102, encoding 0, 0x3f zigzag32
+ "b8067f"+ // field 103, encoding 0, 0x7f zigzag64
+ "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1
+ "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33
+ "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65
+ "aa0308"+ // field 53, encoding 2, 8 bytes
+ "a00c0000050d0000"+ // value 3232, value 3333
+ "b20310"+ // field 54, encoding 2, 16 bytes
+ "4019000000000000a519000000000000"+ // value 6464, value 6565
+ "ba0306"+ // field 55, encoding 2, 6 bytes
+ "a0dd1395ac14"+ // value 323232, value 333333
+ "c20306"+ // field 56, encoding 2, 6 bytes
+ "c0ba27b58928"+ // value 646464, value 656565
+ "ca0308"+ // field 57, encoding 2, 8 bytes
+ "0000004200000442"+ // value 32.0, value 33.0
+ "d20310"+ // field 58, encoding 2, 16 bytes
+ "00000000000050400000000000405040"+ // value 64.0, value 65.0
+ "b21f02"+ // field 502, encoding 2, 2 bytes
+ "403f"+ // value 32, value -32
+ "ba1f03"+ // field 503, encoding 2, 3 bytes
+ "80017f"+ // value 64, value -64
+ "b304"+ // start group field 70 level 1
+ "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required"
+ "b404") // end group field 70 level 1
+}
+
+// Test that we can encode empty bytes fields.
+func TestEncodeDecodeBytes1(t *testing.T) {
+ pb := initGoTest(false)
+
+ // Create our bytes
+ pb.F_BytesRequired = []byte{}
+ pb.F_BytesRepeated = [][]byte{{}}
+ pb.F_BytesOptional = []byte{}
+
+ d, err := Marshal(pb)
+ if err != nil {
+ t.Errorf(err.String())
+ }
+
+ pbd := new(GoTest)
+ if err := Unmarshal(d, pbd); err != nil {
+ t.Errorf(err.String())
+ }
+
+ if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 {
+ t.Errorf("required empty bytes field is incorrect")
+ }
+ if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil {
+ t.Errorf("repeated empty bytes field is incorrect")
+ }
+ if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 {
+ t.Errorf("optional empty bytes field is incorrect")
+ }
+}
+
+// Test that we encode nil-valued fields of a repeated bytes field correctly.
+// Since entries in a repeated field cannot be nil, nil must mean empty value.
+func TestEncodeDecodeBytes2(t *testing.T) {
+ pb := initGoTest(false)
+
+ // Create our bytes
+ pb.F_BytesRepeated = [][]byte{nil}
+
+ d, err := Marshal(pb)
+ if err != nil {
+ t.Errorf(err.String())
+ }
+
+ pbd := new(GoTest)
+ if err := Unmarshal(d, pbd); err != nil {
+ t.Errorf(err.String())
+ }
+
+ if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil {
+ t.Errorf("Unexpected value for repeated bytes field")
+ }
+}
+
+// All required fields set, defaults provided, all repeated fields given two values.
+func TestSkippingUnrecognizedFields(t *testing.T) {
+ o := old()
+ pb := initGoTestField()
+
+ // Marshal it normally.
+ o.Marshal(pb)
+
+ // Now new a GoSkipTest record.
+ skip := &GoSkipTest{
+ SkipInt32: Int32(32),
+ SkipFixed32: Uint32(3232),
+ SkipFixed64: Uint64(6464),
+ SkipString: String("skipper"),
+ Skipgroup: &GoSkipTest_SkipGroup{
+ GroupInt32: Int32(75),
+ GroupString: String("wxyz"),
+ },
+ }
+
+ // Marshal it into same buffer.
+ o.Marshal(skip)
+
+ pbd := new(GoTestField)
+ o.Unmarshal(pbd)
+
+ // The __unrecognized field should be a marshaling of GoSkipTest
+ skipd := new(GoSkipTest)
+
+ o.SetBuf(pbd.XXX_unrecognized)
+ o.Unmarshal(skipd)
+
+ if *skipd.SkipInt32 != *skip.SkipInt32 {
+ t.Error("skip int32", skipd.SkipInt32)
+ }
+ if *skipd.SkipFixed32 != *skip.SkipFixed32 {
+ t.Error("skip fixed32", skipd.SkipFixed32)
+ }
+ if *skipd.SkipFixed64 != *skip.SkipFixed64 {
+ t.Error("skip fixed64", skipd.SkipFixed64)
+ }
+ if *skipd.SkipString != *skip.SkipString {
+ t.Error("skip string", *skipd.SkipString)
+ }
+ if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 {
+ t.Error("skip group int32", skipd.Skipgroup.GroupInt32)
+ }
+ if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString {
+ t.Error("skip group string", *skipd.Skipgroup.GroupString)
+ }
+}
+
+// Check that we can grow an array (repeated field) to have many elements.
+// This test doesn't depend only on our encoding; for variety, it makes sure
+// we create, encode, and decode the correct contents explicitly. It's therefore
+// a bit messier.
+// This test also uses (and hence tests) the Marshal/Unmarshal functions
+// instead of the methods.
+func TestBigRepeated(t *testing.T) {
+ pb := initGoTest(true)
+
+ // Create the arrays
+ const N = 50 // Internally the library starts much smaller.
+ pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N)
+ pb.F_Sint64Repeated = make([]int64, N)
+ pb.F_Sint32Repeated = make([]int32, N)
+ pb.F_BytesRepeated = make([][]byte, N)
+ pb.F_StringRepeated = make([]string, N)
+ pb.F_DoubleRepeated = make([]float64, N)
+ pb.F_FloatRepeated = make([]float32, N)
+ pb.F_Uint64Repeated = make([]uint64, N)
+ pb.F_Uint32Repeated = make([]uint32, N)
+ pb.F_Fixed64Repeated = make([]uint64, N)
+ pb.F_Fixed32Repeated = make([]uint32, N)
+ pb.F_Int64Repeated = make([]int64, N)
+ pb.F_Int32Repeated = make([]int32, N)
+ pb.F_BoolRepeated = make([]bool, N)
+ pb.RepeatedField = make([]*GoTestField, N)
+
+ // Fill in the arrays with checkable values.
+ igtf := initGoTestField()
+ igtrg := initGoTest_RepeatedGroup()
+ for i := 0; i < N; i++ {
+ pb.Repeatedgroup[i] = igtrg
+ pb.F_Sint64Repeated[i] = int64(i)
+ pb.F_Sint32Repeated[i] = int32(i)
+ s := fmt.Sprint(i)
+ pb.F_BytesRepeated[i] = []byte(s)
+ pb.F_StringRepeated[i] = s
+ pb.F_DoubleRepeated[i] = float64(i)
+ pb.F_FloatRepeated[i] = float32(i)
+ pb.F_Uint64Repeated[i] = uint64(i)
+ pb.F_Uint32Repeated[i] = uint32(i)
+ pb.F_Fixed64Repeated[i] = uint64(i)
+ pb.F_Fixed32Repeated[i] = uint32(i)
+ pb.F_Int64Repeated[i] = int64(i)
+ pb.F_Int32Repeated[i] = int32(i)
+ pb.F_BoolRepeated[i] = i%2 == 0
+ pb.RepeatedField[i] = igtf
+ }
+
+ // Marshal.
+ buf, _ := Marshal(pb)
+
+ // Now test Unmarshal by recreating the original buffer.
+ pbd := new(GoTest)
+ Unmarshal(buf, pbd)
+
+ // Check the checkable values
+ for i := uint64(0); i < N; i++ {
+ if pbd.Repeatedgroup[i] == nil { // TODO: more checking?
+ t.Error("pbd.Repeatedgroup bad")
+ }
+ var x uint64
+ x = uint64(pbd.F_Sint64Repeated[i])
+ if x != i {
+ t.Error("pbd.F_Sint64Repeated bad", x, i)
+ }
+ x = uint64(pbd.F_Sint32Repeated[i])
+ if x != i {
+ t.Error("pbd.F_Sint32Repeated bad", x, i)
+ }
+ s := fmt.Sprint(i)
+ equalbytes(pbd.F_BytesRepeated[i], []byte(s), t)
+ if pbd.F_StringRepeated[i] != s {
+ t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i)
+ }
+ x = uint64(pbd.F_DoubleRepeated[i])
+ if x != i {
+ t.Error("pbd.F_DoubleRepeated bad", x, i)
+ }
+ x = uint64(pbd.F_FloatRepeated[i])
+ if x != i {
+ t.Error("pbd.F_FloatRepeated bad", x, i)
+ }
+ x = pbd.F_Uint64Repeated[i]
+ if x != i {
+ t.Error("pbd.F_Uint64Repeated bad", x, i)
+ }
+ x = uint64(pbd.F_Uint32Repeated[i])
+ if x != i {
+ t.Error("pbd.F_Uint32Repeated bad", x, i)
+ }
+ x = pbd.F_Fixed64Repeated[i]
+ if x != i {
+ t.Error("pbd.F_Fixed64Repeated bad", x, i)
+ }
+ x = uint64(pbd.F_Fixed32Repeated[i])
+ if x != i {
+ t.Error("pbd.F_Fixed32Repeated bad", x, i)
+ }
+ x = uint64(pbd.F_Int64Repeated[i])
+ if x != i {
+ t.Error("pbd.F_Int64Repeated bad", x, i)
+ }
+ x = uint64(pbd.F_Int32Repeated[i])
+ if x != i {
+ t.Error("pbd.F_Int32Repeated bad", x, i)
+ }
+ if pbd.F_BoolRepeated[i] != (i%2 == 0) {
+ t.Error("pbd.F_BoolRepeated bad", x, i)
+ }
+ if pbd.RepeatedField[i] == nil { // TODO: more checking?
+ t.Error("pbd.RepeatedField bad")
+ }
+ }
+}
+
+// Verify we give a useful message when decoding to the wrong structure type.
+func TestTypeMismatch(t *testing.T) {
+ pb1 := initGoTest(true)
+
+ // Marshal
+ o := old()
+ o.Marshal(pb1)
+
+ // Now Unmarshal it to the wrong type.
+ pb2 := initGoTestField()
+ err := o.Unmarshal(pb2)
+ switch err {
+ case ErrWrongType:
+ // fine
+ case nil:
+ t.Error("expected wrong type error, got no error")
+ default:
+ t.Error("expected wrong type error, got", err)
+ }
+}
+
+func encodeDecode(t *testing.T, in, out interface{}, msg string) {
+ buf, err := Marshal(in)
+ if err != nil {
+ t.Fatalf("failed marshaling %v: %v", msg, err)
+ }
+ if err := Unmarshal(buf, out); err != nil {
+ t.Fatalf("failed unmarshaling %v: %v", msg, err)
+ }
+}
+
+func TestPackedNonPackedDecoderSwitching(t *testing.T) {
+ np, p := new(NonPackedTest), new(PackedTest)
+
+ // non-packed -> packed
+ np.A = []int32{0, 1, 1, 2, 3, 5}
+ encodeDecode(t, np, p, "non-packed -> packed")
+ if !reflect.DeepEqual(np.A, p.B) {
+ t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B)
+ }
+
+ // packed -> non-packed
+ np.Reset()
+ p.B = []int32{3, 1, 4, 1, 5, 9}
+ encodeDecode(t, p, np, "packed -> non-packed")
+ if !reflect.DeepEqual(p.B, np.A) {
+ t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A)
+ }
+}
+
+func TestProto1RepeatedGroup(t *testing.T) {
+ pb := &MessageList{
+ Message: []*MessageList_Message{
+ &MessageList_Message{
+ Name: String("blah"),
+ Count: Int32(7),
+ },
+ // NOTE: pb.Message[1] is a nil
+ nil,
+ },
+ }
+
+ o := old()
+ if err := o.Marshal(pb); err != ErrRepeatedHasNil {
+ t.Fatalf("unexpected or no error when marshaling: %v", err)
+ }
+}
+
+
+// Test that enums work. Checks for a bug introduced by making enums
+// named types instead of int32: newInt32FromUint64 would crash with
+// a type mismatch in reflect.PointTo.
+func TestEnum(t *testing.T) {
+ pb := new(GoEnum)
+ pb.Foo = NewFOO(FOO_FOO1)
+ o := old()
+ if err := o.Marshal(pb); err != nil {
+ t.Fatal("error encoding enum:", err)
+ }
+ pb1 := new(GoEnum)
+ if err := o.Unmarshal(pb1); err != nil {
+ t.Fatal("error decoding enum:", err)
+ }
+ if *pb1.Foo != FOO_FOO1 {
+ t.Error("expected 7 but got ", *pb1.Foo)
+ }
+}
+
+// Enum types have String methods. Check that enum fields can be printed.
+// We don't care what the value actually is, just as long as it doesn't crash.
+func TestPrintingNilEnumFields(t *testing.T) {
+ pb := new(GoEnum)
+ fmt.Sprintf("%+v", pb)
+}
+
+// Verify that absent required fields cause Marshal/Unmarshal to return errors.
+func TestRequiredFieldEnforcement(t *testing.T) {
+ pb := new(GoTestField)
+ _, err := Marshal(pb)
+ if err == nil {
+ t.Error("marshal: expected error, got nil")
+ } else if strings.Index(err.String(), "GoTestField") < 0 {
+ t.Errorf("marshal: bad error type: %v", err)
+ }
+
+ // A slightly sneaky, yet valid, proto. It encodes the same required field twice,
+ // so simply counting the required fields is insufficient.
+ // field 1, encoding 2, value "hi"
+ buf := []byte("\x0A\x02hi\x0A\x02hi")
+ err = Unmarshal(buf, pb)
+ if err == nil {
+ t.Error("unmarshal: expected error, got nil")
+ } else if strings.Index(err.String(), "GoTestField") < 0 {
+ t.Errorf("unmarshal: bad error type: %v", err)
+ }
+}
+
+// A type that implements the Marshaler interface, but is not nillable.
+type nonNillableInt uint64
+
+func (nni nonNillableInt) Marshal() ([]byte, os.Error) {
+ return EncodeVarint(uint64(nni)), nil
+}
+
+type NNIMessage struct {
+ nni nonNillableInt
+}
+
+// A type that implements the Marshaler interface and is nillable.
+type nillableMessage struct {
+ x uint64
+}
+
+func (nm *nillableMessage) Marshal() ([]byte, os.Error) {
+ return EncodeVarint(nm.x), nil
+}
+
+type NMMessage struct {
+ nm *nillableMessage
+}
+
+// Verify a type that uses the Marshaler interface, but has a nil pointer.
+func TestNilMarshaler(t *testing.T) {
+ // Try a struct with a Marshaler field that is nil.
+ // It should be directly marshable.
+ nmm := new(NMMessage)
+ if _, err := Marshal(nmm); err != nil {
+ t.Error("unexpected error marshaling nmm: ", err)
+ }
+
+ // Try a struct with a Marshaler field that is not nillable.
+ nnim := new(NNIMessage)
+ nnim.nni = 7
+ var _ Marshaler = nnim.nni // verify it is truly a Marshaler
+ if _, err := Marshal(nnim); err != nil {
+ t.Error("unexpected error marshaling nnim: ", err)
+ }
+}
+
+// Check that passing a struct to Marshal returns a good error,
+// rather than panicking.
+func TestStructMarshaling(t *testing.T) {
+ _, err := Marshal(OtherMessage{})
+ if err != ErrNotPtr {
+ t.Errorf("got %v, expected %v", err, ErrNotPtr)
+ }
+}
+
+func TestAllSetDefaults(t *testing.T) {
+ // Exercise SetDefaults with all scalar field types.
+ m := &Defaults{
+ // NaN != NaN, so override that here.
+ F_Nan: Float32(1.7),
+ }
+ expected := &Defaults{
+ F_Bool: Bool(true),
+ F_Int32: Int32(32),
+ F_Int64: Int64(64),
+ F_Fixed32: Uint32(320),
+ F_Fixed64: Uint64(640),
+ F_Uint32: Uint32(3200),
+ F_Uint64: Uint64(6400),
+ F_Float: Float32(314159),
+ F_Double: Float64(271828),
+ F_String: String(`hello, "world!"` + "\n"),
+ F_Bytes: []byte("Bignose"),
+ F_Sint32: Int32(-32),
+ F_Sint64: Int64(-64),
+ F_Enum: NewDefaults_Color(Defaults_GREEN),
+ F_Pinf: Float32(float32(math.Inf(1))),
+ F_Ninf: Float32(float32(math.Inf(-1))),
+ F_Nan: Float32(1.7),
+ }
+ SetDefaults(m)
+ if !Equal(m, expected) {
+ t.Errorf(" got %v\nwant %v", m, expected)
+ }
+}
+
+func TestSetDefaultsWithSetField(t *testing.T) {
+ // Check that a set value is not overridden.
+ m := &Defaults{
+ F_Int32: Int32(12),
+ }
+ SetDefaults(m)
+ if v := GetInt32(m.F_Int32); v != 12 {
+ t.Errorf("m.FInt32 = %v, want 12", v)
+ }
+}
+
+func TestSetDefaultsWithSubMessage(t *testing.T) {
+ m := &OtherMessage{
+ Key: Int64(123),
+ Inner: &InnerMessage{
+ Host: String("gopher"),
+ },
+ }
+ expected := &OtherMessage{
+ Key: Int64(123),
+ Inner: &InnerMessage{
+ Host: String("gopher"),
+ Port: Int32(4000),
+ },
+ }
+ SetDefaults(m)
+ if !Equal(m, expected) {
+ t.Errorf(" got %v\nwant %v", m, expected)
+ }
+}
+
+func TestMaximumTagNumber(t *testing.T) {
+ m := &MaxTag{
+ LastField: String("natural goat essence"),
+ }
+ buf, err := Marshal(m)
+ if err != nil {
+ t.Fatalf("proto.Marshal failed: %v", err)
+ }
+ m2 := new(MaxTag)
+ if err := Unmarshal(buf, m2); err != nil {
+ t.Fatalf("proto.Unmarshal failed: %v", err)
+ }
+ if got, want := GetString(m2.LastField), *m.LastField; got != want {
+ t.Errorf("got %q, want %q", got, want)
+ }
+}
+
+func TestJSON(t *testing.T) {
+ m := &MyMessage{
+ Count: Int32(4),
+ Pet: []string{"bunny", "kitty"},
+ Inner: &InnerMessage{
+ Host: String("cauchy"),
+ },
+ }
+ const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"}}`
+
+ b, err := json.Marshal(m)
+ if err != nil {
+ t.Fatalf("json.Marshal failed: %v", err)
+ }
+ s := string(b)
+ if s != expected {
+ t.Errorf("got %s\nwant %s", s, expected)
+ }
+}
+
+func BenchmarkMarshal(b *testing.B) {
+ b.StopTimer()
+
+ pb := initGoTest(true)
+
+ // Create an array
+ const N = 1000 // Internally the library starts much smaller.
+ pb.F_Int32Repeated = make([]int32, N)
+ pb.F_DoubleRepeated = make([]float64, N)
+
+ // Fill in the array with some values.
+ for i := 0; i < N; i++ {
+ pb.F_Int32Repeated[i] = int32(i)
+ pb.F_DoubleRepeated[i] = float64(i)
+ }
+
+ p := NewBuffer(nil)
+
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ p.Reset()
+ p.Marshal(pb)
+ }
+}
+
+func BenchmarkUnmarshal(b *testing.B) {
+ b.StopTimer()
+
+ pb := initGoTest(true)
+
+ // Create an array
+ const N = 1000 // Internally the library starts much smaller.
+ pb.F_Int32Repeated = make([]int32, N)
+
+ // Fill in the array with some values.
+ for i := 0; i < N; i++ {
+ pb.F_Int32Repeated[i] = int32(i)
+ }
+ pbd := new(GoTest)
+ p := NewBuffer(nil)
+ p.Marshal(pb)
+ p2 := NewBuffer(nil)
+
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ p2.SetBuf(p.Bytes())
+ p2.Unmarshal(pbd)
+ }
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 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.
+
+// Protocol buffer deep copy.
+// TODO: MessageSet and RawMessage.
+
+package proto
+
+import (
+ "log"
+ "reflect"
+ "strings"
+)
+
+// Clone returns a deep copy of a protocol buffer.
+// pb must be a pointer to a protocol buffer struct.
+func Clone(pb interface{}) interface{} {
+ in := reflect.ValueOf(pb)
+ if in.Kind() != reflect.Ptr || in.Elem().Kind() != reflect.Struct {
+ return nil
+ }
+
+ out := reflect.New(in.Type().Elem())
+ copyStruct(out.Elem(), in.Elem())
+ return out.Interface()
+}
+
+func copyStruct(out, in reflect.Value) {
+ for i := 0; i < in.NumField(); i++ {
+ f := in.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ copyAny(out.Field(i), in.Field(i))
+ }
+
+ if emIn, ok := in.Addr().Interface().(extendableProto); ok {
+ emOut := out.Addr().Interface().(extendableProto)
+ copyExtension(emOut.ExtensionMap(), emIn.ExtensionMap())
+ }
+
+ // TODO: Deal with XXX_unrecognized.
+}
+
+func copyAny(out, in reflect.Value) {
+ switch in.Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64:
+ out.Set(in)
+ case reflect.Ptr:
+ if in.IsNil() {
+ return
+ }
+ out.Set(reflect.New(in.Type().Elem()))
+ copyAny(out.Elem(), in.Elem())
+ case reflect.Slice:
+ if in.IsNil() {
+ return
+ }
+ n := in.Len()
+ out.Set(reflect.MakeSlice(in.Type(), n, n))
+ switch in.Type().Elem().Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64, reflect.Uint8:
+ reflect.Copy(out, in)
+ default:
+ for i := 0; i < n; i++ {
+ copyAny(out.Index(i), in.Index(i))
+ }
+ }
+ case reflect.Struct:
+ copyStruct(out, in)
+ default:
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to copy %v", in)
+ }
+}
+
+func copyExtension(out, in map[int32]Extension) {
+ for extNum, eIn := range in {
+ eOut := Extension{desc: eIn.desc}
+ if eIn.value != nil {
+ v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
+ copyAny(v, reflect.ValueOf(eIn.value))
+ eOut.value = v.Interface()
+ }
+ if eIn.enc != nil {
+ eOut.enc = make([]byte, len(eIn.enc))
+ copy(eOut.enc, eIn.enc)
+ }
+
+ out[extNum] = eOut
+ }
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 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.
+
+package proto_test
+
+import (
+ "log"
+ "testing"
+
+ "goprotobuf.googlecode.com/hg/proto"
+
+ pb "./testdata/_obj/test_proto"
+)
+
+var cloneTestMessage = &pb.MyMessage{
+ Count: proto.Int32(42),
+ Name: proto.String("Dave"),
+ Pet: []string{"bunny", "kitty", "horsey"},
+ Inner: &pb.InnerMessage{
+ Host: proto.String("niles"),
+ Port: proto.Int32(9099),
+ Connected: proto.Bool(true),
+ },
+ Others: []*pb.OtherMessage{
+ &pb.OtherMessage{
+ Value: []byte("some bytes"),
+ },
+ },
+ RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
+}
+
+func init() {
+ ext := &pb.Ext{
+ Data: proto.String("extension"),
+ }
+ if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
+ log.Fatalf("SetExtension: %v", err)
+ }
+}
+
+func TestClone(t *testing.T) {
+ m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
+ if !proto.Equal(m, cloneTestMessage) {
+ t.Errorf("Clone(%v) = %v", cloneTestMessage, m)
+ }
+
+ // Verify it was a deep copy.
+ *m.Inner.Port++
+ if proto.Equal(m, cloneTestMessage) {
+ t.Error("Mutating clone changed the original")
+ }
+}
--- /dev/null
+// 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.
+
+package proto
+
+/*
+ * Routines for decoding protocol buffer data to construct in-memory representations.
+ */
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+// ErrWrongType occurs when the wire encoding for the field disagrees with
+// that specified in the type being decoded. This is usually caused by attempting
+// to convert an encoded protocol buffer into a struct of the wrong type.
+var ErrWrongType = os.NewError("field/encoding mismatch: wrong type for field")
+
+// The fundamental decoders that interpret bytes on the wire.
+// Those that take integer types all return uint64 and are
+// therefore of type valueDecoder.
+
+// DecodeVarint reads a varint-encoded integer from the slice.
+// It returns the integer and the number of bytes consumed, or
+// zero if there is not enough.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func DecodeVarint(buf []byte) (x uint64, n int) {
+ // x, n already 0
+ for shift := uint(0); ; shift += 7 {
+ if n >= len(buf) {
+ return 0, 0
+ }
+ b := uint64(buf[n])
+ n++
+ x |= (b & 0x7F) << shift
+ if (b & 0x80) == 0 {
+ break
+ }
+ }
+ return x, n
+}
+
+// DecodeVarint reads a varint-encoded integer from the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) DecodeVarint() (x uint64, err os.Error) {
+ // x, err already 0
+
+ i := p.index
+ l := len(p.buf)
+
+ for shift := uint(0); ; shift += 7 {
+ if i >= l {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ b := p.buf[i]
+ i++
+ x |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ p.index = i
+ return
+}
+
+// DecodeFixed64 reads a 64-bit integer from the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) DecodeFixed64() (x uint64, err os.Error) {
+ // x, err already 0
+ i := p.index + 8
+ if i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-8])
+ x |= uint64(p.buf[i-7]) << 8
+ x |= uint64(p.buf[i-6]) << 16
+ x |= uint64(p.buf[i-5]) << 24
+ x |= uint64(p.buf[i-4]) << 32
+ x |= uint64(p.buf[i-3]) << 40
+ x |= uint64(p.buf[i-2]) << 48
+ x |= uint64(p.buf[i-1]) << 56
+ return
+}
+
+// DecodeFixed32 reads a 32-bit integer from the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) DecodeFixed32() (x uint64, err os.Error) {
+ // x, err already 0
+ i := p.index + 4
+ if i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-4])
+ x |= uint64(p.buf[i-3]) << 8
+ x |= uint64(p.buf[i-2]) << 16
+ x |= uint64(p.buf[i-1]) << 24
+ return
+}
+
+// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
+// from the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) DecodeZigzag64() (x uint64, err os.Error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
+ return
+}
+
+// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
+// from the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) DecodeZigzag32() (x uint64, err os.Error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
+ return
+}
+
+// These are not ValueDecoders: they produce an array of bytes or a string.
+// bytes, embedded messages
+
+// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err os.Error) {
+ n, err := p.DecodeVarint()
+ if err != nil {
+ return
+ }
+
+ nb := int(n)
+ if p.index+nb > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+
+ if !alloc {
+ // todo: check if can get more uses of alloc=false
+ buf = p.buf[p.index : p.index+nb]
+ p.index += nb
+ return
+ }
+
+ buf = make([]byte, nb)
+ copy(buf, p.buf[p.index:])
+ p.index += nb
+ return
+}
+
+// DecodeStringBytes reads an encoded string from the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) DecodeStringBytes() (s string, err os.Error) {
+ buf, err := p.DecodeRawBytes(false)
+ if err != nil {
+ return
+ }
+ return string(buf), nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+// If the protocol buffer has extensions, and the field matches, add it as an extension.
+// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
+func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base uintptr) os.Error {
+
+ oi := o.index
+
+ err := o.skip(t, tag, wire)
+ if err != nil {
+ return err
+ }
+
+ x := fieldIndex(t, "XXX_unrecognized")
+ if x == nil {
+ return nil
+ }
+
+ p := propByIndex(t, x)
+ ptr := (*[]byte)(unsafe.Pointer(base + p.offset))
+
+ if *ptr == nil {
+ // This is the first skipped element,
+ // allocate a new buffer.
+ *ptr = o.bufalloc()
+ }
+
+ // Add the skipped field to struct field
+ obuf := o.buf
+
+ o.buf = *ptr
+ o.EncodeVarint(uint64(tag<<3 | wire))
+ *ptr = append(o.buf, obuf[oi:o.index]...)
+
+ o.buf = obuf
+
+ return nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+func (o *Buffer) skip(t reflect.Type, tag, wire int) os.Error {
+
+ var u uint64
+ var err os.Error
+
+ switch wire {
+ case WireVarint:
+ _, err = o.DecodeVarint()
+ case WireFixed64:
+ _, err = o.DecodeFixed64()
+ case WireBytes:
+ _, err = o.DecodeRawBytes(false)
+ case WireFixed32:
+ _, err = o.DecodeFixed32()
+ case WireStartGroup:
+ for {
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ fwire := int(u & 0x7)
+ if fwire == WireEndGroup {
+ break
+ }
+ ftag := int(u >> 3)
+ err = o.skip(t, ftag, fwire)
+ if err != nil {
+ break
+ }
+ }
+ default:
+ fmt.Fprintf(os.Stderr, "proto: can't skip wire type %d for %s\n", wire, t)
+ }
+ return err
+}
+
+// Unmarshaler is the interface representing objects that can unmarshal themselves.
+type Unmarshaler interface {
+ Unmarshal([]byte) os.Error
+}
+
+// Unmarshal parses the protocol buffer representation in buf and places the
+// decoded result in pb. If the struct underlying pb does not match
+// the data in buf, the results can be unpredictable.
+func Unmarshal(buf []byte, pb interface{}) os.Error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ return u.Unmarshal(buf)
+ }
+
+ return NewBuffer(buf).Unmarshal(pb)
+}
+
+// Unmarshal parses the protocol buffer representation in the
+// Buffer and places the decoded result in pb. If the struct
+// underlying pb does not match the data in the buffer, the results can be
+// unpredictable.
+func (p *Buffer) Unmarshal(pb interface{}) os.Error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ err := u.Unmarshal(p.buf[p.index:])
+ p.index = len(p.buf)
+ return err
+ }
+
+ mstat := runtime.MemStats.Mallocs
+
+ typ, base, err := getbase(pb)
+ if err != nil {
+ return err
+ }
+
+ err = p.unmarshalType(typ, false, base)
+
+ mstat = runtime.MemStats.Mallocs - mstat
+ stats.Dmalloc += mstat
+ stats.Decode++
+
+ return err
+}
+
+// unmarshalType does the work of unmarshaling a structure.
+func (o *Buffer) unmarshalType(t reflect.Type, is_group bool, base uintptr) os.Error {
+ st := t.Elem()
+ prop := GetProperties(st)
+ required, reqFields := prop.reqCount, uint64(0)
+ sbase := getsbase(prop) // scratch area for data items
+
+ var err os.Error
+ for err == nil && o.index < len(o.buf) {
+ oi := o.index
+ var u uint64
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ wire := int(u & 0x7)
+ if wire == WireEndGroup {
+ if is_group {
+ return nil // input is satisfied
+ }
+ return ErrWrongType
+ }
+ tag := int(u >> 3)
+ fieldnum, ok := prop.tags[tag]
+ if !ok {
+ // Maybe it's an extension?
+ o.ptr = base
+ iv := unsafe.Unreflect(t, unsafe.Pointer(&o.ptr))
+ if e, ok := iv.(extendableProto); ok && isExtensionField(e, int32(tag)) {
+ if err = o.skip(st, tag, wire); err == nil {
+ e.ExtensionMap()[int32(tag)] = Extension{enc: append([]byte(nil), o.buf[oi:o.index]...)}
+ }
+ continue
+ }
+ err = o.skipAndSave(st, tag, wire, base)
+ continue
+ }
+ p := prop.Prop[fieldnum]
+
+ if p.dec == nil {
+ fmt.Fprintf(os.Stderr, "no protobuf decoder for %s.%s\n", t, st.Field(fieldnum).Name)
+ continue
+ }
+ dec := p.dec
+ if wire != WireStartGroup && wire != p.WireType {
+ if wire == WireBytes && p.packedDec != nil {
+ // a packable field
+ dec = p.packedDec
+ } else {
+ err = ErrWrongType
+ continue
+ }
+ }
+ err = dec(o, p, base, sbase)
+ if err == nil && p.Required {
+ // Successfully decoded a required field.
+ if tag <= 64 {
+ // use bitmap for fields 1-64 to catch field reuse.
+ var mask uint64 = 1 << uint64(tag-1)
+ if reqFields&mask == 0 {
+ // new required field
+ reqFields |= mask
+ required--
+ }
+ } else {
+ // This is imprecise. It can be fooled by a required field
+ // with a tag > 64 that is encoded twice; that's very rare.
+ // A fully correct implementation would require allocating
+ // a data structure, which we would like to avoid.
+ required--
+ }
+ }
+ }
+ if err == nil {
+ if is_group {
+ return io.ErrUnexpectedEOF
+ }
+ if required > 0 {
+ return &ErrRequiredNotSet{st}
+ }
+ }
+ return err
+}
+
+// Make *pslice have base address base, length 0, and capacity startSize.
+func initSlice(pslice unsafe.Pointer, base uintptr) {
+ sp := (*reflect.SliceHeader)(pslice)
+ sp.Data = base
+ sp.Len = 0
+ sp.Cap = startSize
+}
+
+// Individual type decoders
+// For each,
+// u is the decoded value,
+// v is a pointer to the field (pointer) in the struct
+// x is a pointer to the preallocated scratch space to hold the decoded value.
+
+// Decode a bool.
+func (o *Buffer) dec_bool(p *Properties, base uintptr, sbase uintptr) os.Error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v := (**uint8)(unsafe.Pointer(base + p.offset))
+ x := (*uint8)(unsafe.Pointer(sbase + p.scratch))
+ *x = uint8(u)
+ *v = x
+ return nil
+}
+
+// Decode an int32.
+func (o *Buffer) dec_int32(p *Properties, base uintptr, sbase uintptr) os.Error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v := (**int32)(unsafe.Pointer(base + p.offset))
+ x := (*int32)(unsafe.Pointer(sbase + p.scratch))
+ *x = int32(u)
+ *v = x
+ return nil
+}
+
+// Decode an int64.
+func (o *Buffer) dec_int64(p *Properties, base uintptr, sbase uintptr) os.Error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v := (**int64)(unsafe.Pointer(base + p.offset))
+ x := (*int64)(unsafe.Pointer(sbase + p.scratch))
+ *x = int64(u)
+ *v = x
+ return nil
+}
+
+// Decode a string.
+func (o *Buffer) dec_string(p *Properties, base uintptr, sbase uintptr) os.Error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ v := (**string)(unsafe.Pointer(base + p.offset))
+ x := (*string)(unsafe.Pointer(sbase + p.scratch))
+ *x = s
+ *v = x
+ return nil
+}
+
+// Decode a slice of bytes ([]byte).
+func (o *Buffer) dec_slice_byte(p *Properties, base uintptr, sbase uintptr) os.Error {
+ b, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+
+ x := (*[]uint8)(unsafe.Pointer(base + p.offset))
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ *x = append(y, b...)
+ return nil
+}
+
+// Decode a slice of bools ([]bool).
+func (o *Buffer) dec_slice_bool(p *Properties, base uintptr, sbase uintptr) os.Error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ x := (*[]bool)(unsafe.Pointer(base + p.offset))
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ *x = append(y, u != 0)
+ return nil
+}
+
+// Decode a slice of bools ([]bool) in packed format.
+func (o *Buffer) dec_slice_packed_bool(p *Properties, base uintptr, sbase uintptr) os.Error {
+ x := (*[]bool)(unsafe.Pointer(base + p.offset))
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded bools
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ for i := 0; i < nb; i++ {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ y = append(y, u != 0)
+ }
+
+ *x = y
+ return nil
+}
+
+// Decode a slice of int32s ([]int32).
+func (o *Buffer) dec_slice_int32(p *Properties, base uintptr, sbase uintptr) os.Error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ x := (*[]int32)(unsafe.Pointer(base + p.offset))
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ *x = append(y, int32(u))
+ return nil
+}
+
+// Decode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) dec_slice_packed_int32(p *Properties, base uintptr, sbase uintptr) os.Error {
+ x := (*[]int32)(unsafe.Pointer(base + p.offset))
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int32s
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ fin := o.index + nb
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ y = append(y, int32(u))
+ }
+
+ *x = y
+ return nil
+}
+
+// Decode a slice of int64s ([]int64).
+func (o *Buffer) dec_slice_int64(p *Properties, base uintptr, sbase uintptr) os.Error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ x := (*[]int64)(unsafe.Pointer(base + p.offset))
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ *x = append(y, int64(u))
+ return nil
+}
+
+// Decode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) dec_slice_packed_int64(p *Properties, base uintptr, sbase uintptr) os.Error {
+ x := (*[]int64)(unsafe.Pointer(base + p.offset))
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int64s
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ fin := o.index + nb
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ y = append(y, int64(u))
+ }
+
+ *x = y
+ return nil
+}
+
+// Decode a slice of strings ([]string).
+func (o *Buffer) dec_slice_string(p *Properties, base uintptr, sbase uintptr) os.Error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ x := (*[]string)(unsafe.Pointer(base + p.offset))
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ *x = append(y, s)
+ return nil
+}
+
+// Decode a slice of slice of bytes ([][]byte).
+func (o *Buffer) dec_slice_slice_byte(p *Properties, base uintptr, sbase uintptr) os.Error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ x := (*[][]byte)(unsafe.Pointer(base + p.offset))
+
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ *x = append(y, b)
+ return nil
+}
+
+// Decode a group.
+func (o *Buffer) dec_struct_group(p *Properties, base uintptr, sbase uintptr) os.Error {
+ ptr := (**struct{})(unsafe.Pointer(base + p.offset))
+ typ := p.stype.Elem()
+ structv := unsafe.New(typ)
+ bas := uintptr(structv)
+ *ptr = (*struct{})(structv)
+
+ err := o.unmarshalType(p.stype, true, bas)
+
+ return err
+}
+
+// Decode an embedded message.
+func (o *Buffer) dec_struct_message(p *Properties, base uintptr, sbase uintptr) (err os.Error) {
+ raw, e := o.DecodeRawBytes(false)
+ if e != nil {
+ return e
+ }
+
+ ptr := (**struct{})(unsafe.Pointer(base + p.offset))
+ typ := p.stype.Elem()
+ structv := unsafe.New(typ)
+ bas := uintptr(structv)
+ *ptr = (*struct{})(structv)
+
+ // If the object can unmarshal itself, let it.
+ iv := unsafe.Unreflect(p.stype, unsafe.Pointer(ptr))
+ if u, ok := iv.(Unmarshaler); ok {
+ return u.Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, false, bas)
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
+
+// Decode a slice of embedded messages.
+func (o *Buffer) dec_slice_struct_message(p *Properties, base uintptr, sbase uintptr) os.Error {
+ return o.dec_slice_struct(p, false, base, sbase)
+}
+
+// Decode a slice of embedded groups.
+func (o *Buffer) dec_slice_struct_group(p *Properties, base uintptr, sbase uintptr) os.Error {
+ return o.dec_slice_struct(p, true, base, sbase)
+}
+
+// Decode a slice of structs ([]*struct).
+func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base uintptr, sbase uintptr) os.Error {
+
+ x := (*[]*struct{})(unsafe.Pointer(base + p.offset))
+ y := *x
+ if cap(y) == 0 {
+ initSlice(unsafe.Pointer(x), sbase+p.scratch)
+ y = *x
+ }
+
+ typ := p.stype.Elem()
+ structv := unsafe.New(typ)
+ bas := uintptr(structv)
+ y = append(y, (*struct{})(structv))
+ *x = y
+
+ if is_group {
+ err := o.unmarshalType(p.stype, is_group, bas)
+ return err
+ }
+
+ raw, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+
+ // If the object can unmarshal itself, let it.
+ iv := unsafe.Unreflect(p.stype, unsafe.Pointer(&y[len(y)-1]))
+ if u, ok := iv.(Unmarshaler); ok {
+ return u.Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, is_group, bas)
+
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
--- /dev/null
+// 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.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "os"
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+// ErrRequiredNotSet is the error returned if Marshal is called with
+// a protocol buffer struct whose required fields have not
+// all been initialized. It is also the error returned if Unmarshal is
+// called with an encoded protocol buffer that does not include all the
+// required fields.
+type ErrRequiredNotSet struct {
+ t reflect.Type
+}
+
+func (e *ErrRequiredNotSet) String() string {
+ return "proto: required fields not set in " + e.t.String()
+}
+
+var (
+ // ErrRepeatedHasNil is the error returned if Marshal is called with
+ // a struct with a repeated field containing a nil element.
+ ErrRepeatedHasNil = os.NewError("proto: repeated field has nil")
+
+ // ErrNil is the error returned if Marshal is called with nil.
+ ErrNil = os.NewError("proto: Marshal called with nil")
+
+ // ErrNotPtr is the error returned if Marshal is called with a non-pointer.
+ ErrNotPtr = os.NewError("proto: Marshal called with a non-pointer")
+)
+
+// The fundamental encoders that put bytes on the wire.
+// Those that take integer types all accept uint64 and are
+// therefore of type valueEncoder.
+
+const maxVarintBytes = 10 // maximum length of a varint
+
+// EncodeVarint returns the varint encoding of x.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+// Not used by the package itself, but helpful to clients
+// wishing to use the same encoding.
+func EncodeVarint(x uint64) []byte {
+ var buf [maxVarintBytes]byte
+ var n int
+ for n = 0; x > 127; n++ {
+ buf[n] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ buf[n] = uint8(x)
+ n++
+ return buf[0:n]
+}
+
+// EncodeVarint writes a varint-encoded integer to the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) EncodeVarint(x uint64) os.Error {
+ for x >= 1<<7 {
+ p.buf = append(p.buf, uint8(x&0x7f|0x80))
+ x >>= 7
+ }
+ p.buf = append(p.buf, uint8(x))
+ return nil
+}
+
+// EncodeFixed64 writes a 64-bit integer to the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) EncodeFixed64(x uint64) os.Error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24),
+ uint8(x>>32),
+ uint8(x>>40),
+ uint8(x>>48),
+ uint8(x>>56))
+ return nil
+}
+
+// EncodeFixed32 writes a 32-bit integer to the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) EncodeFixed32(x uint64) os.Error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24))
+ return nil
+}
+
+// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
+// to the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) EncodeZigzag64(x uint64) os.Error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
+// to the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) EncodeZigzag32(x uint64) os.Error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
+// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) EncodeRawBytes(b []byte) os.Error {
+ lb := len(b)
+ p.EncodeVarint(uint64(lb))
+ p.buf = append(p.buf, b...)
+ return nil
+}
+
+// EncodeStringBytes writes an encoded string to the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) EncodeStringBytes(s string) os.Error {
+
+ // this works because strings and slices are the same.
+ y := *(*[]byte)(unsafe.Pointer(&s))
+ p.EncodeRawBytes(y)
+ return nil
+}
+
+// Marshaler is the interface representing objects that can marshal themselves.
+type Marshaler interface {
+ Marshal() ([]byte, os.Error)
+}
+
+// Marshal takes the protocol buffer struct represented by pb
+// and encodes it into the wire format, returning the data.
+func Marshal(pb interface{}) ([]byte, os.Error) {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ return m.Marshal()
+ }
+ p := NewBuffer(nil)
+ err := p.Marshal(pb)
+ if err != nil {
+ return nil, err
+ }
+ return p.buf, err
+}
+
+// Marshal takes the protocol buffer struct represented by pb
+// and encodes it into the wire format, writing the result to the
+// Buffer.
+func (p *Buffer) Marshal(pb interface{}) os.Error {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ data, err := m.Marshal()
+ if err != nil {
+ return err
+ }
+ p.buf = append(p.buf, data...)
+ return nil
+ }
+
+ mstat := runtime.MemStats.Mallocs
+
+ t, b, err := getbase(pb)
+ if t.Kind() != reflect.Ptr {
+ return ErrNotPtr
+ }
+ if err == nil {
+ err = p.enc_struct(t.Elem(), b)
+ }
+
+ mstat = runtime.MemStats.Mallocs - mstat
+ stats.Emalloc += mstat
+ stats.Encode++
+
+ return err
+}
+
+// Individual type encoders.
+
+// Encode a bool.
+func (o *Buffer) enc_bool(p *Properties, base uintptr) os.Error {
+ v := *(**uint8)(unsafe.Pointer(base + p.offset))
+ if v == nil {
+ return ErrNil
+ }
+ x := *v
+ if x != 0 {
+ x = 1
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+// Encode an int32.
+func (o *Buffer) enc_int32(p *Properties, base uintptr) os.Error {
+ v := *(**uint32)(unsafe.Pointer(base + p.offset))
+ if v == nil {
+ return ErrNil
+ }
+ x := *v
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+// Encode an int64.
+func (o *Buffer) enc_int64(p *Properties, base uintptr) os.Error {
+ v := *(**uint64)(unsafe.Pointer(base + p.offset))
+ if v == nil {
+ return ErrNil
+ }
+ x := *v
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+// Encode a string.
+func (o *Buffer) enc_string(p *Properties, base uintptr) os.Error {
+ v := *(**string)(unsafe.Pointer(base + p.offset))
+ if v == nil {
+ return ErrNil
+ }
+ x := *v
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(x)
+ return nil
+}
+
+// All protocol buffer fields are nillable, but be careful.
+func isNil(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Map, reflect.Ptr, reflect.Slice:
+ return v.IsNil()
+ }
+ return false
+}
+
+// Encode a message struct.
+func (o *Buffer) enc_struct_message(p *Properties, base uintptr) os.Error {
+ // Can the object marshal itself?
+ iv := unsafe.Unreflect(p.stype, unsafe.Pointer(base+p.offset))
+ if m, ok := iv.(Marshaler); ok {
+ if isNil(reflect.ValueOf(iv)) {
+ return ErrNil
+ }
+ data, err := m.Marshal()
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+ }
+ v := *(**struct{})(unsafe.Pointer(base + p.offset))
+ if v == nil {
+ return ErrNil
+ }
+
+ // need the length before we can write out the message itself,
+ // so marshal into a separate byte buffer first.
+ obuf := o.buf
+ o.buf = o.bufalloc()
+
+ b := uintptr(unsafe.Pointer(v))
+ typ := p.stype.Elem()
+ err := o.enc_struct(typ, b)
+
+ nbuf := o.buf
+ o.buf = obuf
+ if err != nil {
+ o.buffree(nbuf)
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(nbuf)
+ o.buffree(nbuf)
+ return nil
+}
+
+// Encode a group struct.
+func (o *Buffer) enc_struct_group(p *Properties, base uintptr) os.Error {
+ v := *(**struct{})(unsafe.Pointer(base + p.offset))
+ if v == nil {
+ return ErrNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+ b := uintptr(unsafe.Pointer(v))
+ typ := p.stype.Elem()
+ err := o.enc_struct(typ, b)
+ if err != nil {
+ return err
+ }
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ return nil
+}
+
+// Encode a slice of bools ([]bool).
+func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) os.Error {
+ s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ for _, x := range s {
+ o.buf = append(o.buf, p.tagcode...)
+ if x != 0 {
+ x = 1
+ }
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+// Encode a slice of bools ([]bool) in packed format.
+func (o *Buffer) enc_slice_packed_bool(p *Properties, base uintptr) os.Error {
+ s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
+ for _, x := range s {
+ if x != 0 {
+ x = 1
+ }
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+// Encode a slice of bytes ([]byte).
+func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) os.Error {
+ s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
+ if s == nil {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(s)
+ return nil
+}
+
+// Encode a slice of int32s ([]int32).
+func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) os.Error {
+ s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := s[i]
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+// Encode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) enc_slice_packed_int32(p *Properties, base uintptr) os.Error {
+ s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, uint64(s[i]))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+// Encode a slice of int64s ([]int64).
+func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) os.Error {
+ s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := s[i]
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+// Encode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) enc_slice_packed_int64(p *Properties, base uintptr) os.Error {
+ s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, s[i])
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+// Encode a slice of slice of bytes ([][]byte).
+func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) os.Error {
+ ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
+ l := len(ss)
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ s := ss[i]
+ o.EncodeRawBytes(s)
+ }
+ return nil
+}
+
+// Encode a slice of strings ([]string).
+func (o *Buffer) enc_slice_string(p *Properties, base uintptr) os.Error {
+ ss := *(*[]string)(unsafe.Pointer(base + p.offset))
+ l := len(ss)
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ s := ss[i]
+ o.EncodeStringBytes(s)
+ }
+ return nil
+}
+
+// Encode a slice of message structs ([]*struct).
+func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) os.Error {
+ s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ typ := p.stype.Elem()
+
+ for i := 0; i < l; i++ {
+ v := s[i]
+ if v == nil {
+ return ErrRepeatedHasNil
+ }
+
+ // Can the object marshal itself?
+ iv := unsafe.Unreflect(p.stype, unsafe.Pointer(&s[i]))
+ if m, ok := iv.(Marshaler); ok {
+ if isNil(reflect.ValueOf(iv)) {
+ return ErrNil
+ }
+ data, err := m.Marshal()
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ continue
+ }
+
+ obuf := o.buf
+ o.buf = o.bufalloc()
+
+ b := uintptr(unsafe.Pointer(v))
+ err := o.enc_struct(typ, b)
+
+ nbuf := o.buf
+ o.buf = obuf
+ if err != nil {
+ o.buffree(nbuf)
+ if err == ErrNil {
+ return ErrRepeatedHasNil
+ }
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(nbuf)
+
+ o.buffree(nbuf)
+ }
+ return nil
+}
+
+// Encode a slice of group structs ([]*struct).
+func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) os.Error {
+ s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
+ l := len(s)
+ typ := p.stype.Elem()
+
+ for i := 0; i < l; i++ {
+ v := s[i]
+ if v == nil {
+ return ErrRepeatedHasNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+
+ b := uintptr(unsafe.Pointer(v))
+ err := o.enc_struct(typ, b)
+
+ if err != nil {
+ if err == ErrNil {
+ return ErrRepeatedHasNil
+ }
+ return err
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ }
+ return nil
+}
+
+// Encode an extension map.
+func (o *Buffer) enc_map(p *Properties, base uintptr) os.Error {
+ v := *(*map[int32]Extension)(unsafe.Pointer(base + p.offset))
+ if err := encodeExtensionMap(v); err != nil {
+ return err
+ }
+ for _, e := range v {
+ o.buf = append(o.buf, e.enc...)
+ }
+ return nil
+}
+
+// Encode a struct.
+func (o *Buffer) enc_struct(t reflect.Type, base uintptr) os.Error {
+ prop := GetProperties(t)
+ required := prop.reqCount
+ for _, p := range prop.Prop {
+ if p.enc != nil {
+ err := p.enc(o, p, base)
+ if err != nil {
+ if err != ErrNil {
+ return err
+ }
+ } else if p.Required {
+ required--
+ }
+ }
+ }
+ // See if we encoded all required fields.
+ if required > 0 {
+ return &ErrRequiredNotSet{t}
+ }
+
+ return nil
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 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.
+
+// Protocol buffer comparison.
+// TODO: MessageSet and RawMessage.
+
+package proto
+
+import (
+ "bytes"
+ "log"
+ "os"
+ "reflect"
+ "strings"
+)
+
+/*
+Equal returns true iff protocol buffers a and b are equal.
+The arguments must both be protocol buffer structs,
+or both be pointers to protocol buffer structs.
+
+Equality is defined in this way:
+ - Two messages are equal iff they are the same type,
+ corresponding fields are equal, unknown field sets
+ are equal, and extensions sets are equal.
+ - Two set scalar fields are equal iff their values are equal.
+ If the fields are of a floating-point type, remember that
+ NaN != x for all x, including NaN.
+ - Two repeated fields are equal iff their lengths are the same,
+ and their corresponding elements are equal.
+ - Two unset fields are equal.
+ - Two unknown field sets are equal if their current
+ encoded state is equal. (TODO)
+ - Two extension sets are equal iff they have corresponding
+ elements that are pairwise equal.
+ - Every other combination of things are not equal.
+
+The return value is undefined if a and b are not protocol buffers.
+*/
+func Equal(a, b interface{}) bool {
+ v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
+ if v1.Type() != v2.Type() {
+ return false
+ }
+ if v1.Kind() == reflect.Ptr {
+ v1, v2 = v1.Elem(), v2.Elem()
+ }
+ if v1.Kind() != reflect.Struct {
+ return false
+ }
+ return equalStruct(v1, v2)
+}
+
+// v1 and v2 are known to have the same type.
+func equalStruct(v1, v2 reflect.Value) bool {
+ for i := 0; i < v1.NumField(); i++ {
+ f := v1.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ f1, f2 := v1.Field(i), v2.Field(i)
+ if f.Type.Kind() == reflect.Ptr {
+ if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
+ // both unset
+ continue
+ } else if n1 != n2 {
+ // set/unset mismatch
+ return false
+ }
+ f1, f2 = f1.Elem(), f2.Elem()
+ }
+ if !equalAny(f1, f2) {
+ return false
+ }
+ }
+
+ if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
+ em2 := v2.FieldByName("XXX_extensions")
+ if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
+ return false
+ }
+ }
+
+ // TODO: Deal with XXX_unrecognized.
+
+ return true
+}
+
+// v1 and v2 are known to have the same type.
+func equalAny(v1, v2 reflect.Value) bool {
+ switch v1.Kind() {
+ case reflect.Bool:
+ return v1.Bool() == v2.Bool()
+ case reflect.Float32, reflect.Float64:
+ return v1.Float() == v2.Float()
+ case reflect.Int32, reflect.Int64:
+ return v1.Int() == v2.Int()
+ case reflect.Ptr:
+ return equalAny(v1.Elem(), v2.Elem())
+ case reflect.Slice:
+ if n1, n2 := v1.IsNil(), v2.IsNil(); n1 && n2 {
+ return true
+ } else if n1 != n2 {
+ return false
+ }
+ if v1.Len() != v2.Len() {
+ return false
+ }
+ // short circuit: []byte
+ if v1.Type().Elem().Kind() == reflect.Uint8 {
+ return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
+ }
+ for i := 0; i < v1.Len(); i++ {
+ if !equalAny(v1.Index(i), v2.Index(i)) {
+ return false
+ }
+ }
+ return true
+ case reflect.String:
+ return v1.Interface().(string) == v2.Interface().(string)
+ case reflect.Struct:
+ return equalStruct(v1, v2)
+ case reflect.Uint32, reflect.Uint64:
+ return v1.Uint() == v2.Uint()
+ }
+
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to compare %v", v1)
+ return false
+}
+
+// base is the struct type that the extensions are based on.
+// em1 and em2 are extension maps.
+func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
+ if len(em1) != len(em2) {
+ return false
+ }
+
+ for extNum, e1 := range em1 {
+ e2, ok := em2[extNum]
+ if !ok {
+ return false
+ }
+
+ m1, m2 := e1.value, e2.value
+
+ if m1 != nil && m2 != nil {
+ // Both are unencoded.
+ if !Equal(m1, m2) {
+ return false
+ }
+ continue
+ }
+
+ // At least one is encoded. To do a semantically correct comparison
+ // we need to unmarshal them first.
+ var desc *ExtensionDesc
+ if m := extensionMaps[base]; m != nil {
+ desc = m[extNum]
+ }
+ if desc == nil {
+ log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
+ continue
+ }
+ var err os.Error
+ if m1 == nil {
+ m1, err = decodeExtension(e1.enc, desc)
+ }
+ if m2 == nil && err == nil {
+ m2, err = decodeExtension(e2.enc, desc)
+ }
+ if err != nil {
+ // The encoded form is invalid.
+ log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
+ return false
+ }
+ if !Equal(m1, m2) {
+ return false
+ }
+ }
+
+ return true
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 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.
+
+package proto_test
+
+import (
+ "log"
+ "testing"
+
+ . "goprotobuf.googlecode.com/hg/proto"
+ pb "./testdata/_obj/test_proto"
+)
+
+// Four identical base messages.
+// The init function adds extensions to some of them.
+var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)}
+var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)}
+var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)}
+var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)}
+
+func init() {
+ ext1 := &pb.Ext{Data: String("Kirk")}
+ ext2 := &pb.Ext{Data: String("Picard")}
+
+ // messageWithExtension1a has ext1, but never marshals it.
+ if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil {
+ log.Panicf("SetExtension on 1a failed: %v", err)
+ }
+
+ // messageWithExtension1b is the unmarshaled form of messageWithExtension1a.
+ if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil {
+ log.Panicf("SetExtension on 1b failed: %v", err)
+ }
+ buf, err := Marshal(messageWithExtension1b)
+ if err != nil {
+ log.Panicf("Marshal of 1b failed: %v", err)
+ }
+ messageWithExtension1b.Reset()
+ if err := Unmarshal(buf, messageWithExtension1b); err != nil {
+ log.Panicf("Unmarshal of 1b failed: %v", err)
+ }
+
+ // messageWithExtension2 has ext2.
+ if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil {
+ log.Panicf("SetExtension on 2 failed: %v", err)
+ }
+}
+
+var EqualTests = []struct {
+ desc string
+ a, b interface{}
+ exp bool
+}{
+ {"different types", &pb.GoEnum{}, &pb.GoTestField{}, false},
+ {"one pointer, one value", &pb.GoEnum{}, pb.GoEnum{}, false},
+ {"non-protocol buffers", 7, 7, false},
+ {"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true},
+
+ {"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false},
+ {"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false},
+ {"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false},
+ {"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true},
+
+ {"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false},
+ {"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false},
+ {"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false},
+ {"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true},
+
+ {
+ "nested, different",
+ &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}},
+ &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}},
+ false,
+ },
+ {
+ "nested, equal",
+ &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
+ &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
+ true,
+ },
+
+ {
+ "repeated bytes",
+ &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
+ &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
+ true,
+ },
+
+ {"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false},
+ {"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true},
+ {"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false},
+}
+
+func TestEqual(t *testing.T) {
+ for _, tc := range EqualTests {
+ if res := Equal(tc.a, tc.b); res != tc.exp {
+ t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp)
+ }
+ }
+}
--- /dev/null
+// 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.
+
+package proto
+
+
+/*
+ * Types and routines for supporting protocol buffer extensions.
+ */
+
+import (
+ "os"
+ "reflect"
+ "strconv"
+ "unsafe"
+)
+
+// ExtensionRange represents a range of message extensions for a protocol buffer.
+// Used in code generated by the protocol compiler.
+type ExtensionRange struct {
+ Start, End int32 // both inclusive
+}
+
+// extendableProto is an interface implemented by any protocol buffer that may be extended.
+type extendableProto interface {
+ ExtensionRangeArray() []ExtensionRange
+ ExtensionMap() map[int32]Extension
+}
+
+// ExtensionDesc represents an extension specification.
+// Used in generated code from the protocol compiler.
+type ExtensionDesc struct {
+ ExtendedType interface{} // nil pointer to the type that is being extended
+ ExtensionType interface{} // nil pointer to the extension type
+ Field int32 // field number
+ Name string // fully-qualified name of extension
+ Tag string // protobuf tag style
+}
+
+/*
+Extension represents an extension in a message.
+
+When an extension is stored in a message using SetExtension
+only desc and value are set. When the message is marshaled
+enc will be set to the encoded form of the message.
+
+When a message is unmarshaled and contains extensions, each
+extension will have only enc set. When such an extension is
+accessed using GetExtension (or GetExtensions) desc and value
+will be set.
+*/
+type Extension struct {
+ desc *ExtensionDesc
+ value interface{}
+ enc []byte
+}
+
+// SetRawExtension is for testing only.
+func SetRawExtension(base extendableProto, id int32, b []byte) {
+ base.ExtensionMap()[id] = Extension{enc: b}
+}
+
+// isExtensionField returns true iff the given field number is in an extension range.
+func isExtensionField(pb extendableProto, field int32) bool {
+ for _, er := range pb.ExtensionRangeArray() {
+ if er.Start <= field && field <= er.End {
+ return true
+ }
+ }
+ return false
+}
+
+// checkExtensionTypes checks that the given extension is valid for pb.
+func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) os.Error {
+ // Check the extended type.
+ if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b {
+ return os.NewError("bad extended type; " + b.String() + " does not extend " + a.String())
+ }
+ // Check the range.
+ if !isExtensionField(pb, extension.Field) {
+ return os.NewError("bad extension number; not in declared ranges")
+ }
+ return nil
+}
+
+// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m.
+func encodeExtensionMap(m map[int32]Extension) os.Error {
+ for k, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := new(Properties)
+ props.Init(et, "unknown_name", e.desc.Tag, 0)
+
+ p := NewBuffer(nil)
+ // The encoder must be passed a pointer to e.value.
+ // Allocate a copy of value so that we can use its address.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ if err := props.enc(p, props, x.Pointer()); err != nil {
+ return err
+ }
+ e.enc = p.buf
+ m[k] = e
+ }
+ return nil
+}
+
+// HasExtension returns whether the given extension is present in pb.
+func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
+ // TODO: Check types, field numbers, etc.?
+ _, ok := pb.ExtensionMap()[extension.Field]
+ return ok
+}
+
+// ClearExtension removes the given extension from pb.
+func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
+ // TODO: Check types, field numbers, etc.?
+ pb.ExtensionMap()[extension.Field] = Extension{}, false
+}
+
+// GetExtension parses and returns the given extension of pb.
+// If the extension is not present it returns (nil, nil).
+func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, os.Error) {
+ if err := checkExtensionTypes(pb, extension); err != nil {
+ return nil, err
+ }
+
+ e, ok := pb.ExtensionMap()[extension.Field]
+ if !ok {
+ return nil, nil // not an error
+ }
+ if e.value != nil {
+ // Already decoded. Check the descriptor, though.
+ if e.desc != extension {
+ // This shouldn't happen. If it does, it means that
+ // GetExtension was called twice with two different
+ // descriptors with the same field number.
+ return nil, os.NewError("proto: descriptor conflict")
+ }
+ return e.value, nil
+ }
+
+ v, err := decodeExtension(e.enc, extension)
+ if err != nil {
+ return nil, err
+ }
+
+ // Remember the decoded version and drop the encoded version.
+ // That way it is safe to mutate what we return.
+ e.value = v
+ e.desc = extension
+ e.enc = nil
+ return e.value, nil
+}
+
+// decodeExtension decodes an extension encoded in b.
+func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, os.Error) {
+ // Discard wire type and field number varint. It isn't needed.
+ _, n := DecodeVarint(b)
+ o := NewBuffer(b[n:])
+
+ t := reflect.TypeOf(extension.ExtensionType)
+ props := &Properties{}
+ props.Init(t, "irrelevant_name", extension.Tag, 0)
+
+ base := unsafe.New(t)
+ var sbase uintptr
+ if t.Elem().Kind() == reflect.Struct {
+ // props.dec will be dec_struct_message, which does not refer to sbase.
+ *(*unsafe.Pointer)(base) = unsafe.New(t.Elem())
+ } else {
+ sbase = uintptr(unsafe.New(t.Elem()))
+ }
+ if err := props.dec(o, props, uintptr(base), sbase); err != nil {
+ return nil, err
+ }
+ return unsafe.Unreflect(t, base), nil
+}
+
+// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
+// The returned slice has the same length as es; missing extensions will appear as nil elements.
+func GetExtensions(pb interface{}, es []*ExtensionDesc) (extensions []interface{}, err os.Error) {
+ epb, ok := pb.(extendableProto)
+ if !ok {
+ err = os.NewError("not an extendable proto")
+ return
+ }
+ extensions = make([]interface{}, len(es))
+ for i, e := range es {
+ extensions[i], err = GetExtension(epb, e)
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// TODO: (needed for repeated extensions)
+// - ExtensionSize
+// - AddExtension
+
+// SetExtension sets the specified extension of pb to the specified value.
+func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) os.Error {
+ if err := checkExtensionTypes(pb, extension); err != nil {
+ return err
+ }
+ typ := reflect.TypeOf(extension.ExtensionType)
+ if typ != reflect.TypeOf(value) {
+ return os.NewError("bad extension value type")
+ }
+
+ pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
+ return nil
+}
+
+// A global registry of extensions.
+// The generated code will register the generated descriptors by calling RegisterExtension.
+
+var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
+
+// RegisterExtension is called from the generated code.
+func RegisterExtension(desc *ExtensionDesc) {
+ st := reflect.TypeOf(desc.ExtendedType).Elem()
+ m := extensionMaps[st]
+ if m == nil {
+ m = make(map[int32]*ExtensionDesc)
+ extensionMaps[st] = m
+ }
+ if _, ok := m[desc.Field]; ok {
+ panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
+ }
+ m[desc.Field] = desc
+}
+
+// RegisteredExtensions returns a map of the registered extensions of a
+// protocol buffer struct, indexed by the extension number.
+// The argument pb should be a nil pointer to the struct type.
+func RegisteredExtensions(pb interface{}) map[int32]*ExtensionDesc {
+ return extensionMaps[reflect.TypeOf(pb).Elem()]
+}
--- /dev/null
+// 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.
+ - 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. Enum types have a String method.
+ - 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
+ }
+ func (x FOO) String() string {
+ return proto.EnumName(FOO_name, int32(x))
+ }
+
+ type Test struct {
+ Label *string `protobuf:"bytes,1,req,name=label"`
+ Type *int32 `protobuf:"varint,2,opt,name=type,def=77"`
+ Reps []int64 `protobuf:"varint,3,rep,name=reps"`
+ Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=optionalgroup"`
+ XXX_unrecognized []byte
+ }
+ func (this *Test) Reset() {
+ *this = Test{}
+ }
+ const Default_Test_Type int32 = 77
+
+ type Test_OptionalGroup struct {
+ RequiredField *string `protobuf:"bytes,5,req"`
+ XXX_unrecognized []byte
+ }
+ func (this *Test_OptionalGroup) Reset() {
+ *this = 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.Fatal("marshaling error: ", err)
+ }
+ newTest := new(example.Test)
+ err = proto.Unmarshal(data, newTest)
+ if err != nil {
+ log.Fatal("unmarshaling error: ", err)
+ }
+ // Now test and newTest contain the same data.
+ if proto.GetString(test.Label) != proto.GetString(newTest.Label) {
+ log.Fatalf("data mismatch %q != %q", proto.GetString(test.Label), proto.GetString(newTest.Label))
+ }
+ // etc.
+ }
+*/
+package proto
+
+import (
+ "fmt"
+ "log"
+ "reflect"
+ "strconv"
+ "sync"
+)
+
+// 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
+}
+
+// SetDefaults sets unset protocol buffer fields to their default values.
+// It only modifies fields that are both unset and have defined defaults.
+// It recursively sets default values in any non-nil sub-messages.
+func SetDefaults(pb interface{}) {
+ v := reflect.ValueOf(pb)
+ if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
+ log.Printf("proto: hit non-pointer-to-struct %v", v)
+ }
+ setDefaults(v, true, false)
+}
+
+// v is a pointer to a struct.
+func setDefaults(v reflect.Value, recur, zeros bool) {
+ v = v.Elem()
+
+ defaultMu.Lock()
+ dm, ok := defaults[v.Type()]
+ defaultMu.Unlock()
+ if !ok {
+ dm = buildDefaultMessage(v.Type())
+ defaultMu.Lock()
+ defaults[v.Type()] = dm
+ defaultMu.Unlock()
+ }
+
+ for _, sf := range dm.scalars {
+ f := v.Field(sf.index)
+ if !f.IsNil() {
+ // field already set
+ continue
+ }
+ dv := sf.value
+ if dv == nil && !zeros {
+ // no explicit default, and don't want to set zeros
+ continue
+ }
+ fptr := f.Addr().Interface() // **T
+ // TODO: Consider batching the allocations we do here.
+ switch sf.kind {
+ case reflect.Bool:
+ b := new(bool)
+ if dv != nil {
+ *b = dv.(bool)
+ }
+ *(fptr.(**bool)) = b
+ case reflect.Float32:
+ f := new(float32)
+ if dv != nil {
+ *f = dv.(float32)
+ }
+ *(fptr.(**float32)) = f
+ case reflect.Float64:
+ f := new(float64)
+ if dv != nil {
+ *f = dv.(float64)
+ }
+ *(fptr.(**float64)) = f
+ case reflect.Int32:
+ // might be an enum
+ if ft := f.Type(); ft != int32PtrType {
+ // enum
+ f.Set(reflect.New(ft.Elem()))
+ if dv != nil {
+ f.Elem().SetInt(int64(dv.(int32)))
+ }
+ } else {
+ // int32 field
+ i := new(int32)
+ if dv != nil {
+ *i = dv.(int32)
+ }
+ *(fptr.(**int32)) = i
+ }
+ case reflect.Int64:
+ i := new(int64)
+ if dv != nil {
+ *i = dv.(int64)
+ }
+ *(fptr.(**int64)) = i
+ case reflect.String:
+ s := new(string)
+ if dv != nil {
+ *s = dv.(string)
+ }
+ *(fptr.(**string)) = s
+ case reflect.Uint8:
+ // exceptional case: []byte
+ var b []byte
+ if dv != nil {
+ db := dv.([]byte)
+ b = make([]byte, len(db))
+ copy(b, db)
+ } else {
+ b = []byte{}
+ }
+ *(fptr.(*[]byte)) = b
+ case reflect.Uint32:
+ u := new(uint32)
+ if dv != nil {
+ *u = dv.(uint32)
+ }
+ *(fptr.(**uint32)) = u
+ case reflect.Uint64:
+ u := new(uint64)
+ if dv != nil {
+ *u = dv.(uint64)
+ }
+ *(fptr.(**uint64)) = u
+ default:
+ log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
+ }
+ }
+
+ for _, ni := range dm.nested {
+ setDefaults(v.Field(ni), recur, zeros)
+ }
+}
+
+var (
+ // defaults maps a protocol buffer struct type to a slice of the fields,
+ // with its scalar fields set to their proto-declared non-zero default values.
+ defaultMu sync.Mutex
+ defaults = make(map[reflect.Type]defaultMessage)
+
+ int32PtrType = reflect.TypeOf((*int32)(nil))
+)
+
+// defaultMessage represents information about the default values of a message.
+type defaultMessage struct {
+ scalars []scalarField
+ nested []int // struct field index of nested messages
+}
+
+type scalarField struct {
+ index int // struct field index
+ kind reflect.Kind // element type (the T in *T or []T)
+ value interface{} // the proto-declared default value, or nil
+}
+
+// t is a struct type.
+func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
+ sprop := GetProperties(t)
+ for _, prop := range sprop.Prop {
+ fi := sprop.tags[prop.Tag]
+ ft := t.Field(fi).Type
+
+ // nested messages
+ if ft.Kind() == reflect.Ptr && ft.Elem().Kind() == reflect.Struct {
+ dm.nested = append(dm.nested, fi)
+ continue
+ }
+
+ sf := scalarField{
+ index: fi,
+ kind: ft.Elem().Kind(),
+ }
+
+ // scalar fields without defaults
+ if prop.Default == "" {
+ dm.scalars = append(dm.scalars, sf)
+ continue
+ }
+
+ // a scalar field: either *T or []byte
+ switch ft.Elem().Kind() {
+ case reflect.Bool:
+ x, err := strconv.Atob(prop.Default)
+ if err != nil {
+ log.Printf("proto: bad default bool %q: %v", prop.Default, err)
+ continue
+ }
+ sf.value = x
+ case reflect.Float32:
+ x, err := strconv.Atof32(prop.Default)
+ if err != nil {
+ log.Printf("proto: bad default float32 %q: %v", prop.Default, err)
+ continue
+ }
+ sf.value = x
+ case reflect.Float64:
+ x, err := strconv.Atof64(prop.Default)
+ if err != nil {
+ log.Printf("proto: bad default float64 %q: %v", prop.Default, err)
+ continue
+ }
+ sf.value = x
+ case reflect.Int32:
+ x, err := strconv.Atoi64(prop.Default)
+ if err != nil {
+ log.Printf("proto: bad default int32 %q: %v", prop.Default, err)
+ continue
+ }
+ sf.value = int32(x)
+ case reflect.Int64:
+ x, err := strconv.Atoi64(prop.Default)
+ if err != nil {
+ log.Printf("proto: bad default int64 %q: %v", prop.Default, err)
+ continue
+ }
+ sf.value = x
+ case reflect.String:
+ sf.value = prop.Default
+ case reflect.Uint8:
+ // []byte (not *uint8)
+ sf.value = []byte(prop.Default)
+ case reflect.Uint32:
+ x, err := strconv.Atoui64(prop.Default)
+ if err != nil {
+ log.Printf("proto: bad default uint32 %q: %v", prop.Default, err)
+ continue
+ }
+ sf.value = uint32(x)
+ case reflect.Uint64:
+ x, err := strconv.Atoui64(prop.Default)
+ if err != nil {
+ log.Printf("proto: bad default uint64 %q: %v", prop.Default, err)
+ continue
+ }
+ sf.value = x
+ default:
+ log.Printf("proto: unhandled def kind %v", ft.Elem().Kind())
+ continue
+ }
+
+ dm.scalars = append(dm.scalars, sf)
+ }
+
+ return dm
+}
--- /dev/null
+// 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.
+
+package proto
+
+/*
+ * Support for message sets.
+ */
+
+import (
+ "bytes"
+ "os"
+ "reflect"
+)
+
+// ErrNoMessageTypeId occurs when a protocol buffer does not have a message type ID.
+// A message type ID is required for storing a protocol buffer in a message set.
+var ErrNoMessageTypeId = os.NewError("proto does not have a message type ID")
+
+// The first two types (_MessageSet_Item and MessageSet)
+// model what the protocol compiler produces for the following protocol message:
+// message MessageSet {
+// repeated group Item = 1 {
+// required int32 type_id = 2;
+// required string message = 3;
+// };
+// }
+// That is the MessageSet wire format. We can't use a proto to generate these
+// because that would introduce a circular dependency between it and this package.
+//
+// When a proto1 proto has a field that looks like:
+// optional message<MessageSet> info = 3;
+// the protocol compiler produces a field in the generated struct that looks like:
+// Info *_proto_.MessageSet `protobuf:"bytes,3,opt,name=info"`
+// The package is automatically inserted so there is no need for that proto file to
+// import this package.
+
+type _MessageSet_Item struct {
+ TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
+ Message []byte `protobuf:"bytes,3,req,name=message"`
+}
+
+type MessageSet struct {
+ Item []*_MessageSet_Item `protobuf:"group,1,rep"`
+ XXX_unrecognized *bytes.Buffer
+ // TODO: caching?
+}
+
+// messageTypeIder is an interface satisfied by a protocol buffer type
+// that may be stored in a MessageSet.
+type messageTypeIder interface {
+ MessageTypeId() int32
+}
+
+func (ms *MessageSet) find(pb interface{}) *_MessageSet_Item {
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return nil
+ }
+ id := mti.MessageTypeId()
+ for _, item := range ms.Item {
+ if *item.TypeId == id {
+ return item
+ }
+ }
+ return nil
+}
+
+func (ms *MessageSet) Has(pb interface{}) bool {
+ if ms.find(pb) != nil {
+ return true
+ }
+ return false
+}
+
+func (ms *MessageSet) Unmarshal(pb interface{}) os.Error {
+ if item := ms.find(pb); item != nil {
+ return Unmarshal(item.Message, pb)
+ }
+ if _, ok := pb.(messageTypeIder); !ok {
+ return ErrNoMessageTypeId
+ }
+ return nil // TODO: return error instead?
+}
+
+func (ms *MessageSet) Marshal(pb interface{}) os.Error {
+ msg, err := Marshal(pb)
+ if err != nil {
+ return err
+ }
+ if item := ms.find(pb); item != nil {
+ // reuse existing item
+ item.Message = msg
+ return nil
+ }
+
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return ErrWrongType // TODO: custom error?
+ }
+
+ mtid := mti.MessageTypeId()
+ ms.Item = append(ms.Item, &_MessageSet_Item{
+ TypeId: &mtid,
+ Message: msg,
+ })
+ return nil
+}
+
+// Support for the message_set_wire_format message option.
+
+func skipVarint(buf []byte) []byte {
+ i := 0
+ for ; buf[i]&0x80 != 0; i++ {
+ }
+ return buf[i+1:]
+}
+
+// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
+// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
+func MarshalMessageSet(m map[int32]Extension) ([]byte, os.Error) {
+ if err := encodeExtensionMap(m); err != nil {
+ return nil, err
+ }
+
+ ms := &MessageSet{Item: make([]*_MessageSet_Item, len(m))}
+ i := 0
+ for k, e := range m {
+ // Remove the wire type and field number varint, as well as the length varint.
+ msg := skipVarint(skipVarint(e.enc))
+
+ ms.Item[i] = &_MessageSet_Item{
+ TypeId: Int32(k),
+ Message: msg,
+ }
+ i++
+ }
+ return Marshal(ms)
+}
+
+// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
+// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
+func UnmarshalMessageSet(buf []byte, m map[int32]Extension) os.Error {
+ ms := new(MessageSet)
+ if err := Unmarshal(buf, ms); err != nil {
+ return err
+ }
+ for _, item := range ms.Item {
+ // restore wire type and field number varint, plus length varint.
+ b := EncodeVarint(uint64(*item.TypeId)<<3 | WireBytes)
+ b = append(b, EncodeVarint(uint64(len(item.Message)))...)
+ b = append(b, item.Message...)
+
+ m[*item.TypeId] = Extension{enc: b}
+ }
+ return nil
+}
+
+// A global registry of types that can be used in a MessageSet.
+
+var messageSetMap = make(map[int32]messageSetDesc)
+
+type messageSetDesc struct {
+ t reflect.Type // pointer to struct
+ name string
+}
+
+// RegisterMessageSetType is called from the generated code.
+func RegisterMessageSetType(i messageTypeIder, name string) {
+ messageSetMap[i.MessageTypeId()] = messageSetDesc{
+ t: reflect.TypeOf(i),
+ name: name,
+ }
+}
--- /dev/null
+// 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.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+ "unsafe"
+)
+
+const debug bool = false
+
+// Constants that identify the encoding of a value on the wire.
+const (
+ WireVarint = 0
+ WireFixed64 = 1
+ WireBytes = 2
+ WireStartGroup = 3
+ WireEndGroup = 4
+ WireFixed32 = 5
+)
+
+const startSize = 10 // initial slice/string sizes
+
+// Encoders are defined in encoder.go
+// An encoder outputs the full representation of a field, including its
+// tag and encoder type.
+type encoder func(p *Buffer, prop *Properties, base uintptr) os.Error
+
+// A valueEncoder encodes a single integer in a particular encoding.
+type valueEncoder func(o *Buffer, x uint64) os.Error
+
+// Decoders are defined in decode.go
+// A decoder creates a value from its wire representation.
+// Unrecognized subelements are saved in unrec.
+type decoder func(p *Buffer, prop *Properties, base uintptr, sbase uintptr) os.Error
+
+// A valueDecoder decodes a single integer in a particular encoding.
+type valueDecoder func(o *Buffer) (x uint64, err os.Error)
+
+// StructProperties represents properties for all the fields of a struct.
+type StructProperties struct {
+ Prop []*Properties // properties for each field
+ reqCount int // required count
+ tags map[int]int // map from proto tag to struct field number
+ origNames map[string]int // map from original name to struct field number
+ nscratch uintptr // size of scratch space
+}
+
+// Properties represents the protocol-specific behavior of a single struct field.
+type Properties struct {
+ Name string // name of the field, for error messages
+ OrigName string // original name before protocol compiler (always set)
+ Wire string
+ WireType int
+ Tag int
+ Required bool
+ Optional bool
+ Repeated bool
+ Packed bool // relevant for repeated primitives only
+ Enum string // set for enum types only
+ Default string // default value
+ def_uint64 uint64
+
+ enc encoder
+ valEnc valueEncoder // set for bool and numeric types only
+ offset uintptr
+ tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
+ tagbuf [8]byte
+ stype reflect.Type
+
+ dec decoder
+ valDec valueDecoder // set for bool and numeric types only
+ scratch uintptr
+ sizeof uintptr // calculations of scratch space
+ alignof uintptr
+
+ // If this is a packable field, this will be the decoder for the packed version of the field.
+ packedDec decoder
+}
+
+// String formats the properties in the protobuf struct field tag style.
+func (p *Properties) String() string {
+ s := p.Wire
+ s = ","
+ s += strconv.Itoa(p.Tag)
+ if p.Required {
+ s += ",req"
+ }
+ if p.Optional {
+ s += ",opt"
+ }
+ if p.Repeated {
+ s += ",rep"
+ }
+ if p.Packed {
+ s += ",packed"
+ }
+ if p.OrigName != p.Name {
+ s += ",name=" + p.OrigName
+ }
+ if len(p.Enum) > 0 {
+ s += ",enum=" + p.Enum
+ }
+ if len(p.Default) > 0 {
+ s += ",def=" + p.Default
+ }
+ return s
+}
+
+// Parse populates p by parsing a string in the protobuf struct field tag style.
+func (p *Properties) Parse(s string) {
+ // "bytes,49,opt,def=hello!,name=foo"
+ fields := strings.Split(s, ",") // breaks def=, but handled below.
+ if len(fields) < 2 {
+ fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
+ return
+ }
+
+ p.Wire = fields[0]
+ switch p.Wire {
+ case "varint":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeVarint
+ p.valDec = (*Buffer).DecodeVarint
+ case "fixed32":
+ p.WireType = WireFixed32
+ p.valEnc = (*Buffer).EncodeFixed32
+ p.valDec = (*Buffer).DecodeFixed32
+ case "fixed64":
+ p.WireType = WireFixed64
+ p.valEnc = (*Buffer).EncodeFixed64
+ p.valDec = (*Buffer).DecodeFixed64
+ case "zigzag32":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag32
+ p.valDec = (*Buffer).DecodeZigzag32
+ case "zigzag64":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag64
+ p.valDec = (*Buffer).DecodeZigzag64
+ case "bytes", "group":
+ p.WireType = WireBytes
+ // no numeric converter for non-numeric types
+ default:
+ fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
+ return
+ }
+
+ var err os.Error
+ p.Tag, err = strconv.Atoi(fields[1])
+ if err != nil {
+ return
+ }
+
+ for i := 2; i < len(fields); i++ {
+ f := fields[i]
+ switch {
+ case f == "req":
+ p.Required = true
+ case f == "opt":
+ p.Optional = true
+ case f == "rep":
+ p.Repeated = true
+ case f == "packed":
+ p.Packed = true
+ case len(f) >= 5 && f[0:5] == "name=":
+ p.OrigName = f[5:len(f)]
+ case len(f) >= 5 && f[0:5] == "enum=":
+ p.Enum = f[5:len(f)]
+ case len(f) >= 4 && f[0:4] == "def=":
+ p.Default = f[4:len(f)] // rest of string
+ if i+1 < len(fields) {
+ // Commas aren't escaped, and def is always last.
+ p.Default += "," + strings.Join(fields[i+1:len(fields)], ",")
+ break
+ }
+ }
+ }
+}
+
+func logNoSliceEnc(t1, t2 reflect.Type) {
+ fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
+}
+
+// Initialize the fields for encoding and decoding.
+func (p *Properties) setEncAndDec(typ reflect.Type) {
+ var vbool bool
+ var vbyte byte
+ var vint32 int32
+ var vint64 int64
+ var vfloat32 float32
+ var vfloat64 float64
+ var vstring string
+ var vslice []byte
+
+ p.enc = nil
+ p.dec = nil
+
+ switch t1 := typ; t1.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no coders for %T\n", t1)
+ break
+
+ case reflect.Ptr:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no encoder function for %T -> %T\n", t1, t2)
+ break
+ case reflect.Bool:
+ p.enc = (*Buffer).enc_bool
+ p.dec = (*Buffer).dec_bool
+ p.alignof = unsafe.Alignof(vbool)
+ p.sizeof = unsafe.Sizeof(vbool)
+ case reflect.Int32, reflect.Uint32:
+ p.enc = (*Buffer).enc_int32
+ p.dec = (*Buffer).dec_int32
+ p.alignof = unsafe.Alignof(vint32)
+ p.sizeof = unsafe.Sizeof(vint32)
+ case reflect.Int64, reflect.Uint64:
+ p.enc = (*Buffer).enc_int64
+ p.dec = (*Buffer).dec_int64
+ p.alignof = unsafe.Alignof(vint64)
+ p.sizeof = unsafe.Sizeof(vint64)
+ case reflect.Float32:
+ p.enc = (*Buffer).enc_int32 // can just treat them as bits
+ p.dec = (*Buffer).dec_int32
+ p.alignof = unsafe.Alignof(vfloat32)
+ p.sizeof = unsafe.Sizeof(vfloat32)
+ case reflect.Float64:
+ p.enc = (*Buffer).enc_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_int64
+ p.alignof = unsafe.Alignof(vfloat64)
+ p.sizeof = unsafe.Sizeof(vfloat64)
+ case reflect.String:
+ p.enc = (*Buffer).enc_string
+ p.dec = (*Buffer).dec_string
+ p.alignof = unsafe.Alignof(vstring)
+ p.sizeof = unsafe.Sizeof(vstring) + startSize*unsafe.Sizeof(vbyte)
+ case reflect.Struct:
+ p.stype = t1
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_struct_message
+ p.dec = (*Buffer).dec_struct_message
+ } else {
+ p.enc = (*Buffer).enc_struct_group
+ p.dec = (*Buffer).dec_struct_group
+ }
+ }
+
+ case reflect.Slice:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ case reflect.Bool:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_bool
+ } else {
+ p.enc = (*Buffer).enc_slice_bool
+ }
+ p.dec = (*Buffer).dec_slice_bool
+ p.packedDec = (*Buffer).dec_slice_packed_bool
+ p.alignof = unsafe.Alignof(vbool)
+ p.sizeof = startSize * unsafe.Sizeof(vbool)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch t2.Bits() {
+ case 32:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int32
+ } else {
+ p.enc = (*Buffer).enc_slice_int32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ p.alignof = unsafe.Alignof(vint32)
+ p.sizeof = startSize * unsafe.Sizeof(vint32)
+ case 64:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ p.alignof = unsafe.Alignof(vint64)
+ p.sizeof = startSize * unsafe.Sizeof(vint64)
+ case 8:
+ if t2.Kind() == reflect.Uint8 {
+ p.enc = (*Buffer).enc_slice_byte
+ p.dec = (*Buffer).dec_slice_byte
+ p.alignof = unsafe.Alignof(vbyte)
+ p.sizeof = startSize * unsafe.Sizeof(vbyte)
+ }
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ }
+ case reflect.Float32, reflect.Float64:
+ switch t2.Bits() {
+ case 32:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int32
+ } else {
+ p.enc = (*Buffer).enc_slice_int32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ p.alignof = unsafe.Alignof(vfloat32)
+ p.sizeof = startSize * unsafe.Sizeof(vfloat32)
+ case 64:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ p.alignof = unsafe.Alignof(vfloat64)
+ p.sizeof = startSize * unsafe.Sizeof(vfloat64)
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ }
+ case reflect.String:
+ p.enc = (*Buffer).enc_slice_string
+ p.dec = (*Buffer).dec_slice_string
+ p.alignof = unsafe.Alignof(vstring)
+ p.sizeof = startSize * unsafe.Sizeof(vstring)
+ case reflect.Ptr:
+ switch t3 := t2.Elem(); t3.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
+ break
+ case reflect.Struct:
+ p.stype = t2
+ p.enc = (*Buffer).enc_slice_struct_group
+ p.dec = (*Buffer).dec_slice_struct_group
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_slice_struct_message
+ p.dec = (*Buffer).dec_slice_struct_message
+ }
+ p.alignof = unsafe.Alignof(vslice)
+ p.sizeof = startSize * unsafe.Sizeof(vslice)
+ }
+ case reflect.Slice:
+ switch t2.Elem().Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
+ break
+ case reflect.Uint8:
+ p.enc = (*Buffer).enc_slice_slice_byte
+ p.dec = (*Buffer).dec_slice_slice_byte
+ p.alignof = unsafe.Alignof(vslice)
+ p.sizeof = startSize * unsafe.Sizeof(vslice)
+ }
+ }
+ }
+
+ // precalculate tag code
+ wire := p.WireType
+ if p.Packed {
+ wire = WireBytes
+ }
+ x := uint32(p.Tag)<<3 | uint32(wire)
+ i := 0
+ for i = 0; x > 127; i++ {
+ p.tagbuf[i] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ p.tagbuf[i] = uint8(x)
+ p.tagcode = p.tagbuf[0 : i+1]
+}
+
+// Init populates the properties from a protocol buffer struct tag.
+func (p *Properties) Init(typ reflect.Type, name, tag string, offset uintptr) {
+ // "bytes,49,opt,def=hello!"
+ p.Name = name
+ p.OrigName = name
+ p.offset = offset
+
+ if tag == "" {
+ return
+ }
+ p.Parse(tag)
+ p.setEncAndDec(typ)
+}
+
+var (
+ mutex sync.Mutex
+ propertiesMap = make(map[reflect.Type]*StructProperties)
+)
+
+// GetProperties returns the list of properties for the type represented by t.
+func GetProperties(t reflect.Type) *StructProperties {
+ mutex.Lock()
+ if prop, ok := propertiesMap[t]; ok {
+ mutex.Unlock()
+ stats.Chit++
+ return prop
+ }
+ stats.Cmiss++
+
+ prop := new(StructProperties)
+
+ // build properties
+ prop.Prop = make([]*Properties, t.NumField())
+ prop.origNames = make(map[string]int)
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ p := new(Properties)
+ p.Init(f.Type, f.Name, f.Tag.Get("protobuf"), f.Offset)
+ if f.Name == "XXX_extensions" { // special case
+ var vmap map[int32][]byte
+ p.enc = (*Buffer).enc_map
+ p.dec = nil // not needed
+ p.alignof = unsafe.Alignof(vmap)
+ p.sizeof = unsafe.Sizeof(vmap)
+ }
+ prop.Prop[i] = p
+ prop.origNames[p.OrigName] = i
+ if debug {
+ print(i, " ", f.Name, " ", t.String(), " ")
+ if p.Tag > 0 {
+ print(p.String())
+ }
+ print("\n")
+ }
+ if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") {
+ fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
+ }
+ }
+
+ // build required counts
+ // build scratch offsets
+ // build tags
+ reqCount := 0
+ scratch := uintptr(0)
+ prop.tags = make(map[int]int)
+ for i, p := range prop.Prop {
+ if p.Required {
+ reqCount++
+ }
+ scratch = align(scratch, p.alignof)
+ p.scratch = scratch
+ scratch += p.sizeof
+ prop.tags[p.Tag] = i
+ }
+ prop.reqCount = reqCount
+ prop.nscratch = scratch
+
+ propertiesMap[t] = prop
+ mutex.Unlock()
+ return prop
+}
+
+// Alignment of the data in the scratch area. It doesn't have to be
+// exact, just conservative. Returns the first number >= o that divides s.
+func align(o uintptr, s uintptr) uintptr {
+ if s != 0 {
+ for o%uintptr(s) != 0 {
+ o++
+ }
+ }
+ return o
+}
+
+// Return the field index of the named field.
+// Returns nil if there is no such field.
+func fieldIndex(t reflect.Type, name string) []int {
+ if field, ok := t.FieldByName(name); ok {
+ return field.Index
+ }
+ return nil
+}
+
+// Return the Properties object for the x[0]'th field of the structure.
+func propByIndex(t reflect.Type, x []int) *Properties {
+ if len(x) != 1 {
+ fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
+ return nil
+ }
+ prop := GetProperties(t)
+ return prop.Prop[x[0]]
+}
+
+// Get the address and type of a pointer to a struct from an interface.
+// unsafe.Reflect can do this, but does multiple mallocs.
+func getbase(pb interface{}) (t reflect.Type, b uintptr, err os.Error) {
+ // get pointer
+ x := *(*[2]uintptr)(unsafe.Pointer(&pb))
+ b = x[1]
+ if b == 0 {
+ err = ErrNil
+ return
+ }
+
+ // get the reflect type of the struct.
+ t = reflect.TypeOf(pb)
+ return
+}
+
+// Allocate the aux space containing all the decoded data. The structure
+// handed into Unmarshal is filled with pointers to this newly allocated
+// data.
+func getsbase(prop *StructProperties) uintptr {
+ var vbyteptr *byte
+ if prop.nscratch == 0 {
+ return 0
+ }
+
+ // allocate the decode space as pointers
+ // so that the GC will scan it for pointers
+ n := uintptr(unsafe.Sizeof(vbyteptr))
+ b := make([]*byte, (prop.nscratch+n-1)/n)
+ sbase := uintptr(unsafe.Pointer(&b[0]))
+ return sbase
+}
+
+// A global registry of enum types.
+// The generated code will register the generated maps by calling RegisterEnum.
+
+var enumNameMaps = make(map[string]map[int32]string)
+var enumValueMaps = make(map[string]map[string]int32)
+
+// RegisterEnum is called from the generated code to install the enum descriptor
+// maps into the global table to aid parsing ASCII protocol buffers.
+func RegisterEnum(typeName string, nameMap map[int32]string, valueMap map[string]int32) {
+ if _, ok := enumNameMaps[typeName]; ok {
+ panic("proto: duplicate enum registered: " + typeName)
+ }
+ enumNameMaps[typeName] = nameMap
+ enumValueMaps[typeName] = valueMap
+}
--- /dev/null
+# 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.
+
+
+include $(GOROOT)/src/Make.inc
+include ../../Make.protobuf
+
+TARG=test_proto
+GOFILES=\
+ test.pb.go\
+
+include $(GOROOT)/src/Make.pkg
+
+CLEANFILES+=test.pb.go
+
+# These rules are just aids to development. Not needed for testing.
+regenerate:
+ rm test.pb.go
+ make test.pb.go
+
+restore:
+ cp test.pb.go.golden test.pb.go
+
+preserve:
+ cp test.pb.go test.pb.go.golden
--- /dev/null
+// Code generated by protoc-gen-go from "test.proto"
+// DO NOT EDIT!
+
+package test_proto
+
+import proto "goprotobuf.googlecode.com/hg/proto"
+import "math"
+import "os"
+
+// Reference proto, math & os imports to suppress error if they are not otherwise used.
+var _ = proto.GetString
+var _ = math.Inf
+var _ os.Error
+
+
+type FOO int32
+
+const (
+ FOO_FOO1 = 1
+)
+
+var FOO_name = map[int32]string{
+ 1: "FOO1",
+}
+var FOO_value = map[string]int32{
+ "FOO1": 1,
+}
+
+func NewFOO(x int32) *FOO {
+ e := FOO(x)
+ return &e
+}
+func (x FOO) String() string {
+ return proto.EnumName(FOO_name, int32(x))
+}
+
+type GoTest_KIND int32
+
+const (
+ GoTest_VOID = 0
+ GoTest_BOOL = 1
+ GoTest_BYTES = 2
+ GoTest_FINGERPRINT = 3
+ GoTest_FLOAT = 4
+ GoTest_INT = 5
+ GoTest_STRING = 6
+ GoTest_TIME = 7
+ GoTest_TUPLE = 8
+ GoTest_ARRAY = 9
+ GoTest_MAP = 10
+ GoTest_TABLE = 11
+ GoTest_FUNCTION = 12
+)
+
+var GoTest_KIND_name = map[int32]string{
+ 0: "VOID",
+ 1: "BOOL",
+ 2: "BYTES",
+ 3: "FINGERPRINT",
+ 4: "FLOAT",
+ 5: "INT",
+ 6: "STRING",
+ 7: "TIME",
+ 8: "TUPLE",
+ 9: "ARRAY",
+ 10: "MAP",
+ 11: "TABLE",
+ 12: "FUNCTION",
+}
+var GoTest_KIND_value = map[string]int32{
+ "VOID": 0,
+ "BOOL": 1,
+ "BYTES": 2,
+ "FINGERPRINT": 3,
+ "FLOAT": 4,
+ "INT": 5,
+ "STRING": 6,
+ "TIME": 7,
+ "TUPLE": 8,
+ "ARRAY": 9,
+ "MAP": 10,
+ "TABLE": 11,
+ "FUNCTION": 12,
+}
+
+func NewGoTest_KIND(x int32) *GoTest_KIND {
+ e := GoTest_KIND(x)
+ return &e
+}
+func (x GoTest_KIND) String() string {
+ return proto.EnumName(GoTest_KIND_name, int32(x))
+}
+
+type MyMessage_Color int32
+
+const (
+ MyMessage_RED = 0
+ MyMessage_GREEN = 1
+ MyMessage_BLUE = 2
+)
+
+var MyMessage_Color_name = map[int32]string{
+ 0: "RED",
+ 1: "GREEN",
+ 2: "BLUE",
+}
+var MyMessage_Color_value = map[string]int32{
+ "RED": 0,
+ "GREEN": 1,
+ "BLUE": 2,
+}
+
+func NewMyMessage_Color(x int32) *MyMessage_Color {
+ e := MyMessage_Color(x)
+ return &e
+}
+func (x MyMessage_Color) String() string {
+ return proto.EnumName(MyMessage_Color_name, int32(x))
+}
+
+type GoEnum struct {
+ Foo *FOO `protobuf:"varint,1,req,name=foo,enum=test_proto.FOO"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoEnum) Reset() { *this = GoEnum{} }
+func (this *GoEnum) String() string { return proto.CompactTextString(this) }
+
+type GoTestField struct {
+ Label *string `protobuf:"bytes,1,req"`
+ Type *string `protobuf:"bytes,2,req"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoTestField) Reset() { *this = GoTestField{} }
+func (this *GoTestField) String() string { return proto.CompactTextString(this) }
+
+type GoTest struct {
+ Kind *int32 `protobuf:"varint,1,req"`
+ Table *string `protobuf:"bytes,2,opt"`
+ Param *int32 `protobuf:"varint,3,opt"`
+ RequiredField *GoTestField `protobuf:"bytes,4,req"`
+ RepeatedField []*GoTestField `protobuf:"bytes,5,rep"`
+ OptionalField *GoTestField `protobuf:"bytes,6,opt"`
+ F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required"`
+ F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required"`
+ F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required"`
+ F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required"`
+ F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required"`
+ F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required"`
+ F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required"`
+ F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required"`
+ F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required"`
+ F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required"`
+ F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required"`
+ F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required"`
+ F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required"`
+ F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated"`
+ F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated"`
+ F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated"`
+ F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated"`
+ F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated"`
+ F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated"`
+ F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated"`
+ F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated"`
+ F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated"`
+ F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated"`
+ F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated"`
+ F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated"`
+ F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated"`
+ F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional"`
+ F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional"`
+ F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional"`
+ F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional"`
+ F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional"`
+ F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional"`
+ F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional"`
+ F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional"`
+ F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional"`
+ F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional"`
+ F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional"`
+ F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional"`
+ F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional"`
+ F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,def=1"`
+ F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,def=32"`
+ F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,def=64"`
+ F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,def=320"`
+ F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,def=640"`
+ F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,def=3200"`
+ F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,def=6400"`
+ F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,def=314159"`
+ F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,def=271828"`
+ F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,def=hello, \\\"world!\\\"\\n"`
+ F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,def=Bignose"`
+ F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,def=-32"`
+ F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,def=-64"`
+ F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed"`
+ F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed"`
+ F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed"`
+ F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed"`
+ F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed"`
+ F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed"`
+ F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed"`
+ F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed"`
+ F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed"`
+ F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed"`
+ F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed"`
+ Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup"`
+ Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup"`
+ Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoTest) Reset() { *this = GoTest{} }
+func (this *GoTest) String() string { return proto.CompactTextString(this) }
+
+const Default_GoTest_F_BoolDefaulted bool = true
+const Default_GoTest_F_Int32Defaulted int32 = 32
+const Default_GoTest_F_Int64Defaulted int64 = 64
+const Default_GoTest_F_Fixed32Defaulted uint32 = 320
+const Default_GoTest_F_Fixed64Defaulted uint64 = 640
+const Default_GoTest_F_Uint32Defaulted uint32 = 3200
+const Default_GoTest_F_Uint64Defaulted uint64 = 6400
+const Default_GoTest_F_FloatDefaulted float32 = 314159
+const Default_GoTest_F_DoubleDefaulted float64 = 271828
+const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n"
+
+var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose")
+
+const Default_GoTest_F_Sint32Defaulted int32 = -32
+const Default_GoTest_F_Sint64Defaulted int64 = -64
+
+type GoTest_RequiredGroup struct {
+ RequiredField *string `protobuf:"bytes,71,req"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoTest_RequiredGroup) Reset() { *this = GoTest_RequiredGroup{} }
+func (this *GoTest_RequiredGroup) String() string { return proto.CompactTextString(this) }
+
+type GoTest_RepeatedGroup struct {
+ RequiredField *string `protobuf:"bytes,81,req"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoTest_RepeatedGroup) Reset() { *this = GoTest_RepeatedGroup{} }
+func (this *GoTest_RepeatedGroup) String() string { return proto.CompactTextString(this) }
+
+type GoTest_OptionalGroup struct {
+ RequiredField *string `protobuf:"bytes,91,req"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoTest_OptionalGroup) Reset() { *this = GoTest_OptionalGroup{} }
+func (this *GoTest_OptionalGroup) String() string { return proto.CompactTextString(this) }
+
+type GoSkipTest struct {
+ SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32"`
+ SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32"`
+ SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64"`
+ SkipString *string `protobuf:"bytes,14,req,name=skip_string"`
+ Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoSkipTest) Reset() { *this = GoSkipTest{} }
+func (this *GoSkipTest) String() string { return proto.CompactTextString(this) }
+
+type GoSkipTest_SkipGroup struct {
+ GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32"`
+ GroupString *string `protobuf:"bytes,17,req,name=group_string"`
+ XXX_unrecognized []byte
+}
+
+func (this *GoSkipTest_SkipGroup) Reset() { *this = GoSkipTest_SkipGroup{} }
+func (this *GoSkipTest_SkipGroup) String() string { return proto.CompactTextString(this) }
+
+type NonPackedTest struct {
+ A []int32 `protobuf:"varint,1,rep,name=a"`
+ XXX_unrecognized []byte
+}
+
+func (this *NonPackedTest) Reset() { *this = NonPackedTest{} }
+func (this *NonPackedTest) String() string { return proto.CompactTextString(this) }
+
+type PackedTest struct {
+ B []int32 `protobuf:"varint,1,rep,packed,name=b"`
+ XXX_unrecognized []byte
+}
+
+func (this *PackedTest) Reset() { *this = PackedTest{} }
+func (this *PackedTest) String() string { return proto.CompactTextString(this) }
+
+type InnerMessage struct {
+ Host *string `protobuf:"bytes,1,req,name=host"`
+ Port *int32 `protobuf:"varint,2,opt,name=port,def=4000"`
+ Connected *bool `protobuf:"varint,3,opt,name=connected"`
+ XXX_unrecognized []byte
+}
+
+func (this *InnerMessage) Reset() { *this = InnerMessage{} }
+func (this *InnerMessage) String() string { return proto.CompactTextString(this) }
+
+const Default_InnerMessage_Port int32 = 4000
+
+type OtherMessage struct {
+ Key *int64 `protobuf:"varint,1,opt,name=key"`
+ Value []byte `protobuf:"bytes,2,opt,name=value"`
+ Weight *float32 `protobuf:"fixed32,3,opt,name=weight"`
+ Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner"`
+ XXX_unrecognized []byte
+}
+
+func (this *OtherMessage) Reset() { *this = OtherMessage{} }
+func (this *OtherMessage) String() string { return proto.CompactTextString(this) }
+
+type MyMessage struct {
+ Count *int32 `protobuf:"varint,1,req,name=count"`
+ Name *string `protobuf:"bytes,2,opt,name=name"`
+ Quote *string `protobuf:"bytes,3,opt,name=quote"`
+ Pet []string `protobuf:"bytes,4,rep,name=pet"`
+ Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner"`
+ Others []*OtherMessage `protobuf:"bytes,6,rep,name=others"`
+ Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=test_proto.MyMessage_Color"`
+ Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup"`
+ XXX_extensions map[int32][]byte
+ XXX_unrecognized []byte
+}
+
+func (this *MyMessage) Reset() { *this = MyMessage{} }
+func (this *MyMessage) String() string { return proto.CompactTextString(this) }
+
+var extRange_MyMessage = []proto.ExtensionRange{
+ proto.ExtensionRange{100, 536870911},
+}
+
+func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MyMessage
+}
+func (this *MyMessage) ExtensionMap() map[int32][]byte {
+ if this.XXX_extensions == nil {
+ this.XXX_extensions = make(map[int32][]byte)
+ }
+ return this.XXX_extensions
+}
+
+type MyMessage_SomeGroup struct {
+ GroupField *int32 `protobuf:"varint,9,opt,name=group_field"`
+ XXX_unrecognized []byte
+}
+
+func (this *MyMessage_SomeGroup) Reset() { *this = MyMessage_SomeGroup{} }
+func (this *MyMessage_SomeGroup) String() string { return proto.CompactTextString(this) }
+
+type Ext struct {
+ Data *string `protobuf:"bytes,1,opt,name=data"`
+ XXX_unrecognized []byte
+}
+
+func (this *Ext) Reset() { *this = Ext{} }
+func (this *Ext) String() string { return proto.CompactTextString(this) }
+
+var E_Ext_More = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessage)(nil),
+ ExtensionType: (*Ext)(nil),
+ Field: 103,
+ Name: "test_proto.more",
+ Tag: "bytes,103,opt,name=more",
+}
+
+type MessageList struct {
+ Message []*MessageList_Message `protobuf:"group,1,rep"`
+ XXX_unrecognized []byte
+}
+
+func (this *MessageList) Reset() { *this = MessageList{} }
+func (this *MessageList) String() string { return proto.CompactTextString(this) }
+
+type MessageList_Message struct {
+ Name *string `protobuf:"bytes,2,req,name=name"`
+ Count *int32 `protobuf:"varint,3,req,name=count"`
+ XXX_unrecognized []byte
+}
+
+func (this *MessageList_Message) Reset() { *this = MessageList_Message{} }
+func (this *MessageList_Message) String() string { return proto.CompactTextString(this) }
+
+func init() {
+ proto.RegisterEnum("test_proto.FOO", FOO_name, FOO_value)
+ proto.RegisterEnum("test_proto.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value)
+ proto.RegisterEnum("test_proto.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value)
+ proto.RegisterExtension(E_Ext_More)
+}
--- /dev/null
+// 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.
+
+// A feature-rich test file for the protocol compiler and libraries.
+
+syntax = "proto2";
+
+package test_proto;
+
+enum FOO { FOO1 = 1; };
+
+message GoEnum {
+ required FOO foo = 1;
+}
+
+message GoTestField {
+ required string Label = 1;
+ required string Type = 2;
+}
+
+message GoTest {
+ // An enum, for completeness.
+ enum KIND {
+ VOID = 0;
+
+ // Basic types
+ BOOL = 1;
+ BYTES = 2;
+ FINGERPRINT = 3;
+ FLOAT = 4;
+ INT = 5;
+ STRING = 6;
+ TIME = 7;
+
+ // Groupings
+ TUPLE = 8;
+ ARRAY = 9;
+ MAP = 10;
+
+ // Table types
+ TABLE = 11;
+
+ // Functions
+ FUNCTION = 12; // last tag
+ };
+
+ // Some typical parameters
+ required KIND Kind = 1;
+ optional string Table = 2;
+ optional int32 Param = 3;
+
+ // Required, repeated and optional foreign fields.
+ required GoTestField RequiredField = 4;
+ repeated GoTestField RepeatedField = 5;
+ optional GoTestField OptionalField = 6;
+
+ // Required fields of all basic types
+ required bool F_Bool_required = 10;
+ required int32 F_Int32_required = 11;
+ required int64 F_Int64_required = 12;
+ required fixed32 F_Fixed32_required = 13;
+ required fixed64 F_Fixed64_required = 14;
+ required uint32 F_Uint32_required = 15;
+ required uint64 F_Uint64_required = 16;
+ required float F_Float_required = 17;
+ required double F_Double_required = 18;
+ required string F_String_required = 19;
+ required bytes F_Bytes_required = 101;
+ required sint32 F_Sint32_required = 102;
+ required sint64 F_Sint64_required = 103;
+
+ // Repeated fields of all basic types
+ repeated bool F_Bool_repeated = 20;
+ repeated int32 F_Int32_repeated = 21;
+ repeated int64 F_Int64_repeated = 22;
+ repeated fixed32 F_Fixed32_repeated = 23;
+ repeated fixed64 F_Fixed64_repeated = 24;
+ repeated uint32 F_Uint32_repeated = 25;
+ repeated uint64 F_Uint64_repeated = 26;
+ repeated float F_Float_repeated = 27;
+ repeated double F_Double_repeated = 28;
+ repeated string F_String_repeated = 29;
+ repeated bytes F_Bytes_repeated = 201;
+ repeated sint32 F_Sint32_repeated = 202;
+ repeated sint64 F_Sint64_repeated = 203;
+
+ // Optional fields of all basic types
+ optional bool F_Bool_optional = 30;
+ optional int32 F_Int32_optional = 31;
+ optional int64 F_Int64_optional = 32;
+ optional fixed32 F_Fixed32_optional = 33;
+ optional fixed64 F_Fixed64_optional = 34;
+ optional uint32 F_Uint32_optional = 35;
+ optional uint64 F_Uint64_optional = 36;
+ optional float F_Float_optional = 37;
+ optional double F_Double_optional = 38;
+ optional string F_String_optional = 39;
+ optional bytes F_Bytes_optional = 301;
+ optional sint32 F_Sint32_optional = 302;
+ optional sint64 F_Sint64_optional = 303;
+
+ // Default-valued fields of all basic types
+ optional bool F_Bool_defaulted = 40 [default=true];
+ optional int32 F_Int32_defaulted = 41 [default=32];
+ optional int64 F_Int64_defaulted = 42 [default=64];
+ optional fixed32 F_Fixed32_defaulted = 43 [default=320];
+ optional fixed64 F_Fixed64_defaulted = 44 [default=640];
+ optional uint32 F_Uint32_defaulted = 45 [default=3200];
+ optional uint64 F_Uint64_defaulted = 46 [default=6400];
+ optional float F_Float_defaulted = 47 [default=314159.];
+ optional double F_Double_defaulted = 48 [default=271828.];
+ optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"];
+ optional bytes F_Bytes_defaulted = 401 [default="Bignose"];
+ optional sint32 F_Sint32_defaulted = 402 [default = -32];
+ optional sint64 F_Sint64_defaulted = 403 [default = -64];
+
+ // Packed repeated fields (no string or bytes).
+ repeated bool F_Bool_repeated_packed = 50 [packed=true];
+ repeated int32 F_Int32_repeated_packed = 51 [packed=true];
+ repeated int64 F_Int64_repeated_packed = 52 [packed=true];
+ repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true];
+ repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true];
+ repeated uint32 F_Uint32_repeated_packed = 55 [packed=true];
+ repeated uint64 F_Uint64_repeated_packed = 56 [packed=true];
+ repeated float F_Float_repeated_packed = 57 [packed=true];
+ repeated double F_Double_repeated_packed = 58 [packed=true];
+ repeated sint32 F_Sint32_repeated_packed = 502 [packed=true];
+ repeated sint64 F_Sint64_repeated_packed = 503 [packed=true];
+
+ // Required, repeated, and optional groups.
+ required group RequiredGroup = 70 {
+ required string RequiredField = 71;
+ };
+
+ repeated group RepeatedGroup = 80 {
+ required string RequiredField = 81;
+ };
+
+ optional group OptionalGroup = 90 {
+ required string RequiredField = 91;
+ };
+}
+
+// For testing skipping of unrecognized fields.
+// Numbers are all big, larger than tag numbers in GoTestField,
+// the message used in the corresponding test.
+message GoSkipTest {
+ required int32 skip_int32 = 11;
+ required fixed32 skip_fixed32 = 12;
+ required fixed64 skip_fixed64 = 13;
+ required string skip_string = 14;
+ required group SkipGroup = 15 {
+ required int32 group_int32 = 16;
+ required string group_string = 17;
+ }
+}
+
+// For testing packed/non-packed decoder switching.
+// A serialized instance of one should be deserializable as the other.
+message NonPackedTest {
+ repeated int32 a = 1;
+}
+
+message PackedTest {
+ repeated int32 b = 1 [packed=true];
+}
+
+message MaxTag {
+ // Maximum possible tag number.
+ optional string last_field = 536870911;
+}
+
+// Smaller tests for ASCII formatting.
+
+message InnerMessage {
+ required string host = 1;
+ optional int32 port = 2 [default=4000];
+ optional bool connected = 3;
+}
+
+message OtherMessage {
+ optional int64 key = 1;
+ optional bytes value = 2;
+ optional float weight = 3;
+ optional InnerMessage inner = 4;
+}
+
+message MyMessage {
+ required int32 count = 1;
+ optional string name = 2;
+ optional string quote = 3;
+ repeated string pet = 4;
+ optional InnerMessage inner = 5;
+ repeated OtherMessage others = 6;
+
+ enum Color {
+ RED = 0;
+ GREEN = 1;
+ BLUE = 2;
+ };
+ optional Color bikeshed = 7;
+
+ optional group SomeGroup = 8 {
+ optional int32 group_field = 9;
+ }
+
+ // This field becomes [][]byte in the generated code.
+ repeated bytes rep_bytes = 10;
+
+ extensions 100 to max;
+}
+
+message Ext {
+ extend MyMessage {
+ optional Ext more = 103;
+ }
+
+ optional string data = 1;
+}
+
+message MessageList {
+ repeated group Message = 1 {
+ required string name = 2;
+ required int32 count = 3;
+ }
+}
+
+message Strings {
+ optional string string_field = 1;
+ optional bytes bytes_field = 2;
+}
+
+message Defaults {
+ enum Color {
+ RED = 0;
+ GREEN = 1;
+ BLUE = 2;
+ }
+
+ // Default-valued fields of all basic types.
+ // Same as GoTest, but copied here to make testing easier.
+ optional bool F_Bool = 1 [default=true];
+ optional int32 F_Int32 = 2 [default=32];
+ optional int64 F_Int64 = 3 [default=64];
+ optional fixed32 F_Fixed32 = 4 [default=320];
+ optional fixed64 F_Fixed64 = 5 [default=640];
+ optional uint32 F_Uint32 = 6 [default=3200];
+ optional uint64 F_Uint64 = 7 [default=6400];
+ optional float F_Float = 8 [default=314159.];
+ optional double F_Double = 9 [default=271828.];
+ optional string F_String = 10 [default="hello, \"world!\"\n"];
+ optional bytes F_Bytes = 11 [default="Bignose"];
+ optional sint32 F_Sint32 = 12 [default=-32];
+ optional sint64 F_Sint64 = 13 [default=-64];
+ optional Color F_Enum = 14 [default=GREEN];
+
+ // More fields with crazy defaults.
+ optional float F_Pinf = 15 [default=inf];
+ optional float F_Ninf = 16 [default=-inf];
+ optional float F_Nan = 17 [default=nan];
+}
--- /dev/null
+// 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.
+
+package proto
+
+// Functions for writing the text protocol buffer format.
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "reflect"
+ "sort"
+ "strings"
+)
+
+// textWriter is an io.Writer that tracks its indentation level.
+type textWriter struct {
+ ind int
+ complete bool // if the current position is a complete line
+ compact bool // whether to write out as a one-liner
+ writer io.Writer
+
+ c [1]byte // scratch
+}
+
+func (w *textWriter) Write(p []byte) (n int, err os.Error) {
+ n, err = len(p), nil
+
+ frags := strings.Split(string(p), "\n")
+ if w.compact {
+ w.writer.Write([]byte(strings.Join(frags, " ")))
+ return
+ }
+
+ for i, frag := range frags {
+ if w.complete {
+ for j := 0; j < w.ind; j++ {
+ w.writer.Write([]byte{' ', ' '})
+ }
+ w.complete = false
+ }
+
+ w.writer.Write([]byte(frag))
+ if i+1 < len(frags) {
+ w.writer.Write([]byte{'\n'})
+ }
+ }
+ w.complete = len(frags[len(frags)-1]) == 0
+
+ return
+}
+
+func (w *textWriter) WriteByte(c byte) os.Error {
+ w.c[0] = c
+ _, err := w.Write(w.c[:])
+ return err
+}
+
+func (w *textWriter) indent() { w.ind++ }
+
+func (w *textWriter) unindent() {
+ if w.ind == 0 {
+ log.Printf("proto: textWriter unindented too far!")
+ return
+ }
+ w.ind--
+}
+
+func writeName(w *textWriter, props *Properties) {
+ io.WriteString(w, props.OrigName)
+ if props.Wire != "group" {
+ w.WriteByte(':')
+ }
+}
+
+var (
+ messageSetType = reflect.TypeOf((*MessageSet)(nil)).Elem()
+ extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
+)
+
+func writeStruct(w *textWriter, sv reflect.Value) {
+ if sv.Type() == messageSetType {
+ writeMessageSet(w, sv.Addr().Interface().(*MessageSet))
+ return
+ }
+
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < sv.NumField(); i++ {
+ fv := sv.Field(i)
+ if name := st.Field(i).Name; strings.HasPrefix(name, "XXX_") {
+ // There's only two XXX_ fields:
+ // XXX_unrecognized []byte
+ // XXX_extensions map[int32]proto.Extension
+ // The first is handled here;
+ // the second is handled at the bottom of this function.
+ if name == "XXX_unrecognized" && !fv.IsNil() {
+ writeUnknownStruct(w, fv.Interface().([]byte))
+ }
+ continue
+ }
+ props := sprops.Prop[i]
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ // Field not filled in. This could be an optional field or
+ // a required field that wasn't filled in. Either way, there
+ // isn't anything we can show for it.
+ continue
+ }
+ if fv.Kind() == reflect.Slice && fv.IsNil() {
+ // Repeated field that is empty, or a bytes field that is unused.
+ continue
+ }
+
+ if props.Repeated && fv.Kind() == reflect.Slice {
+ // Repeated field.
+ for j := 0; j < fv.Len(); j++ {
+ writeName(w, props)
+ if !w.compact {
+ w.WriteByte(' ')
+ }
+ writeAny(w, fv.Index(j), props)
+ w.WriteByte('\n')
+ }
+ continue
+ }
+
+ writeName(w, props)
+ if !w.compact {
+ w.WriteByte(' ')
+ }
+ if props.Enum != "" && tryWriteEnum(w, props.Enum, fv) {
+ // Enum written.
+ } else {
+ writeAny(w, fv, props)
+ }
+ w.WriteByte('\n')
+ }
+
+ // Extensions (the XXX_extensions field).
+ pv := sv.Addr()
+ if pv.Type().Implements(extendableProtoType) {
+ writeExtensions(w, pv)
+ }
+}
+
+// tryWriteEnum attempts to write an enum value as a symbolic constant.
+// If the enum is unregistered, nothing is written and false is returned.
+func tryWriteEnum(w *textWriter, enum string, v reflect.Value) bool {
+ v = reflect.Indirect(v)
+ if v.Type().Kind() != reflect.Int32 {
+ return false
+ }
+ m, ok := enumNameMaps[enum]
+ if !ok {
+ return false
+ }
+ str, ok := m[int32(v.Int())]
+ if !ok {
+ return false
+ }
+ fmt.Fprintf(w, str)
+ return true
+}
+
+// writeAny writes an arbitrary field.
+func writeAny(w *textWriter, v reflect.Value, props *Properties) {
+ v = reflect.Indirect(v)
+
+ // We don't attempt to serialise every possible value type; only those
+ // that can occur in protocol buffers, plus a few extra that were easy.
+ switch v.Kind() {
+ case reflect.Slice:
+ // Should only be a []byte; repeated fields are handled in writeStruct.
+ writeString(w, string(v.Interface().([]byte)))
+ case reflect.String:
+ writeString(w, v.String())
+ case reflect.Struct:
+ // Required/optional group/message.
+ var bra, ket byte = '<', '>'
+ if props != nil && props.Wire == "group" {
+ bra, ket = '{', '}'
+ }
+ w.WriteByte(bra)
+ if !w.compact {
+ w.WriteByte('\n')
+ }
+ w.indent()
+ writeStruct(w, v)
+ w.unindent()
+ w.WriteByte(ket)
+ default:
+ fmt.Fprint(w, v.Interface())
+ }
+}
+
+// equivalent to C's isprint.
+func isprint(c byte) bool {
+ return c >= 0x20 && c < 0x7f
+}
+
+// writeString writes a string in the protocol buffer text format.
+// It is similar to strconv.Quote except we don't use Go escape sequences,
+// we treat the string as a byte sequence, and we use octal escapes.
+// These differences are to maintain interoperability with the other
+// languages' implementations of the text format.
+func writeString(w *textWriter, s string) {
+ w.WriteByte('"')
+
+ // Loop over the bytes, not the runes.
+ for i := 0; i < len(s); i++ {
+ // Divergence from C++: we don't escape apostrophes.
+ // There's no need to escape them, and the C++ parser
+ // copes with a naked apostrophe.
+ switch c := s[i]; c {
+ case '\n':
+ w.Write([]byte{'\\', 'n'})
+ case '\r':
+ w.Write([]byte{'\\', 'r'})
+ case '\t':
+ w.Write([]byte{'\\', 't'})
+ case '"':
+ w.Write([]byte{'\\', '"'})
+ case '\\':
+ w.Write([]byte{'\\', '\\'})
+ default:
+ if isprint(c) {
+ w.WriteByte(c)
+ } else {
+ fmt.Fprintf(w, "\\%03o", c)
+ }
+ }
+ }
+
+ w.WriteByte('"')
+}
+
+func writeMessageSet(w *textWriter, ms *MessageSet) {
+ for _, item := range ms.Item {
+ id := *item.TypeId
+ if msd, ok := messageSetMap[id]; ok {
+ // Known message set type.
+ fmt.Fprintf(w, "[%s]: <\n", msd.name)
+ w.indent()
+
+ pb := reflect.New(msd.t.Elem())
+ if err := Unmarshal(item.Message, pb.Interface()); err != nil {
+ fmt.Fprintf(w, "/* bad message: %v */\n", err)
+ } else {
+ writeStruct(w, pb.Elem())
+ }
+ } else {
+ // Unknown type.
+ fmt.Fprintf(w, "[%d]: <\n", id)
+ w.indent()
+ writeUnknownStruct(w, item.Message)
+ }
+ w.unindent()
+ w.Write([]byte(">\n"))
+ }
+}
+
+func writeUnknownStruct(w *textWriter, data []byte) {
+ if !w.compact {
+ fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data))
+ }
+ b := NewBuffer(data)
+ for b.index < len(b.buf) {
+ x, err := b.DecodeVarint()
+ if err != nil {
+ fmt.Fprintf(w, "/* %v */\n", err)
+ return
+ }
+ wire, tag := x&7, x>>3
+ if wire == WireEndGroup {
+ w.unindent()
+ w.Write([]byte("}\n"))
+ continue
+ }
+ fmt.Fprintf(w, "tag%d", tag)
+ if wire != WireStartGroup {
+ w.WriteByte(':')
+ }
+ if !w.compact || wire == WireStartGroup {
+ w.WriteByte(' ')
+ }
+ switch wire {
+ case WireBytes:
+ buf, err := b.DecodeRawBytes(false)
+ if err == nil {
+ fmt.Fprintf(w, "%q", buf)
+ } else {
+ fmt.Fprintf(w, "/* %v */", err)
+ }
+ case WireFixed32:
+ x, err := b.DecodeFixed32()
+ writeUnknownInt(w, x, err)
+ case WireFixed64:
+ x, err := b.DecodeFixed64()
+ writeUnknownInt(w, x, err)
+ case WireStartGroup:
+ fmt.Fprint(w, "{")
+ w.indent()
+ case WireVarint:
+ x, err := b.DecodeVarint()
+ writeUnknownInt(w, x, err)
+ default:
+ fmt.Fprintf(w, "/* unknown wire type %d */", wire)
+ }
+ w.WriteByte('\n')
+ }
+}
+
+func writeUnknownInt(w *textWriter, x uint64, err os.Error) {
+ if err == nil {
+ fmt.Fprint(w, x)
+ } else {
+ fmt.Fprintf(w, "/* %v */", err)
+ }
+}
+
+type int32Slice []int32
+
+func (s int32Slice) Len() int { return len(s) }
+func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
+func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// writeExtensions writes all the extensions in pv.
+// pv is assumed to be a pointer to a protocol message struct that is extendable.
+func writeExtensions(w *textWriter, pv reflect.Value) {
+ emap := extensionMaps[pv.Type().Elem()]
+ ep := pv.Interface().(extendableProto)
+
+ // Order the extensions by ID.
+ // This isn't strictly necessary, but it will give us
+ // canonical output, which will also make testing easier.
+ m := ep.ExtensionMap()
+ ids := make([]int32, 0, len(m))
+ for id := range m {
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids))
+
+ for _, extNum := range ids {
+ ext := m[extNum]
+ var desc *ExtensionDesc
+ if emap != nil {
+ desc = emap[extNum]
+ }
+ if desc == nil {
+ // Unknown extension.
+ writeUnknownStruct(w, ext.enc)
+ continue
+ }
+
+ pb, err := GetExtension(ep, desc)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "proto: failed getting extension: ", err)
+ continue
+ }
+
+ fmt.Fprintf(w, "[%s]:", desc.Name)
+ if !w.compact {
+ w.WriteByte(' ')
+ }
+ writeAny(w, reflect.ValueOf(pb), nil)
+ w.WriteByte('\n')
+ }
+}
+
+func marshalText(w io.Writer, pb interface{}, compact bool) {
+ if pb == nil {
+ w.Write([]byte("<nil>"))
+ return
+ }
+ aw := new(textWriter)
+ aw.writer = w
+ aw.complete = true
+ aw.compact = compact
+
+ v := reflect.ValueOf(pb)
+ // We should normally be passed a struct, or a pointer to a struct,
+ // and we don't want the outer < and > in that case.
+ v = reflect.Indirect(v)
+ if v.Kind() == reflect.Struct {
+ writeStruct(aw, v)
+ } else {
+ writeAny(aw, v, nil)
+ }
+}
+
+// MarshalText writes a given protocol buffer in text format.
+// Values that are not protocol buffers can also be written, but their formatting is not guaranteed.
+func MarshalText(w io.Writer, pb interface{}) { marshalText(w, pb, false) }
+
+// CompactText writes a given protocl buffer in compact text format (one line).
+// Values that are not protocol buffers can also be written, but their formatting is not guaranteed.
+func CompactText(w io.Writer, pb interface{}) { marshalText(w, pb, true) }
+
+// CompactTextString is the same as CompactText, but returns the string directly.
+func CompactTextString(pb interface{}) string {
+ buf := new(bytes.Buffer)
+ marshalText(buf, pb, true)
+ return buf.String()
+}
--- /dev/null
+// 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.
+
+package proto
+
+// Functions for parsing the Text protocol buffer format.
+// TODO: message sets, extensions.
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+)
+
+// ParseError satisfies the os.Error interface.
+type ParseError struct {
+ Message string
+ Line int // 1-based line number
+ Offset int // 0-based byte offset from start of input
+}
+
+func (p *ParseError) String() string {
+ if p.Line == 1 {
+ // show offset only for first line
+ return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
+ }
+ return fmt.Sprintf("line %d: %v", p.Line, p.Message)
+}
+
+type token struct {
+ value string
+ err *ParseError
+ line int // line number
+ offset int // byte number from start of input, not start of line
+ unquoted string // the unquoted version of value, if it was a quoted string
+}
+
+func (t *token) String() string {
+ if t.err == nil {
+ return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
+ }
+ return fmt.Sprintf("parse error: %v", t.err)
+}
+
+type textParser struct {
+ s string // remaining input
+ done bool // whether the parsing is finished (success or error)
+ backed bool // whether back() was called
+ offset, line int
+ cur token
+}
+
+func newTextParser(s string) *textParser {
+ p := new(textParser)
+ p.s = s
+ p.line = 1
+ p.cur.line = 1
+ return p
+}
+
+func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
+ pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
+ p.cur.err = pe
+ p.done = true
+ return pe
+}
+
+// Numbers and identifiers are matched by [-+._A-Za-z0-9]
+func isIdentOrNumberChar(c byte) bool {
+ switch {
+ case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
+ return true
+ case '0' <= c && c <= '9':
+ return true
+ }
+ switch c {
+ case '-', '+', '.', '_':
+ return true
+ }
+ return false
+}
+
+func isWhitespace(c byte) bool {
+ switch c {
+ case ' ', '\t', '\n', '\r':
+ return true
+ }
+ return false
+}
+
+func (p *textParser) skipWhitespace() {
+ i := 0
+ for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
+ if p.s[i] == '#' {
+ // comment; skip to end of line or input
+ for i < len(p.s) && p.s[i] != '\n' {
+ i++
+ }
+ if i == len(p.s) {
+ break
+ }
+ }
+ if p.s[i] == '\n' {
+ p.line++
+ }
+ i++
+ }
+ p.offset += i
+ p.s = p.s[i:len(p.s)]
+ if len(p.s) == 0 {
+ p.done = true
+ }
+}
+
+func (p *textParser) advance() {
+ // Skip whitespace
+ p.skipWhitespace()
+ if p.done {
+ return
+ }
+
+ // Start of non-whitespace
+ p.cur.err = nil
+ p.cur.offset, p.cur.line = p.offset, p.line
+ p.cur.unquoted = ""
+ switch p.s[0] {
+ case '<', '>', '{', '}', ':':
+ // Single symbol
+ p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
+ case '"':
+ // Quoted string
+ i := 1
+ for i < len(p.s) && p.s[i] != '"' && p.s[i] != '\n' {
+ if p.s[i] == '\\' && i+1 < len(p.s) {
+ // skip escaped char
+ i++
+ }
+ i++
+ }
+ if i >= len(p.s) || p.s[i] != '"' {
+ p.errorf("unmatched quote")
+ return
+ }
+ // TODO: Should be UnquoteC.
+ unq, err := strconv.Unquote(p.s[0 : i+1])
+ if err != nil {
+ p.errorf("invalid quoted string %v", p.s[0:i+1])
+ return
+ }
+ p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
+ p.cur.unquoted = unq
+ default:
+ i := 0
+ for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
+ i++
+ }
+ if i == 0 {
+ p.errorf("unexpected byte %#x", p.s[0])
+ return
+ }
+ p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
+ }
+ p.offset += len(p.cur.value)
+}
+
+// Back off the parser by one token. Can only be done between calls to next().
+// It makes the next advance() a no-op.
+func (p *textParser) back() { p.backed = true }
+
+// Advances the parser and returns the new current token.
+func (p *textParser) next() *token {
+ if p.backed || p.done {
+ p.backed = false
+ return &p.cur
+ }
+ p.advance()
+ if p.done {
+ p.cur.value = ""
+ } else if len(p.cur.value) > 0 && p.cur.value[0] == '"' {
+ // Look for multiple quoted strings separated by whitespace,
+ // and concatenate them.
+ cat := p.cur
+ for {
+ p.skipWhitespace()
+ if p.done || p.s[0] != '"' {
+ break
+ }
+ p.advance()
+ if p.cur.err != nil {
+ return &p.cur
+ }
+ cat.value += " " + p.cur.value
+ cat.unquoted += p.cur.unquoted
+ }
+ p.done = false // parser may have seen EOF, but we want to return cat
+ p.cur = cat
+ }
+ return &p.cur
+}
+
+// Return an error indicating which required field was not set.
+func (p *textParser) missingRequiredFieldError(sv reflect.Value) *ParseError {
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < st.NumField(); i++ {
+ if !isNil(sv.Field(i)) {
+ continue
+ }
+
+ props := sprops.Prop[i]
+ if props.Required {
+ return p.errorf("message %v missing required field %q", st, props.OrigName)
+ }
+ }
+ return p.errorf("message %v missing required field", st) // should not happen
+}
+
+// Returns the index in the struct for the named field, as well as the parsed tag properties.
+func structFieldByName(st reflect.Type, name string) (int, *Properties, bool) {
+ sprops := GetProperties(st)
+ i, ok := sprops.origNames[name]
+ if ok {
+ return i, sprops.Prop[i], true
+ }
+ return -1, nil, false
+}
+
+func (p *textParser) readStruct(sv reflect.Value, terminator string) *ParseError {
+ st := sv.Type()
+ reqCount := GetProperties(st).reqCount
+ // A struct is a sequence of "name: value", terminated by one of
+ // '>' or '}', or the end of the input.
+ for {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == terminator {
+ break
+ }
+
+ fi, props, ok := structFieldByName(st, tok.value)
+ if !ok {
+ return p.errorf("unknown field name %q in %v", tok.value, st)
+ }
+
+ // Check that it's not already set if it's not a repeated field.
+ if !props.Repeated && !isNil(sv.Field(fi)) {
+ return p.errorf("non-repeated field %q was repeated", tok.value)
+ }
+
+ tok = p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != ":" {
+ // Colon is optional when the field is a group or message.
+ needColon := true
+ switch props.Wire {
+ case "group":
+ needColon = false
+ case "bytes":
+ // A "bytes" field is either a message, a string, or a repeated field;
+ // those three become *T, *string and []T respectively, so we can check for
+ // this field being a pointer to a non-string.
+ typ := st.Field(fi).Type
+ if typ.Kind() == reflect.Ptr {
+ // *T or *string
+ if typ.Elem().Kind() == reflect.String {
+ break
+ }
+ } else if typ.Kind() == reflect.Slice {
+ // []T or []*T
+ if typ.Elem().Kind() != reflect.Ptr {
+ break
+ }
+ }
+ needColon = false
+ }
+ if needColon {
+ return p.errorf("expected ':', found %q", tok.value)
+ }
+ p.back()
+ }
+
+ // Parse into the field.
+ if err := p.readAny(sv.Field(fi), props); err != nil {
+ return err
+ }
+
+ if props.Required {
+ reqCount--
+ }
+ }
+
+ if reqCount > 0 {
+ return p.missingRequiredFieldError(sv)
+ }
+ return nil
+}
+
+const (
+ minInt32 = -1 << 31
+ maxInt32 = 1<<31 - 1
+ maxUint32 = 1<<32 - 1
+)
+
+func (p *textParser) readAny(v reflect.Value, props *Properties) *ParseError {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == "" {
+ return p.errorf("unexpected EOF")
+ }
+
+ switch fv := v; fv.Kind() {
+ case reflect.Slice:
+ at := v.Type()
+ if at.Elem().Kind() == reflect.Uint8 {
+ // Special case for []byte
+ if tok.value[0] != '"' {
+ // Deliberately written out here, as the error after
+ // this switch statement would write "invalid []byte: ...",
+ // which is not as user-friendly.
+ return p.errorf("invalid string: %v", tok.value)
+ }
+ bytes := []byte(tok.unquoted)
+ fv.Set(reflect.ValueOf(bytes))
+ return nil
+ }
+ // Repeated field. May already exist.
+ flen := fv.Len()
+ if flen == fv.Cap() {
+ nav := reflect.MakeSlice(at, flen, 2*flen+1)
+ reflect.Copy(nav, fv)
+ fv.Set(nav)
+ }
+ fv.SetLen(flen + 1)
+
+ // Read one.
+ p.back()
+ return p.readAny(fv.Index(flen), nil) // TODO: pass properties?
+ case reflect.Bool:
+ // Either "true", "false", 1 or 0.
+ switch tok.value {
+ case "true", "1":
+ fv.SetBool(true)
+ return nil
+ case "false", "0":
+ fv.SetBool(false)
+ return nil
+ }
+ case reflect.Float32, reflect.Float64:
+ if f, err := strconv.AtofN(tok.value, fv.Type().Bits()); err == nil {
+ fv.SetFloat(f)
+ return nil
+ }
+ case reflect.Int32:
+ if x, err := strconv.Atoi64(tok.value); err == nil && minInt32 <= x && x <= maxInt32 {
+ fv.SetInt(x)
+ return nil
+ }
+ if len(props.Enum) == 0 {
+ break
+ }
+ m, ok := enumValueMaps[props.Enum]
+ if !ok {
+ break
+ }
+ x, ok := m[tok.value]
+ if !ok {
+ break
+ }
+ fv.SetInt(int64(x))
+ return nil
+ case reflect.Int64:
+ if x, err := strconv.Atoi64(tok.value); err == nil {
+ fv.SetInt(x)
+ return nil
+ }
+ case reflect.Ptr:
+ // A basic field (indirected through pointer), or a repeated message/group
+ p.back()
+ fv.Set(reflect.New(fv.Type().Elem()))
+ return p.readAny(fv.Elem(), props)
+ case reflect.String:
+ if tok.value[0] == '"' {
+ fv.SetString(tok.unquoted)
+ return nil
+ }
+ case reflect.Struct:
+ var terminator string
+ switch tok.value {
+ case "{":
+ terminator = "}"
+ case "<":
+ terminator = ">"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ return p.readStruct(fv, terminator)
+ case reflect.Uint32:
+ if x, err := strconv.Atoui64(tok.value); err == nil && x <= maxUint32 {
+ fv.SetUint(uint64(x))
+ return nil
+ }
+ case reflect.Uint64:
+ if x, err := strconv.Atoui64(tok.value); err == nil {
+ fv.SetUint(x)
+ return nil
+ }
+ }
+ return p.errorf("invalid %v: %v", v.Type(), tok.value)
+}
+
+var notPtrStruct os.Error = &ParseError{"destination is not a pointer to a struct", 0, 0}
+
+// UnmarshalText reads a protobuffer in Text format.
+func UnmarshalText(s string, pb interface{}) os.Error {
+ v := reflect.ValueOf(pb)
+ if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
+ return notPtrStruct
+ }
+ if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
+ return pe
+ }
+ return nil
+}
--- /dev/null
+// 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.
+
+package proto_test
+
+import (
+ . "goprotobuf.googlecode.com/hg/proto"
+ . "./testdata/_obj/test_proto"
+ "reflect"
+ "testing"
+)
+
+type UnmarshalTextTest struct {
+ in string
+ error string // if "", no error expected
+ out *MyMessage
+}
+
+var unMarshalTextTests = []UnmarshalTextTest{
+ // Basic
+ {
+ in: " count:42\n name:\"Dave\" ",
+ out: &MyMessage{
+ Count: Int32(42),
+ Name: String("Dave"),
+ },
+ },
+
+ // Empty quoted string
+ {
+ in: `count:42 name:""`,
+ out: &MyMessage{
+ Count: Int32(42),
+ Name: String(""),
+ },
+ },
+
+ // Quoted string concatenation
+ {
+ in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
+ out: &MyMessage{
+ Count: Int32(42),
+ Name: String("My name is elsewhere"),
+ },
+ },
+
+ // Bad quoted string
+ {
+ in: `inner: < host: "\0" >` + "\n",
+ error: `line 1.15: invalid quoted string "\0"`,
+ },
+
+ // Number too large for int64
+ {
+ in: "count: 123456789012345678901",
+ error: "line 1.7: invalid int32: 123456789012345678901",
+ },
+
+ // Number too large for int32
+ {
+ in: "count: 1234567890123",
+ error: "line 1.7: invalid int32: 1234567890123",
+ },
+
+ // Number too large for float32
+ {
+ in: "others:< weight: 12345678901234567890123456789012345678901234567890 >",
+ error: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
+ },
+
+ // Number posing as a quoted string
+ {
+ in: `inner: < host: 12 >` + "\n",
+ error: `line 1.15: invalid string: 12`,
+ },
+
+ // Quoted string posing as int32
+ {
+ in: `count: "12"`,
+ error: `line 1.7: invalid int32: "12"`,
+ },
+
+ // Quoted string posing a float32
+ {
+ in: `others:< weight: "17.4" >`,
+ error: `line 1.17: invalid float32: "17.4"`,
+ },
+
+ // Enum
+ {
+ in: `count:42 bikeshed: BLUE`,
+ out: &MyMessage{
+ Count: Int32(42),
+ Bikeshed: NewMyMessage_Color(MyMessage_BLUE),
+ },
+ },
+
+ // Repeated field
+ {
+ in: `count:42 pet: "horsey" pet:"bunny"`,
+ out: &MyMessage{
+ Count: Int32(42),
+ Pet: []string{"horsey", "bunny"},
+ },
+ },
+
+ // Repeated message with/without colon and <>/{}
+ {
+ in: `count:42 others:{} others{} others:<> others:{}`,
+ out: &MyMessage{
+ Count: Int32(42),
+ Others: []*OtherMessage{
+ &OtherMessage{},
+ &OtherMessage{},
+ &OtherMessage{},
+ &OtherMessage{},
+ },
+ },
+ },
+
+ // Missing colon for inner message
+ {
+ in: `count:42 inner < host: "cauchy.syd" >`,
+ out: &MyMessage{
+ Count: Int32(42),
+ Inner: &InnerMessage{
+ Host: String("cauchy.syd"),
+ },
+ },
+ },
+
+ // Missing colon for string field
+ {
+ in: `name "Dave"`,
+ error: `line 1.5: expected ':', found "\"Dave\""`,
+ },
+
+ // Missing colon for int32 field
+ {
+ in: `count 42`,
+ error: `line 1.6: expected ':', found "42"`,
+ },
+
+ // Missing required field
+ {
+ in: ``,
+ error: `line 1.0: message test_proto.MyMessage missing required field "count"`,
+ },
+
+ // Repeated non-repeated field
+ {
+ in: `name: "Rob" name: "Russ"`,
+ error: `line 1.12: non-repeated field "name" was repeated`,
+ },
+
+ // Group
+ {
+ in: `count: 17 SomeGroup { group_field: 12 }`,
+ out: &MyMessage{
+ Count: Int32(17),
+ Somegroup: &MyMessage_SomeGroup{
+ GroupField: Int32(12),
+ },
+ },
+ },
+
+ // Big all-in-one
+ {
+ in: "count:42 # Meaning\n" +
+ `name:"Dave" ` +
+ `quote:"\"I didn't want to go.\"" ` +
+ `pet:"bunny" ` +
+ `pet:"kitty" ` +
+ `pet:"horsey" ` +
+ `inner:<` +
+ ` host:"footrest.syd" ` +
+ ` port:7001 ` +
+ ` connected:true ` +
+ `> ` +
+ `others:<` +
+ ` key:3735928559 ` +
+ ` value:"\x01A\a\f" ` +
+ `> ` +
+ `others:<` +
+ " weight:58.9 # Atomic weight of Co\n" +
+ ` inner:<` +
+ ` host:"lesha.mtv" ` +
+ ` port:8002 ` +
+ ` >` +
+ `>`,
+ out: &MyMessage{
+ Count: Int32(42),
+ Name: String("Dave"),
+ Quote: String(`"I didn't want to go."`),
+ Pet: []string{"bunny", "kitty", "horsey"},
+ Inner: &InnerMessage{
+ Host: String("footrest.syd"),
+ Port: Int32(7001),
+ Connected: Bool(true),
+ },
+ Others: []*OtherMessage{
+ &OtherMessage{
+ Key: Int64(3735928559),
+ Value: []byte{0x1, 'A', '\a', '\f'},
+ },
+ &OtherMessage{
+ Weight: Float32(58.9),
+ Inner: &InnerMessage{
+ Host: String("lesha.mtv"),
+ Port: Int32(8002),
+ },
+ },
+ },
+ },
+ },
+}
+
+func TestUnmarshalText(t *testing.T) {
+ for i, test := range unMarshalTextTests {
+ pb := new(MyMessage)
+ err := UnmarshalText(test.in, pb)
+ if test.error == "" {
+ // We don't expect failure.
+ if err != nil {
+ t.Errorf("Test %d: Unexpected error: %v", i, err)
+ } else if !reflect.DeepEqual(pb, test.out) {
+ t.Errorf("Test %d: Incorrect populated \n"+
+ "Have: %v\nWant: %v",
+ i, CompactTextString(pb), CompactTextString(test.out))
+ }
+ } else {
+ // We do expect failure.
+ if err == nil {
+ t.Errorf("Test %d: Didn't get expected error: %v", i, test.error)
+ } else if err.String() != test.error {
+ t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
+ i, err.String(), test.error)
+ }
+ }
+ }
+}
+
+var benchInput string
+
+func init() {
+ benchInput = "count: 4\n"
+ for i := 0; i < 1000; i++ {
+ benchInput += "pet: \"fido\"\n"
+ }
+
+ // Check it is valid input.
+ pb := new(MyMessage)
+ err := UnmarshalText(benchInput, pb)
+ if err != nil {
+ panic("Bad benchmark input: " + err.String())
+ }
+}
+
+func BenchmarkUnmarshalText(b *testing.B) {
+ pb := new(MyMessage)
+ for i := 0; i < b.N; i++ {
+ UnmarshalText(benchInput, pb)
+ }
+ b.SetBytes(int64(len(benchInput)))
+}
--- /dev/null
+// 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.
+
+package proto_test
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+
+ "goprotobuf.googlecode.com/hg/proto"
+
+ pb "./testdata/_obj/test_proto"
+)
+
+func newTestMessage() *pb.MyMessage {
+ msg := &pb.MyMessage{
+ Count: proto.Int32(42),
+ Name: proto.String("Dave"),
+ Quote: proto.String(`"I didn't want to go."`),
+ Pet: []string{"bunny", "kitty", "horsey"},
+ Inner: &pb.InnerMessage{
+ Host: proto.String("footrest.syd"),
+ Port: proto.Int32(7001),
+ Connected: proto.Bool(true),
+ },
+ Others: []*pb.OtherMessage{
+ &pb.OtherMessage{
+ Key: proto.Int64(0xdeadbeef),
+ Value: []byte{1, 65, 7, 12},
+ },
+ &pb.OtherMessage{
+ Weight: proto.Float32(6.022),
+ Inner: &pb.InnerMessage{
+ Host: proto.String("lesha.mtv"),
+ Port: proto.Int32(8002),
+ },
+ },
+ },
+ Bikeshed: pb.NewMyMessage_Color(pb.MyMessage_BLUE),
+ Somegroup: &pb.MyMessage_SomeGroup{
+ GroupField: proto.Int32(8),
+ },
+ // One normally wouldn't do this.
+ // This is an undeclared tag 13, as a varint (wire type 0) with value 4.
+ XXX_unrecognized: []byte{13<<3 | 0, 4},
+ }
+ ext := &pb.Ext{
+ Data: proto.String("Big gobs for big rats"),
+ }
+ if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil {
+ panic(err)
+ }
+
+ // Add an unknown extension. We marshal a pb.Ext, and fake the ID.
+ b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")})
+ if err != nil {
+ panic(err)
+ }
+ b = append(proto.EncodeVarint(104<<3|proto.WireBytes), b...)
+ proto.SetRawExtension(msg, 104, b)
+
+ // Extensions can be plain fields, too, so let's test that.
+ b = append(proto.EncodeVarint(105<<3|proto.WireVarint), 19)
+ proto.SetRawExtension(msg, 105, b)
+
+ return msg
+}
+
+const text = `count: 42
+name: "Dave"
+quote: "\"I didn't want to go.\""
+pet: "bunny"
+pet: "kitty"
+pet: "horsey"
+inner: <
+ host: "footrest.syd"
+ port: 7001
+ connected: true
+>
+others: <
+ key: 3735928559
+ value: "\001A\007\014"
+>
+others: <
+ weight: 6.022
+ inner: <
+ host: "lesha.mtv"
+ port: 8002
+ >
+>
+bikeshed: BLUE
+SomeGroup {
+ group_field: 8
+}
+/* 2 unknown bytes */
+tag13: 4
+[test_proto.Ext.more]: <
+ data: "Big gobs for big rats"
+>
+/* 13 unknown bytes */
+tag104: "\t3G skiing"
+/* 3 unknown bytes */
+tag105: 19
+`
+
+func TestMarshalTextFull(t *testing.T) {
+ buf := new(bytes.Buffer)
+ proto.MarshalText(buf, newTestMessage())
+ s := buf.String()
+ if s != text {
+ t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text)
+ }
+}
+
+func compact(src string) string {
+ // s/[ \n]+/ /g; s/ $//;
+ dst := make([]byte, len(src))
+ space, comment := false, false
+ j := 0
+ for i := 0; i < len(src); i++ {
+ if strings.HasPrefix(src[i:], "/*") {
+ comment = true
+ i++
+ continue
+ }
+ if comment && strings.HasPrefix(src[i:], "*/") {
+ comment = false
+ i++
+ continue
+ }
+ if comment {
+ continue
+ }
+ c := src[i]
+ if c == ' ' || c == '\n' {
+ space = true
+ continue
+ }
+ if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') {
+ space = false
+ }
+ if c == '{' {
+ space = false
+ }
+ if space {
+ dst[j] = ' '
+ j++
+ space = false
+ }
+ dst[j] = c
+ j++
+ }
+ if space {
+ dst[j] = ' '
+ j++
+ }
+ return string(dst[0:j])
+}
+
+var compactText = compact(text)
+
+func TestCompactText(t *testing.T) {
+ s := proto.CompactTextString(newTestMessage())
+ if s != compactText {
+ t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText)
+ }
+}
+
+func TestStringEscaping(t *testing.T) {
+ testCases := []struct {
+ in *pb.Strings
+ out string
+ }{
+ {
+ // Test data from C++ test (TextFormatTest.StringEscape).
+ // Single divergence: we don't escape apostrophes.
+ &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")},
+ "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n",
+ },
+ {
+ // Test data from the same C++ test.
+ &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")},
+ "string_field: \"\\350\\260\\267\\346\\255\\214\"\n",
+ },
+ }
+
+ for i, tc := range testCases {
+ var buf bytes.Buffer
+ proto.MarshalText(&buf, tc.in)
+ if s := buf.String(); s != tc.out {
+ t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out)
+ }
+ }
+}
+
+