initialise
authorSteven McDonald <steven@steven-mcdonald.id.au>
Sun, 2 Oct 2011 13:33:36 +0000 (00:33 +1100)
committerSteven McDonald <steven@steven-mcdonald.id.au>
Sun, 2 Oct 2011 13:33:36 +0000 (00:33 +1100)
53 files changed:
.hg_archival.txt [new file with mode: 0644]
.hgignore [new file with mode: 0644]
.hgtags [new file with mode: 0644]
CONTRIBUTORS [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Make.protobuf [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
compiler/Makefile [new file with mode: 0644]
compiler/descriptor/Makefile [new file with mode: 0644]
compiler/descriptor/descriptor.pb.go [new file with mode: 0644]
compiler/descriptor/descriptor.pb.golden [new file with mode: 0644]
compiler/doc.go [new file with mode: 0644]
compiler/generator/Makefile [new file with mode: 0644]
compiler/generator/generator.go [new file with mode: 0644]
compiler/main.go [new file with mode: 0644]
compiler/plugin/Makefile [new file with mode: 0644]
compiler/plugin/plugin.pb.go [new file with mode: 0644]
compiler/plugin/plugin.pb.golden [new file with mode: 0644]
compiler/testdata/Makefile [new file with mode: 0644]
compiler/testdata/extension_base.proto [new file with mode: 0644]
compiler/testdata/extension_extra.proto [new file with mode: 0644]
compiler/testdata/extension_test.go [new file with mode: 0644]
compiler/testdata/extension_user.proto [new file with mode: 0644]
compiler/testdata/imp.pb.go.golden [new file with mode: 0644]
compiler/testdata/imp.proto [new file with mode: 0644]
compiler/testdata/imp2.proto [new file with mode: 0644]
compiler/testdata/main.go [new file with mode: 0644]
compiler/testdata/multi1.proto [new file with mode: 0644]
compiler/testdata/multi2.proto [new file with mode: 0644]
compiler/testdata/multi3.proto [new file with mode: 0644]
compiler/testdata/test.pb.go.golden [new file with mode: 0644]
compiler/testdata/test.proto [new file with mode: 0644]
lib/codereview/codereview.cfg [new file with mode: 0644]
proto/Makefile [new file with mode: 0644]
proto/all_test.go [new file with mode: 0644]
proto/clone.go [new file with mode: 0644]
proto/clone_test.go [new file with mode: 0644]
proto/decode.go [new file with mode: 0644]
proto/encode.go [new file with mode: 0644]
proto/equal.go [new file with mode: 0644]
proto/equal_test.go [new file with mode: 0644]
proto/extensions.go [new file with mode: 0644]
proto/lib.go [new file with mode: 0644]
proto/message_set.go [new file with mode: 0644]
proto/properties.go [new file with mode: 0644]
proto/testdata/Makefile [new file with mode: 0644]
proto/testdata/test.pb.go.golden [new file with mode: 0644]
proto/testdata/test.proto [new file with mode: 0644]
proto/text.go [new file with mode: 0644]
proto/text_parser.go [new file with mode: 0644]
proto/text_parser_test.go [new file with mode: 0644]
proto/text_test.go [new file with mode: 0644]

diff --git a/.hg_archival.txt b/.hg_archival.txt
new file mode 100644 (file)
index 0000000..6bcceed
--- /dev/null
@@ -0,0 +1,5 @@
+repo: ecf73c3ec4286914856b51b4e9cb5c320f528952
+node: bc76a153ffde5de8535b7c2791102ddd0b93f187
+branch: default
+tag: go.r60
+tag: go.weekly.2011-09-21
diff --git a/.hgignore b/.hgignore
new file mode 100644 (file)
index 0000000..7f7b763
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,20 @@
+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
diff --git a/.hgtags b/.hgtags
new file mode 100644 (file)
index 0000000..0de67a6
--- /dev/null
+++ b/.hgtags
@@ -0,0 +1,16 @@
+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
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644 (file)
index 0000000..f926e4e
--- /dev/null
@@ -0,0 +1,14 @@
+# 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>
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..ae3664f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+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.
+
diff --git a/Make.protobuf b/Make.protobuf
new file mode 100644 (file)
index 0000000..06d37b5
--- /dev/null
@@ -0,0 +1,46 @@
+# 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=. $<
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..f1c42f5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,65 @@
+# 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
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..487c7f7
--- /dev/null
+++ b/README
@@ -0,0 +1,162 @@
+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.
+       }
diff --git a/compiler/Makefile b/compiler/Makefile
new file mode 100644 (file)
index 0000000..75bbd0b
--- /dev/null
@@ -0,0 +1,44 @@
+# 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
diff --git a/compiler/descriptor/Makefile b/compiler/descriptor/Makefile
new file mode 100644 (file)
index 0000000..ae052d6
--- /dev/null
@@ -0,0 +1,54 @@
+# 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
diff --git a/compiler/descriptor/descriptor.pb.go b/compiler/descriptor/descriptor.pb.go
new file mode 100644 (file)
index 0000000..507126e
--- /dev/null
@@ -0,0 +1,485 @@
+// 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)
+}
diff --git a/compiler/descriptor/descriptor.pb.golden b/compiler/descriptor/descriptor.pb.golden
new file mode 100644 (file)
index 0000000..507126e
--- /dev/null
@@ -0,0 +1,485 @@
+// 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)
+}
diff --git a/compiler/doc.go b/compiler/doc.go
new file mode 100644 (file)
index 0000000..f84ff8e
--- /dev/null
@@ -0,0 +1,51 @@
+// 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
diff --git a/compiler/generator/Makefile b/compiler/generator/Makefile
new file mode 100644 (file)
index 0000000..c19eeb0
--- /dev/null
@@ -0,0 +1,40 @@
+# 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
diff --git a/compiler/generator/generator.go b/compiler/generator/generator.go
new file mode 100644 (file)
index 0000000..ca1e576
--- /dev/null
@@ -0,0 +1,1425 @@
+// 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
+}
diff --git a/compiler/main.go b/compiler/main.go
new file mode 100644 (file)
index 0000000..9fd6070
--- /dev/null
@@ -0,0 +1,89 @@
+// 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")
+       }
+}
diff --git a/compiler/plugin/Makefile b/compiler/plugin/Makefile
new file mode 100644 (file)
index 0000000..e20482d
--- /dev/null
@@ -0,0 +1,56 @@
+# 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
diff --git a/compiler/plugin/plugin.pb.go b/compiler/plugin/plugin.pb.go
new file mode 100644 (file)
index 0000000..ac80dc4
--- /dev/null
@@ -0,0 +1,47 @@
+// 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() {
+}
diff --git a/compiler/plugin/plugin.pb.golden b/compiler/plugin/plugin.pb.golden
new file mode 100644 (file)
index 0000000..ac80dc4
--- /dev/null
@@ -0,0 +1,47 @@
+// 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() {
+}
diff --git a/compiler/testdata/Makefile b/compiler/testdata/Makefile
new file mode 100644 (file)
index 0000000..f1dcd50
--- /dev/null
@@ -0,0 +1,68 @@
+# 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
diff --git a/compiler/testdata/extension_base.proto b/compiler/testdata/extension_base.proto
new file mode 100644 (file)
index 0000000..bb35b74
--- /dev/null
@@ -0,0 +1,44 @@
+// 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;
+}
diff --git a/compiler/testdata/extension_extra.proto b/compiler/testdata/extension_extra.proto
new file mode 100644 (file)
index 0000000..08b949b
--- /dev/null
@@ -0,0 +1,38 @@
+// 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;
+}
diff --git a/compiler/testdata/extension_test.go b/compiler/testdata/extension_test.go
new file mode 100644 (file)
index 0000000..ad79052
--- /dev/null
@@ -0,0 +1,205 @@
+// 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{})
+}
diff --git a/compiler/testdata/extension_user.proto b/compiler/testdata/extension_user.proto
new file mode 100644 (file)
index 0000000..b5a731a
--- /dev/null
@@ -0,0 +1,89 @@
+// 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;
+}
diff --git a/compiler/testdata/imp.pb.go.golden b/compiler/testdata/imp.pb.go.golden
new file mode 100644 (file)
index 0000000..c038c74
--- /dev/null
@@ -0,0 +1,107 @@
+// 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)
+}
diff --git a/compiler/testdata/imp.proto b/compiler/testdata/imp.proto
new file mode 100644 (file)
index 0000000..b059db2
--- /dev/null
@@ -0,0 +1,50 @@
+// 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;
+}
diff --git a/compiler/testdata/imp2.proto b/compiler/testdata/imp2.proto
new file mode 100644 (file)
index 0000000..e69870a
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// 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;
+}
diff --git a/compiler/testdata/main.go b/compiler/testdata/main.go
new file mode 100644 (file)
index 0000000..ed81320
--- /dev/null
@@ -0,0 +1,44 @@
+// 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{}
+}
diff --git a/compiler/testdata/multi1.proto b/compiler/testdata/multi1.proto
new file mode 100644 (file)
index 0000000..47a4d2f
--- /dev/null
@@ -0,0 +1,42 @@
+// 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;
+}
+
diff --git a/compiler/testdata/multi2.proto b/compiler/testdata/multi2.proto
new file mode 100644 (file)
index 0000000..6bb76f9
--- /dev/null
@@ -0,0 +1,44 @@
+// 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;
+}
+
diff --git a/compiler/testdata/multi3.proto b/compiler/testdata/multi3.proto
new file mode 100644 (file)
index 0000000..191fefd
--- /dev/null
@@ -0,0 +1,41 @@
+// 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;
+}
+
diff --git a/compiler/testdata/test.pb.go.golden b/compiler/testdata/test.pb.go.golden
new file mode 100644 (file)
index 0000000..233d1f9
--- /dev/null
@@ -0,0 +1,243 @@
+// 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)
+}
diff --git a/compiler/testdata/test.proto b/compiler/testdata/test.proto
new file mode 100644 (file)
index 0000000..0c197f7
--- /dev/null
@@ -0,0 +1,101 @@
+// 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;
+}
+
diff --git a/lib/codereview/codereview.cfg b/lib/codereview/codereview.cfg
new file mode 100644 (file)
index 0000000..93b55c0
--- /dev/null
@@ -0,0 +1 @@
+defaultcc: golang-dev@googlegroups.com
diff --git a/proto/Makefile b/proto/Makefile
new file mode 100644 (file)
index 0000000..8f9380b
--- /dev/null
@@ -0,0 +1,58 @@
+# 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
diff --git a/proto/all_test.go b/proto/all_test.go
new file mode 100644 (file)
index 0000000..ae419aa
--- /dev/null
@@ -0,0 +1,1373 @@
+// 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)
+       }
+}
diff --git a/proto/clone.go b/proto/clone.go
new file mode 100644 (file)
index 0000000..05fb388
--- /dev/null
@@ -0,0 +1,122 @@
+// 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
+       }
+}
diff --git a/proto/clone_test.go b/proto/clone_test.go
new file mode 100644 (file)
index 0000000..c9c4a2f
--- /dev/null
@@ -0,0 +1,80 @@
+// 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")
+       }
+}
diff --git a/proto/decode.go b/proto/decode.go
new file mode 100644 (file)
index 0000000..fe28821
--- /dev/null
@@ -0,0 +1,773 @@
+// 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
+}
diff --git a/proto/encode.go b/proto/encode.go
new file mode 100644 (file)
index 0000000..7060520
--- /dev/null
@@ -0,0 +1,598 @@
+// 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
+}
diff --git a/proto/equal.go b/proto/equal.go
new file mode 100644 (file)
index 0000000..405d99a
--- /dev/null
@@ -0,0 +1,211 @@
+// 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
+}
diff --git a/proto/equal_test.go b/proto/equal_test.go
new file mode 100644 (file)
index 0000000..fd347af
--- /dev/null
@@ -0,0 +1,128 @@
+// 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)
+               }
+       }
+}
diff --git a/proto/extensions.go b/proto/extensions.go
new file mode 100644 (file)
index 0000000..d329b90
--- /dev/null
@@ -0,0 +1,276 @@
+// 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)