зеркало из https://github.com/golang/protobuf.git
Go support for protocol buffers.
Consists of a compiler plugin and the support library, all written in Go. This is a complete implementation except for: - Extensions in the plugin - coming soon - support is already in the library - Services (RPC) - needs an external definition to honor before supporting. - Insertion points in the plugin - may come R=rsc, dsymonds1, ken2 CC=golang-dev http://codereview.appspot.com/676041
This commit is contained in:
Родитель
fceca43ab4
Коммит
aaa3a62e62
|
@ -0,0 +1,11 @@
|
|||
# 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.
|
||||
|
||||
|
||||
David Symonds <dsymonds@golang.org>
|
||||
Ken Thompson <ken@golang.org>
|
||||
Rob Pike <r@golang.org>
|
|
@ -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.
|
||||
|
|
@ -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.$(GOARCH)
|
||||
# TARG=mypackage
|
||||
# GOFILES=\
|
||||
# myproto.pb.go
|
||||
#
|
||||
# include $(GOROOT)/src/Make.pkg
|
||||
# include $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/Make.proto
|
||||
|
||||
%.pb.go: %.proto
|
||||
protoc --go_out=. $<
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# 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.$(GOARCH)
|
||||
|
||||
all: install
|
||||
|
||||
install:
|
||||
cd proto && make install
|
||||
cd compiler && make install
|
||||
|
||||
clean:
|
||||
cd proto && make clean
|
||||
cd compiler && make clean
|
||||
cd compiler/testdata && make clean
|
||||
cd compiler/descriptor && make clean
|
||||
cd compiler/plugin && make clean
|
||||
|
||||
nuke:
|
||||
cd proto && make nuke
|
||||
cd compiler && make nuke
|
||||
cd compiler/testdata && make nuke
|
||||
cd compiler/descriptor && make nuke
|
||||
cd compiler/plugin && make nuke
|
|
@ -0,0 +1,160 @@
|
|||
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.
|
||||
|
||||
Extensions are not supported by the plugin in this release, although
|
||||
they are in the library. The work will be completed soon.
|
||||
|
||||
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 commentin 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.
|
||||
|
||||
|
||||
|
||||
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.
|
||||
- Each type T has a method NewT() to create a new instance. It
|
||||
is equivalent to new(T).
|
||||
- Non-repeated fields are pointers to the values; nil means unset.
|
||||
That is, optional or required field int32 f becomes F *int32.
|
||||
- Repeated fields are slices.
|
||||
- Helper functions are available to simplify the getting and setting of fields:
|
||||
foo.String = proto.String("hello") // set field
|
||||
s := proto.GetString(foo.String) // get field
|
||||
- Constants are defined to hold the default values of all fields that
|
||||
have them. They have the form Default_StructName_FieldName.
|
||||
- Enums are given type names and maps between names to values,
|
||||
plus a helper function to create values. Enum values are prefixed
|
||||
with the enum's type name.
|
||||
- Nested groups and enums have type names prefixed with the name of
|
||||
the surrounding message type.
|
||||
- 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.Exit("marshaling error:", err)
|
||||
}
|
||||
newTest := example.NewTest()
|
||||
err = proto.Unmarshal(data, newTest)
|
||||
if err != nil {
|
||||
log.Exit("unmarshaling error:", err)
|
||||
}
|
||||
// Now test and newTest contain the same data.
|
||||
if proto.GetString(test.Label) != proto.GetString(newTest.Label) {
|
||||
log.Exit("data mismatch %q %q", proto.GetString(test.Label), proto.GetString(newTest.Label))
|
||||
}
|
||||
// etc.
|
||||
}
|
|
@ -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.$(GOARCH)
|
||||
|
||||
TARG=protoc-gen-go
|
||||
GOFILES=\
|
||||
main.go\
|
||||
|
||||
DEPS=descriptor plugin
|
||||
|
||||
include $(GOROOT)/src/Make.cmd
|
||||
|
||||
test:
|
||||
cd testdata && make test
|
|
@ -0,0 +1,53 @@
|
|||
# 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.$(GOARCH)
|
||||
|
||||
TARG=goprotobuf.googlecode.com/hg/compiler/descriptor
|
||||
GOFILES=\
|
||||
descriptor.pb.go\
|
||||
|
||||
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
|
||||
# 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/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
|
|
@ -0,0 +1,398 @@
|
|||
// Code generated by protoc-gen-go from "google/protobuf/descriptor.proto"
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import "goprotobuf.googlecode.com/hg/proto"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type FileDescriptorSet struct {
|
||||
File []*FileDescriptorProto "PB(bytes,1,rep,name=file)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FileDescriptorSet) Reset() {
|
||||
*this = FileDescriptorSet{}
|
||||
}
|
||||
func NewFileDescriptorSet() *FileDescriptorSet {
|
||||
return new(FileDescriptorSet)
|
||||
}
|
||||
|
||||
type FileDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Package *string "PB(bytes,2,opt,name=package)"
|
||||
Dependency []string "PB(bytes,3,rep,name=dependency)"
|
||||
MessageType []*DescriptorProto "PB(bytes,4,rep,name=message_type)"
|
||||
EnumType []*EnumDescriptorProto "PB(bytes,5,rep,name=enum_type)"
|
||||
Service []*ServiceDescriptorProto "PB(bytes,6,rep,name=service)"
|
||||
Extension []*FieldDescriptorProto "PB(bytes,7,rep,name=extension)"
|
||||
Options *FileOptions "PB(bytes,8,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FileDescriptorProto) Reset() {
|
||||
*this = FileDescriptorProto{}
|
||||
}
|
||||
func NewFileDescriptorProto() *FileDescriptorProto {
|
||||
return new(FileDescriptorProto)
|
||||
}
|
||||
|
||||
type DescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Field []*FieldDescriptorProto "PB(bytes,2,rep,name=field)"
|
||||
Extension []*FieldDescriptorProto "PB(bytes,6,rep,name=extension)"
|
||||
NestedType []*DescriptorProto "PB(bytes,3,rep,name=nested_type)"
|
||||
EnumType []*EnumDescriptorProto "PB(bytes,4,rep,name=enum_type)"
|
||||
ExtensionRange []*DescriptorProto_ExtensionRange "PB(bytes,5,rep,name=extension_range)"
|
||||
Options *MessageOptions "PB(bytes,7,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *DescriptorProto) Reset() {
|
||||
*this = DescriptorProto{}
|
||||
}
|
||||
func NewDescriptorProto() *DescriptorProto {
|
||||
return new(DescriptorProto)
|
||||
}
|
||||
|
||||
type DescriptorProto_ExtensionRange struct {
|
||||
Start *int32 "PB(varint,1,opt,name=start)"
|
||||
End *int32 "PB(varint,2,opt,name=end)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *DescriptorProto_ExtensionRange) Reset() {
|
||||
*this = DescriptorProto_ExtensionRange{}
|
||||
}
|
||||
func NewDescriptorProto_ExtensionRange() *DescriptorProto_ExtensionRange {
|
||||
return new(DescriptorProto_ExtensionRange)
|
||||
}
|
||||
|
||||
type FieldDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Number *int32 "PB(varint,3,opt,name=number)"
|
||||
Label *FieldDescriptorProto_Label "PB(varint,4,opt,name=label,enum=google_protobuf.FieldDescriptorProto_Label)"
|
||||
Type *FieldDescriptorProto_Type "PB(varint,5,opt,name=type,enum=google_protobuf.FieldDescriptorProto_Type)"
|
||||
TypeName *string "PB(bytes,6,opt,name=type_name)"
|
||||
Extendee *string "PB(bytes,2,opt,name=extendee)"
|
||||
DefaultValue *string "PB(bytes,7,opt,name=default_value)"
|
||||
Options *FieldOptions "PB(bytes,8,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FieldDescriptorProto) Reset() {
|
||||
*this = FieldDescriptorProto{}
|
||||
}
|
||||
func NewFieldDescriptorProto() *FieldDescriptorProto {
|
||||
return new(FieldDescriptorProto)
|
||||
}
|
||||
|
||||
type EnumDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Value []*EnumValueDescriptorProto "PB(bytes,2,rep,name=value)"
|
||||
Options *EnumOptions "PB(bytes,3,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumDescriptorProto) Reset() {
|
||||
*this = EnumDescriptorProto{}
|
||||
}
|
||||
func NewEnumDescriptorProto() *EnumDescriptorProto {
|
||||
return new(EnumDescriptorProto)
|
||||
}
|
||||
|
||||
type EnumValueDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Number *int32 "PB(varint,2,opt,name=number)"
|
||||
Options *EnumValueOptions "PB(bytes,3,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumValueDescriptorProto) Reset() {
|
||||
*this = EnumValueDescriptorProto{}
|
||||
}
|
||||
func NewEnumValueDescriptorProto() *EnumValueDescriptorProto {
|
||||
return new(EnumValueDescriptorProto)
|
||||
}
|
||||
|
||||
type ServiceDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Method []*MethodDescriptorProto "PB(bytes,2,rep,name=method)"
|
||||
Options *ServiceOptions "PB(bytes,3,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *ServiceDescriptorProto) Reset() {
|
||||
*this = ServiceDescriptorProto{}
|
||||
}
|
||||
func NewServiceDescriptorProto() *ServiceDescriptorProto {
|
||||
return new(ServiceDescriptorProto)
|
||||
}
|
||||
|
||||
type MethodDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
InputType *string "PB(bytes,2,opt,name=input_type)"
|
||||
OutputType *string "PB(bytes,3,opt,name=output_type)"
|
||||
Options *MethodOptions "PB(bytes,4,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MethodDescriptorProto) Reset() {
|
||||
*this = MethodDescriptorProto{}
|
||||
}
|
||||
func NewMethodDescriptorProto() *MethodDescriptorProto {
|
||||
return new(MethodDescriptorProto)
|
||||
}
|
||||
|
||||
type FileOptions struct {
|
||||
JavaPackage *string "PB(bytes,1,opt,name=java_package)"
|
||||
JavaOuterClassname *string "PB(bytes,8,opt,name=java_outer_classname)"
|
||||
JavaMultipleFiles *bool "PB(varint,10,opt,name=java_multiple_files,def=0)"
|
||||
OptimizeFor *FileOptions_OptimizeMode "PB(varint,9,opt,name=optimize_for,enum=google_protobuf.FileOptions_OptimizeMode,def=1)"
|
||||
CcGenericServices *bool "PB(varint,16,opt,name=cc_generic_services,def=1)"
|
||||
JavaGenericServices *bool "PB(varint,17,opt,name=java_generic_services,def=1)"
|
||||
PyGenericServices *bool "PB(varint,18,opt,name=py_generic_services,def=1)"
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FileOptions) Reset() {
|
||||
*this = FileOptions{}
|
||||
}
|
||||
func NewFileOptions() *FileOptions {
|
||||
return new(FileOptions)
|
||||
}
|
||||
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 "PB(varint,1,opt,name=message_set_wire_format,def=0)"
|
||||
NoStandardDescriptorAccessor *bool "PB(varint,2,opt,name=no_standard_descriptor_accessor,def=0)"
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MessageOptions) Reset() {
|
||||
*this = MessageOptions{}
|
||||
}
|
||||
func NewMessageOptions() *MessageOptions {
|
||||
return new(MessageOptions)
|
||||
}
|
||||
const Default_MessageOptions_MessageSetWireFormat bool = false
|
||||
const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
|
||||
|
||||
type FieldOptions struct {
|
||||
Ctype *FieldOptions_CType "PB(varint,1,opt,name=ctype,enum=google_protobuf.FieldOptions_CType,def=0)"
|
||||
Packed *bool "PB(varint,2,opt,name=packed)"
|
||||
Deprecated *bool "PB(varint,3,opt,name=deprecated,def=0)"
|
||||
ExperimentalMapKey *string "PB(bytes,9,opt,name=experimental_map_key)"
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FieldOptions) Reset() {
|
||||
*this = FieldOptions{}
|
||||
}
|
||||
func NewFieldOptions() *FieldOptions {
|
||||
return new(FieldOptions)
|
||||
}
|
||||
const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
|
||||
const Default_FieldOptions_Deprecated bool = false
|
||||
|
||||
type EnumOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumOptions) Reset() {
|
||||
*this = EnumOptions{}
|
||||
}
|
||||
func NewEnumOptions() *EnumOptions {
|
||||
return new(EnumOptions)
|
||||
}
|
||||
|
||||
type EnumValueOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumValueOptions) Reset() {
|
||||
*this = EnumValueOptions{}
|
||||
}
|
||||
func NewEnumValueOptions() *EnumValueOptions {
|
||||
return new(EnumValueOptions)
|
||||
}
|
||||
|
||||
type ServiceOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *ServiceOptions) Reset() {
|
||||
*this = ServiceOptions{}
|
||||
}
|
||||
func NewServiceOptions() *ServiceOptions {
|
||||
return new(ServiceOptions)
|
||||
}
|
||||
|
||||
type MethodOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MethodOptions) Reset() {
|
||||
*this = MethodOptions{}
|
||||
}
|
||||
func NewMethodOptions() *MethodOptions {
|
||||
return new(MethodOptions)
|
||||
}
|
||||
|
||||
type UninterpretedOption struct {
|
||||
Name []*UninterpretedOption_NamePart "PB(bytes,2,rep,name=name)"
|
||||
IdentifierValue *string "PB(bytes,3,opt,name=identifier_value)"
|
||||
PositiveIntValue *uint64 "PB(varint,4,opt,name=positive_int_value)"
|
||||
NegativeIntValue *int64 "PB(varint,5,opt,name=negative_int_value)"
|
||||
DoubleValue *float64 "PB(fixed64,6,opt,name=double_value)"
|
||||
StringValue []byte "PB(bytes,7,opt,name=string_value)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *UninterpretedOption) Reset() {
|
||||
*this = UninterpretedOption{}
|
||||
}
|
||||
func NewUninterpretedOption() *UninterpretedOption {
|
||||
return new(UninterpretedOption)
|
||||
}
|
||||
|
||||
type UninterpretedOption_NamePart struct {
|
||||
NamePart *string "PB(bytes,1,req,name=name_part)"
|
||||
IsExtension *bool "PB(varint,2,req,name=is_extension)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *UninterpretedOption_NamePart) Reset() {
|
||||
*this = UninterpretedOption_NamePart{}
|
||||
}
|
||||
func NewUninterpretedOption_NamePart() *UninterpretedOption_NamePart {
|
||||
return new(UninterpretedOption_NamePart)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
|
@ -0,0 +1,398 @@
|
|||
// Code generated by protoc-gen-go from "google/protobuf/descriptor.proto"
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf
|
||||
|
||||
import "goprotobuf.googlecode.com/hg/proto"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type FileDescriptorSet struct {
|
||||
File []*FileDescriptorProto "PB(bytes,1,rep,name=file)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FileDescriptorSet) Reset() {
|
||||
*this = FileDescriptorSet{}
|
||||
}
|
||||
func NewFileDescriptorSet() *FileDescriptorSet {
|
||||
return new(FileDescriptorSet)
|
||||
}
|
||||
|
||||
type FileDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Package *string "PB(bytes,2,opt,name=package)"
|
||||
Dependency []string "PB(bytes,3,rep,name=dependency)"
|
||||
MessageType []*DescriptorProto "PB(bytes,4,rep,name=message_type)"
|
||||
EnumType []*EnumDescriptorProto "PB(bytes,5,rep,name=enum_type)"
|
||||
Service []*ServiceDescriptorProto "PB(bytes,6,rep,name=service)"
|
||||
Extension []*FieldDescriptorProto "PB(bytes,7,rep,name=extension)"
|
||||
Options *FileOptions "PB(bytes,8,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FileDescriptorProto) Reset() {
|
||||
*this = FileDescriptorProto{}
|
||||
}
|
||||
func NewFileDescriptorProto() *FileDescriptorProto {
|
||||
return new(FileDescriptorProto)
|
||||
}
|
||||
|
||||
type DescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Field []*FieldDescriptorProto "PB(bytes,2,rep,name=field)"
|
||||
Extension []*FieldDescriptorProto "PB(bytes,6,rep,name=extension)"
|
||||
NestedType []*DescriptorProto "PB(bytes,3,rep,name=nested_type)"
|
||||
EnumType []*EnumDescriptorProto "PB(bytes,4,rep,name=enum_type)"
|
||||
ExtensionRange []*DescriptorProto_ExtensionRange "PB(bytes,5,rep,name=extension_range)"
|
||||
Options *MessageOptions "PB(bytes,7,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *DescriptorProto) Reset() {
|
||||
*this = DescriptorProto{}
|
||||
}
|
||||
func NewDescriptorProto() *DescriptorProto {
|
||||
return new(DescriptorProto)
|
||||
}
|
||||
|
||||
type DescriptorProto_ExtensionRange struct {
|
||||
Start *int32 "PB(varint,1,opt,name=start)"
|
||||
End *int32 "PB(varint,2,opt,name=end)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *DescriptorProto_ExtensionRange) Reset() {
|
||||
*this = DescriptorProto_ExtensionRange{}
|
||||
}
|
||||
func NewDescriptorProto_ExtensionRange() *DescriptorProto_ExtensionRange {
|
||||
return new(DescriptorProto_ExtensionRange)
|
||||
}
|
||||
|
||||
type FieldDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Number *int32 "PB(varint,3,opt,name=number)"
|
||||
Label *FieldDescriptorProto_Label "PB(varint,4,opt,name=label,enum=google_protobuf.FieldDescriptorProto_Label)"
|
||||
Type *FieldDescriptorProto_Type "PB(varint,5,opt,name=type,enum=google_protobuf.FieldDescriptorProto_Type)"
|
||||
TypeName *string "PB(bytes,6,opt,name=type_name)"
|
||||
Extendee *string "PB(bytes,2,opt,name=extendee)"
|
||||
DefaultValue *string "PB(bytes,7,opt,name=default_value)"
|
||||
Options *FieldOptions "PB(bytes,8,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FieldDescriptorProto) Reset() {
|
||||
*this = FieldDescriptorProto{}
|
||||
}
|
||||
func NewFieldDescriptorProto() *FieldDescriptorProto {
|
||||
return new(FieldDescriptorProto)
|
||||
}
|
||||
|
||||
type EnumDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Value []*EnumValueDescriptorProto "PB(bytes,2,rep,name=value)"
|
||||
Options *EnumOptions "PB(bytes,3,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumDescriptorProto) Reset() {
|
||||
*this = EnumDescriptorProto{}
|
||||
}
|
||||
func NewEnumDescriptorProto() *EnumDescriptorProto {
|
||||
return new(EnumDescriptorProto)
|
||||
}
|
||||
|
||||
type EnumValueDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Number *int32 "PB(varint,2,opt,name=number)"
|
||||
Options *EnumValueOptions "PB(bytes,3,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumValueDescriptorProto) Reset() {
|
||||
*this = EnumValueDescriptorProto{}
|
||||
}
|
||||
func NewEnumValueDescriptorProto() *EnumValueDescriptorProto {
|
||||
return new(EnumValueDescriptorProto)
|
||||
}
|
||||
|
||||
type ServiceDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
Method []*MethodDescriptorProto "PB(bytes,2,rep,name=method)"
|
||||
Options *ServiceOptions "PB(bytes,3,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *ServiceDescriptorProto) Reset() {
|
||||
*this = ServiceDescriptorProto{}
|
||||
}
|
||||
func NewServiceDescriptorProto() *ServiceDescriptorProto {
|
||||
return new(ServiceDescriptorProto)
|
||||
}
|
||||
|
||||
type MethodDescriptorProto struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
InputType *string "PB(bytes,2,opt,name=input_type)"
|
||||
OutputType *string "PB(bytes,3,opt,name=output_type)"
|
||||
Options *MethodOptions "PB(bytes,4,opt,name=options)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MethodDescriptorProto) Reset() {
|
||||
*this = MethodDescriptorProto{}
|
||||
}
|
||||
func NewMethodDescriptorProto() *MethodDescriptorProto {
|
||||
return new(MethodDescriptorProto)
|
||||
}
|
||||
|
||||
type FileOptions struct {
|
||||
JavaPackage *string "PB(bytes,1,opt,name=java_package)"
|
||||
JavaOuterClassname *string "PB(bytes,8,opt,name=java_outer_classname)"
|
||||
JavaMultipleFiles *bool "PB(varint,10,opt,name=java_multiple_files,def=0)"
|
||||
OptimizeFor *FileOptions_OptimizeMode "PB(varint,9,opt,name=optimize_for,enum=google_protobuf.FileOptions_OptimizeMode,def=1)"
|
||||
CcGenericServices *bool "PB(varint,16,opt,name=cc_generic_services,def=1)"
|
||||
JavaGenericServices *bool "PB(varint,17,opt,name=java_generic_services,def=1)"
|
||||
PyGenericServices *bool "PB(varint,18,opt,name=py_generic_services,def=1)"
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FileOptions) Reset() {
|
||||
*this = FileOptions{}
|
||||
}
|
||||
func NewFileOptions() *FileOptions {
|
||||
return new(FileOptions)
|
||||
}
|
||||
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 "PB(varint,1,opt,name=message_set_wire_format,def=0)"
|
||||
NoStandardDescriptorAccessor *bool "PB(varint,2,opt,name=no_standard_descriptor_accessor,def=0)"
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MessageOptions) Reset() {
|
||||
*this = MessageOptions{}
|
||||
}
|
||||
func NewMessageOptions() *MessageOptions {
|
||||
return new(MessageOptions)
|
||||
}
|
||||
const Default_MessageOptions_MessageSetWireFormat bool = false
|
||||
const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
|
||||
|
||||
type FieldOptions struct {
|
||||
Ctype *FieldOptions_CType "PB(varint,1,opt,name=ctype,enum=google_protobuf.FieldOptions_CType,def=0)"
|
||||
Packed *bool "PB(varint,2,opt,name=packed)"
|
||||
Deprecated *bool "PB(varint,3,opt,name=deprecated,def=0)"
|
||||
ExperimentalMapKey *string "PB(bytes,9,opt,name=experimental_map_key)"
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *FieldOptions) Reset() {
|
||||
*this = FieldOptions{}
|
||||
}
|
||||
func NewFieldOptions() *FieldOptions {
|
||||
return new(FieldOptions)
|
||||
}
|
||||
const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
|
||||
const Default_FieldOptions_Deprecated bool = false
|
||||
|
||||
type EnumOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumOptions) Reset() {
|
||||
*this = EnumOptions{}
|
||||
}
|
||||
func NewEnumOptions() *EnumOptions {
|
||||
return new(EnumOptions)
|
||||
}
|
||||
|
||||
type EnumValueOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *EnumValueOptions) Reset() {
|
||||
*this = EnumValueOptions{}
|
||||
}
|
||||
func NewEnumValueOptions() *EnumValueOptions {
|
||||
return new(EnumValueOptions)
|
||||
}
|
||||
|
||||
type ServiceOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *ServiceOptions) Reset() {
|
||||
*this = ServiceOptions{}
|
||||
}
|
||||
func NewServiceOptions() *ServiceOptions {
|
||||
return new(ServiceOptions)
|
||||
}
|
||||
|
||||
type MethodOptions struct {
|
||||
UninterpretedOption []*UninterpretedOption "PB(bytes,999,rep,name=uninterpreted_option)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MethodOptions) Reset() {
|
||||
*this = MethodOptions{}
|
||||
}
|
||||
func NewMethodOptions() *MethodOptions {
|
||||
return new(MethodOptions)
|
||||
}
|
||||
|
||||
type UninterpretedOption struct {
|
||||
Name []*UninterpretedOption_NamePart "PB(bytes,2,rep,name=name)"
|
||||
IdentifierValue *string "PB(bytes,3,opt,name=identifier_value)"
|
||||
PositiveIntValue *uint64 "PB(varint,4,opt,name=positive_int_value)"
|
||||
NegativeIntValue *int64 "PB(varint,5,opt,name=negative_int_value)"
|
||||
DoubleValue *float64 "PB(fixed64,6,opt,name=double_value)"
|
||||
StringValue []byte "PB(bytes,7,opt,name=string_value)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *UninterpretedOption) Reset() {
|
||||
*this = UninterpretedOption{}
|
||||
}
|
||||
func NewUninterpretedOption() *UninterpretedOption {
|
||||
return new(UninterpretedOption)
|
||||
}
|
||||
|
||||
type UninterpretedOption_NamePart struct {
|
||||
NamePart *string "PB(bytes,1,req,name=name_part)"
|
||||
IsExtension *bool "PB(varint,2,req,name=is_extension)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *UninterpretedOption_NamePart) Reset() {
|
||||
*this = UninterpretedOption_NamePart{}
|
||||
}
|
||||
func NewUninterpretedOption_NamePart() *UninterpretedOption_NamePart {
|
||||
return new(UninterpretedOption_NamePart)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,903 @@
|
|||
// 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.
|
||||
|
||||
Not supported yet:
|
||||
Extensions
|
||||
Services
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"goprotobuf.googlecode.com/hg/proto"
|
||||
plugin "goprotobuf.googlecode.com/hg/compiler/plugin"
|
||||
descriptor "goprotobuf.googlecode.com/hg/compiler/descriptor"
|
||||
)
|
||||
|
||||
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 := NewGenerator()
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
}
|
||||
|
||||
// The package name we will produce in our output.
|
||||
func (c *common) packageName() string { return uniquePackageOf(c.file) }
|
||||
|
||||
// A message (struct).
|
||||
type Descriptor struct {
|
||||
common
|
||||
*descriptor.DescriptorProto
|
||||
parent *Descriptor // The containing message, if any.
|
||||
nested []*Descriptor // Inner messages, if any.
|
||||
typename []string // Cached typename vector.
|
||||
}
|
||||
|
||||
// Return 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
|
||||
}
|
||||
|
||||
// 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.
|
||||
}
|
||||
|
||||
// Return the elements of the dotted type 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.Exit("cannot find value for enum constant")
|
||||
return ""
|
||||
}
|
||||
|
||||
// A file. 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.
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (d *FileDescriptor) originalPackageName() string {
|
||||
return proto.GetString(d.Package)
|
||||
}
|
||||
|
||||
// Simplify some things by abstracting the abilities shared by enums and messages.
|
||||
type Object interface {
|
||||
packageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness.
|
||||
typeName() []string
|
||||
}
|
||||
|
||||
// Each package name we generate must be unique. The package we're generating
|
||||
// gets its own name but every other package must have a unqiue 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.Exit("internal error: no package name defined for", proto.GetString(fd.Name))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
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.
|
||||
typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
|
||||
indent string
|
||||
}
|
||||
|
||||
// Create a new generator and allocate the request and response protobufs.
|
||||
func NewGenerator() *Generator {
|
||||
g := new(Generator)
|
||||
g.request = plugin.NewCodeGeneratorRequest()
|
||||
g.response = plugin.NewCodeGeneratorResponse()
|
||||
return g
|
||||
}
|
||||
|
||||
// Report problem, including an os.Error, and fail.
|
||||
func (g *Generator) error(err os.Error, msgs ...string) {
|
||||
s := strings.Join(msgs, " ") + ":" + err.String()
|
||||
log.Stderr("protoc-gen-go: error: ", s)
|
||||
g.response.Error = proto.String(s)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Report problem and fail.
|
||||
func (g *Generator) fail(msgs ...string) {
|
||||
s := strings.Join(msgs, " ")
|
||||
log.Stderr("protoc-gen-go: error: ", s)
|
||||
g.response.Error = proto.String(s)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// If this file is in a different package, return the package name we're using for this file, plus ".".
|
||||
// Otherwise return 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)
|
||||
|
||||
// Set the package name for this run. It must agree across all files being generated.
|
||||
// Also define unique package names for all imported files.
|
||||
func (g *Generator) SetPackageNames() {
|
||||
inUse := make(map[string]bool)
|
||||
pkg := proto.GetString(g.genFiles[0].Package)
|
||||
g.packageName = strings.Map(DotToUnderscore, pkg)
|
||||
inUse[pkg] = true
|
||||
for _, f := range g.genFiles {
|
||||
thisPkg := proto.GetString(f.Package)
|
||||
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
|
||||
}
|
||||
}
|
||||
truePkg := proto.GetString(f.Package)
|
||||
pkg := truePkg
|
||||
for {
|
||||
_, present := inUse[pkg]
|
||||
if present {
|
||||
// It's a duplicate; must rename.
|
||||
pkg += "X"
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
// Install it.
|
||||
if pkg != truePkg {
|
||||
log.Stderr("renaming duplicate imported package named", truePkg, "to", pkg)
|
||||
}
|
||||
inUse[pkg] = true
|
||||
uniquePackageName[f.FileDescriptorProto] = strings.Map(DotToUnderscore, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the incoming data, wrapping DescriptorProtos and EnumDescriptorProtos
|
||||
// into file-referenced objects within the Generator. Also create the list of files
|
||||
// to generate
|
||||
func (g *Generator) WrapTypes() {
|
||||
g.allFiles = make([]*FileDescriptor, len(g.request.ProtoFile))
|
||||
for i, f := range g.request.ProtoFile {
|
||||
pkg := proto.GetString(f.Package)
|
||||
if pkg == "" {
|
||||
g.fail(proto.GetString(f.Name), "is missing a package declaration")
|
||||
}
|
||||
// We must wrap the descriptors before we wrap the enums
|
||||
descs := WrapDescriptors(f)
|
||||
g.BuildNestedDescriptors(descs)
|
||||
enums := WrapEnumDescriptors(f, descs)
|
||||
g.allFiles[i] = &FileDescriptor{
|
||||
FileDescriptorProto: f,
|
||||
desc: descs,
|
||||
enum: enums,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if len(sl) == cap(sl) {
|
||||
nsl := make([]*Descriptor, len(sl), 2*len(sl))
|
||||
copy(nsl, sl)
|
||||
sl = nsl
|
||||
}
|
||||
sl = sl[0 : len(sl)+1]
|
||||
sl[len(sl)-1] = &Descriptor{common{file: file}, desc, parent, nil, nil}
|
||||
return sl
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if len(sl) == cap(sl) {
|
||||
nsl := make([]*EnumDescriptor, len(sl), 2*len(sl))
|
||||
copy(nsl, sl)
|
||||
sl = nsl
|
||||
}
|
||||
sl = sl[0 : len(sl)+1]
|
||||
sl[len(sl)-1] = &EnumDescriptor{common{file: file}, desc, parent, nil}
|
||||
return sl
|
||||
}
|
||||
|
||||
// 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)
|
||||
for _, enum := range file.EnumType {
|
||||
sl = AddEnumDescriptor(sl, enum, nil, file)
|
||||
}
|
||||
for _, nested := range descs {
|
||||
sl = WrapEnumDescriptorsInMessage(sl, nested, file)
|
||||
}
|
||||
return sl
|
||||
}
|
||||
|
||||
// Wrap this EnumDescriptor, recursively
|
||||
func WrapEnumDescriptorsInMessage(sl []*EnumDescriptor, desc *Descriptor, file *descriptor.FileDescriptorProto) []*EnumDescriptor {
|
||||
for _, enum := range desc.EnumType {
|
||||
sl = AddEnumDescriptor(sl, enum, desc, file)
|
||||
}
|
||||
for _, nested := range desc.nested {
|
||||
sl = WrapEnumDescriptorsInMessage(sl, nested, file)
|
||||
}
|
||||
return sl
|
||||
}
|
||||
|
||||
// Build the map from fully qualified type names to objects. The key for the map
|
||||
// comes from the input data, which puts a period at the beginning.
|
||||
func (g *Generator) BuildTypeNameMap() {
|
||||
g.typeNameToObject = make(map[string]Object)
|
||||
for _, f := range g.allFiles {
|
||||
dottedPkg := "." + f.originalPackageName() + "."
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Given a fully-qualified input type name, return the descriptor for the message or enum with that type.
|
||||
func (g *Generator) objectNamed(typeName string) Object {
|
||||
f, ok := g.typeNameToObject[typeName]
|
||||
if !ok {
|
||||
panicln()
|
||||
g.fail("can't find object with type", typeName)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// Print the arguments, 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 *int32:
|
||||
g.WriteString(fmt.Sprintf("%d", *s))
|
||||
default:
|
||||
g.fail(fmt.Sprintf("unknown type in printer: %T", v))
|
||||
}
|
||||
}
|
||||
g.WriteByte('\n')
|
||||
}
|
||||
|
||||
// Indent the output one tab stop.
|
||||
func (g *Generator) in() { g.indent += "\t" }
|
||||
|
||||
// Unindent the output one tab stop.
|
||||
func (g *Generator) out() {
|
||||
if len(g.indent) > 0 {
|
||||
g.indent = g.indent[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the output for all the files we're generating output for.
|
||||
func (g *Generator) GenerateAllFiles() {
|
||||
for i, file := range g.genFiles {
|
||||
g.Reset()
|
||||
g.Generate(file)
|
||||
g.response.File[i] = plugin.NewCodeGeneratorResponse_File()
|
||||
g.response.File[i].Name = proto.String(GoName(*file.Name))
|
||||
g.response.File[i].Content = proto.String(g.String())
|
||||
}
|
||||
}
|
||||
|
||||
// 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.GenerateHeader()
|
||||
g.GenerateImports()
|
||||
for _, enum := range g.file.enum {
|
||||
g.GenerateEnum(enum)
|
||||
}
|
||||
for _, desc := range g.file.desc {
|
||||
g.GenerateMessage(desc)
|
||||
}
|
||||
g.GenerateInitFunction()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// Generate the header, including package definition and imports
|
||||
func (g *Generator) GenerateImports() {
|
||||
if len(g.file.enum) > 0 {
|
||||
g.p(`import "goprotobuf.googlecode.com/hg/proto"`)
|
||||
}
|
||||
for _, s := range g.file.Dependency {
|
||||
// Need to find the descriptor for this file
|
||||
for _, fd := range g.allFiles {
|
||||
if proto.GetString(fd.Name) == s {
|
||||
filename := GoName(s)
|
||||
if strings.HasSuffix(filename, ".go") {
|
||||
filename = filename[0:len(filename)-3]
|
||||
}
|
||||
g.p("import ", fd.packageName(), " ", Quote(filename))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
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.p("const (")
|
||||
g.in()
|
||||
for _, e := range enum.Value {
|
||||
g.p(ccPrefix+*e.Name, " = ", e.Number)
|
||||
}
|
||||
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 int32) *", ccTypeName, " {")
|
||||
g.in()
|
||||
g.p("e := ", ccTypeName, "(x)")
|
||||
g.p("return &e")
|
||||
g.out()
|
||||
g.p("}")
|
||||
g.p()
|
||||
}
|
||||
|
||||
// The tag is a string like "PB(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
|
||||
// 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:
|
||||
// Protect frogs.
|
||||
defaultValue = Quote(defaultValue)
|
||||
// Don't need the quotes
|
||||
defaultValue = defaultValue[1 : len(defaultValue)-1]
|
||||
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 {
|
||||
obj := g.objectNamed(proto.GetString(field.TypeName))
|
||||
enum = ",enum=" + obj.packageName() + "." + CamelCaseSlice(obj.typeName())
|
||||
}
|
||||
name := proto.GetString(field.Name)
|
||||
if name == CamelCase(name) {
|
||||
name = ""
|
||||
} else {
|
||||
name = ",name=" + name
|
||||
}
|
||||
return Quote(fmt.Sprintf("PB(%s,%d,%s%s%s%s)",
|
||||
wiretype,
|
||||
proto.GetInt32(field.Number),
|
||||
optrepreq,
|
||||
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
|
||||
}
|
||||
|
||||
// The type name appropriate for an item. If it's in the current file,
|
||||
// drop the package name and underscore the rest.
|
||||
// Otherwise it's from another package; use the underscored package name
|
||||
// followed by the field name. The result has an initial capital.
|
||||
func (g *Generator) TypeName(obj Object) string {
|
||||
return g.DefaultPackageName(obj) + CamelCaseSlice(obj.typeName())
|
||||
}
|
||||
|
||||
// Like TypeName, but always includes the package name even if it's our own package.
|
||||
func (g *Generator) TypeNameWithPackage(obj Object) string {
|
||||
return obj.packageName() + CamelCaseSlice(obj.typeName())
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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)
|
||||
tag := g.GoTag(field, wiretype)
|
||||
g.p(fieldname, "\t", typename, "\t", tag)
|
||||
}
|
||||
g.p("XXX_unrecognized\t[]byte")
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
||||
// Reset and New functions
|
||||
g.p("func (this *", ccTypeName, ") Reset() {")
|
||||
g.in()
|
||||
g.p("*this = ", ccTypeName, "{}")
|
||||
g.out()
|
||||
g.p("}")
|
||||
g.p("func New", ccTypeName, "() *", ccTypeName, " {")
|
||||
g.in()
|
||||
g.p("return new(", ccTypeName, ")")
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
||||
// 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 *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.Stderr("don't know how to generate constant for", fieldname)
|
||||
continue
|
||||
}
|
||||
def = enum.prefix() + def
|
||||
}
|
||||
g.p(kind, fieldname, " ", typename, " = ", def)
|
||||
}
|
||||
g.p()
|
||||
}
|
||||
|
||||
func (g *Generator) GenerateInitFunction() {
|
||||
g.p("func init() {")
|
||||
g.in()
|
||||
for _, enum := range g.file.enum {
|
||||
g.GenerateEnumRegistration(enum)
|
||||
}
|
||||
g.out()
|
||||
g.p("}")
|
||||
}
|
||||
|
||||
func (g *Generator) GenerateEnumRegistration(enum *EnumDescriptor) {
|
||||
pkg := g.packageName + "." // We always print the full package name here.
|
||||
// The full type name
|
||||
typeName := enum.typeName()
|
||||
// The full type name, CamelCased.
|
||||
ccTypeName := CamelCaseSlice(typeName)
|
||||
g.p("proto.RegisterEnum(", Quote(pkg+ccTypeName), ", ", ccTypeName+"_name, ", ccTypeName+"_value)")
|
||||
}
|
||||
|
||||
// And now lots of helper functions.
|
||||
|
||||
// Return change foo_bar_Baz to FooBar_Baz.
|
||||
func CamelCase(name string) string {
|
||||
elems := strings.Split(name, "_", 0)
|
||||
for i, e := range elems {
|
||||
if e == "" {
|
||||
elems[i] = "_"
|
||||
continue
|
||||
}
|
||||
runes := []int(e)
|
||||
if unicode.IsLower(runes[0]) {
|
||||
runes[0] = unicode.ToUpper(runes[0])
|
||||
elems[i] = string(runes)
|
||||
} else {
|
||||
if i > 0 {
|
||||
elems[i] = "_" + e
|
||||
}
|
||||
}
|
||||
}
|
||||
s := strings.Join(elems, "")
|
||||
// Name must not begin with an underscore.
|
||||
if len(s) > 0 && s[0] == '_' {
|
||||
s = "X" + s[1:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Like CamelCase, but the argument is a slice of strings to
|
||||
// be concatenated with "_"
|
||||
func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
|
||||
|
||||
// Turn a sliced name into a dotted name
|
||||
func DottedSlice(elem []string) string { return strings.Join(elem, ".") }
|
||||
|
||||
// Return 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 GoName(name string) string {
|
||||
if strings.HasSuffix(name, ".proto") {
|
||||
name = name[0 : len(name)-6]
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// Mapping function used to generate Go names from package names, which can be dotted.
|
||||
func DotToUnderscore(rune int) int {
|
||||
if rune == '.' {
|
||||
return '_'
|
||||
}
|
||||
return rune
|
||||
}
|
|
@ -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.$(GOARCH)
|
||||
|
||||
TARG=goprotobuf.googlecode.com/hg/compiler/plugin
|
||||
GOFILES=\
|
||||
plugin.pb.go\
|
||||
|
||||
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
|
|
@ -0,0 +1,47 @@
|
|||
// Code generated by protoc-gen-go from "google/protobuf/compiler/plugin.proto"
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf_compiler
|
||||
|
||||
import google_protobuf "goprotobuf.googlecode.com/hg/compiler/descriptor"
|
||||
|
||||
type CodeGeneratorRequest struct {
|
||||
FileToGenerate []string "PB(bytes,1,rep,name=file_to_generate)"
|
||||
Parameter *string "PB(bytes,2,opt,name=parameter)"
|
||||
ProtoFile []*google_protobuf.FileDescriptorProto "PB(bytes,15,rep,name=proto_file)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *CodeGeneratorRequest) Reset() {
|
||||
*this = CodeGeneratorRequest{}
|
||||
}
|
||||
func NewCodeGeneratorRequest() *CodeGeneratorRequest {
|
||||
return new(CodeGeneratorRequest)
|
||||
}
|
||||
|
||||
type CodeGeneratorResponse struct {
|
||||
Error *string "PB(bytes,1,opt,name=error)"
|
||||
File []*CodeGeneratorResponse_File "PB(bytes,15,rep,name=file)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *CodeGeneratorResponse) Reset() {
|
||||
*this = CodeGeneratorResponse{}
|
||||
}
|
||||
func NewCodeGeneratorResponse() *CodeGeneratorResponse {
|
||||
return new(CodeGeneratorResponse)
|
||||
}
|
||||
|
||||
type CodeGeneratorResponse_File struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
InsertionPoint *string "PB(bytes,2,opt,name=insertion_point)"
|
||||
Content *string "PB(bytes,15,opt,name=content)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *CodeGeneratorResponse_File) Reset() {
|
||||
*this = CodeGeneratorResponse_File{}
|
||||
}
|
||||
func NewCodeGeneratorResponse_File() *CodeGeneratorResponse_File {
|
||||
return new(CodeGeneratorResponse_File)
|
||||
}
|
||||
|
||||
func init() {
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Code generated by protoc-gen-go from "google/protobuf/compiler/plugin.proto"
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf_compiler
|
||||
|
||||
import google_protobuf "goprotobuf.googlecode.com/hg/compiler/descriptor"
|
||||
|
||||
type CodeGeneratorRequest struct {
|
||||
FileToGenerate []string "PB(bytes,1,rep,name=file_to_generate)"
|
||||
Parameter *string "PB(bytes,2,opt,name=parameter)"
|
||||
ProtoFile []*google_protobuf.FileDescriptorProto "PB(bytes,15,rep,name=proto_file)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *CodeGeneratorRequest) Reset() {
|
||||
*this = CodeGeneratorRequest{}
|
||||
}
|
||||
func NewCodeGeneratorRequest() *CodeGeneratorRequest {
|
||||
return new(CodeGeneratorRequest)
|
||||
}
|
||||
|
||||
type CodeGeneratorResponse struct {
|
||||
Error *string "PB(bytes,1,opt,name=error)"
|
||||
File []*CodeGeneratorResponse_File "PB(bytes,15,rep,name=file)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *CodeGeneratorResponse) Reset() {
|
||||
*this = CodeGeneratorResponse{}
|
||||
}
|
||||
func NewCodeGeneratorResponse() *CodeGeneratorResponse {
|
||||
return new(CodeGeneratorResponse)
|
||||
}
|
||||
|
||||
type CodeGeneratorResponse_File struct {
|
||||
Name *string "PB(bytes,1,opt,name=name)"
|
||||
InsertionPoint *string "PB(bytes,2,opt,name=insertion_point)"
|
||||
Content *string "PB(bytes,15,opt,name=content)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *CodeGeneratorResponse_File) Reset() {
|
||||
*this = CodeGeneratorResponse_File{}
|
||||
}
|
||||
func NewCodeGeneratorResponse_File() *CodeGeneratorResponse_File {
|
||||
return new(CodeGeneratorResponse_File)
|
||||
}
|
||||
|
||||
func init() {
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
# 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.$(GOARCH)
|
||||
|
||||
all:
|
||||
@echo run make test
|
||||
|
||||
include $(GOROOT)/src/Make.common
|
||||
include $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/Make.protobuf
|
||||
|
||||
CLEANFILES+=*.pb.go
|
||||
|
||||
test: golden testbuild
|
||||
@echo PASS
|
||||
|
||||
golden:
|
||||
$(QUOTED_GOBIN)/gomake -B test.pb.go
|
||||
diff test.pb.go test.pb.go.golden
|
||||
|
||||
nuke: clean
|
||||
|
||||
testbuild: main.$O
|
||||
$(LD) -L. main.$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
|
|
@ -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 imp;
|
||||
|
||||
message ImportedMessage {
|
||||
required int64 field = 1;
|
||||
|
||||
enum Owner {
|
||||
DAVE = 1;
|
||||
MIKE = 2;
|
||||
}
|
||||
}
|
|
@ -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.NewRequest()
|
||||
_ = multitest.NewMulti1()
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
// Code generated by protoc-gen-go from "test.proto"
|
||||
// DO NOT EDIT!
|
||||
|
||||
package my_test
|
||||
|
||||
import "goprotobuf.googlecode.com/hg/proto"
|
||||
import imp "imp.pb"
|
||||
|
||||
type HatType int32
|
||||
const (
|
||||
HatType_FEDORA = 1
|
||||
HatType_FEZ = 2
|
||||
)
|
||||
var HatType_name = map[int32] string {
|
||||
1: "FEDORA",
|
||||
2: "FEZ",
|
||||
}
|
||||
var HatType_value = map[string] int32 {
|
||||
"FEDORA": 1,
|
||||
"FEZ": 2,
|
||||
}
|
||||
func NewHatType(x int32) *HatType {
|
||||
e := HatType(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type Days int32
|
||||
const (
|
||||
Days_MONDAY = 1
|
||||
Days_TUESDAY = 2
|
||||
Days_LUNDI = 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 int32) *Days {
|
||||
e := Days(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type Request_Color int32
|
||||
const (
|
||||
Request_RED = 0
|
||||
Request_GREEN = 1
|
||||
Request_BLUE = 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 int32) *Request_Color {
|
||||
e := Request_Color(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
Key []int64 "PB(varint,1,rep,name=key)"
|
||||
ImportedMessage *imp.ImportedMessage "PB(bytes,2,opt,name=imported_message)"
|
||||
Hue *Request_Color "PB(varint,3,opt,name=hue,enum=my_test.Request_Color)"
|
||||
Hat *HatType "PB(varint,4,opt,name=hat,enum=my_test.HatType,def=1)"
|
||||
Owner *imp.ImportedMessage_Owner "PB(varint,6,opt,name=owner,enum=imp.ImportedMessage_Owner)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *Request) Reset() {
|
||||
*this = Request{}
|
||||
}
|
||||
func NewRequest() *Request {
|
||||
return new(Request)
|
||||
}
|
||||
const Default_Request_Hat HatType = HatType_FEDORA
|
||||
|
||||
type Reply struct {
|
||||
Found []*Reply_Entry "PB(bytes,1,rep,name=found)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *Reply) Reset() {
|
||||
*this = Reply{}
|
||||
}
|
||||
func NewReply() *Reply {
|
||||
return new(Reply)
|
||||
}
|
||||
|
||||
type Reply_Entry struct {
|
||||
KeyThatNeeds_1234camel_CasIng *int64 "PB(varint,1,req,name=key_that_needs_1234camel_CasIng)"
|
||||
Value *int64 "PB(varint,2,opt,name=value,def=7)"
|
||||
XMyFieldName_2 *int64 "PB(varint,3,opt,name=_my_field_name_2)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *Reply_Entry) Reset() {
|
||||
*this = Reply_Entry{}
|
||||
}
|
||||
func NewReply_Entry() *Reply_Entry {
|
||||
return new(Reply_Entry)
|
||||
}
|
||||
const Default_Reply_Entry_Value int64 = 7
|
||||
|
||||
type ReplyExtensions struct {
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *ReplyExtensions) Reset() {
|
||||
*this = ReplyExtensions{}
|
||||
}
|
||||
func NewReplyExtensions() *ReplyExtensions {
|
||||
return new(ReplyExtensions)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
// 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";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
repeated Entry found = 1;
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message ReplyExtensions {
|
||||
extend Reply {
|
||||
optional double time = 101;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
# 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.$(GOARCH)
|
||||
|
||||
TARG=goprotobuf.googlecode.com/hg/proto
|
||||
GOFILES=\
|
||||
encode.go\
|
||||
decode.go\
|
||||
extensions.go\
|
||||
lib.go\
|
||||
properties.go\
|
||||
text.go\
|
||||
text_parser.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,741 @@
|
|||
// 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 (
|
||||
"bytes"
|
||||
"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.StructType, 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 = bytes.Add(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.StructType, 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.PtrType, is_group bool, base uintptr) os.Error {
|
||||
st := t.Elem().(*reflect.StructType)
|
||||
prop := GetProperties(st)
|
||||
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)] = bytes.Add(nil, o.buf[oi:o.index])
|
||||
}
|
||||
continue
|
||||
}
|
||||
err = o.skipAndSave(st, tag, wire, base)
|
||||
continue
|
||||
}
|
||||
p := prop.Prop[fieldnum]
|
||||
|
||||
if p.dec != nil {
|
||||
if wire != WireStartGroup && wire != p.WireType {
|
||||
err = ErrWrongType
|
||||
continue
|
||||
}
|
||||
err = p.dec(o, p, base, sbase)
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "no protobuf decoder for %s.%s\n", t, st.Field(fieldnum).Name)
|
||||
}
|
||||
if err == nil && is_group {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
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
|
||||
}
|
||||
lb := len(b)
|
||||
if lb == 0 {
|
||||
return nil
|
||||
}
|
||||
x := (*[]uint8)(unsafe.Pointer(base + p.offset))
|
||||
|
||||
y := *x
|
||||
c := cap(y)
|
||||
if c == 0 {
|
||||
initSlice(unsafe.Pointer(x), sbase+p.scratch)
|
||||
y = *x
|
||||
c = cap(y)
|
||||
}
|
||||
|
||||
l := len(y)
|
||||
if l+lb > c {
|
||||
// incremental growth is max(len(slice)*1.5, len(slice)+len(bytes))
|
||||
g := l * 3 / 2
|
||||
if l+lb > g {
|
||||
g = l + lb
|
||||
}
|
||||
z := make([]uint8, l, g)
|
||||
copy(z, y)
|
||||
y = z
|
||||
}
|
||||
|
||||
y = y[0 : l+lb]
|
||||
copy(y[l:l+lb], b)
|
||||
|
||||
*x = y
|
||||
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
|
||||
c := cap(y)
|
||||
if c == 0 {
|
||||
initSlice(unsafe.Pointer(x), sbase+p.scratch)
|
||||
y = *x
|
||||
c = cap(y)
|
||||
}
|
||||
l := len(y)
|
||||
if l >= c {
|
||||
g := l * 3 / 2
|
||||
z := make([]bool, l, g)
|
||||
copy(z, y)
|
||||
y = z
|
||||
}
|
||||
y = y[0 : l+1]
|
||||
y[l] = 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
|
||||
c := cap(y)
|
||||
if c == 0 {
|
||||
initSlice(unsafe.Pointer(x), sbase+p.scratch)
|
||||
y = *x
|
||||
c = cap(y)
|
||||
}
|
||||
l := len(y)
|
||||
if l >= c {
|
||||
g := l * 3 / 2
|
||||
z := make([]int32, l, g)
|
||||
copy(z, y)
|
||||
y = z
|
||||
}
|
||||
y = y[0 : l+1]
|
||||
y[l] = 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
|
||||
c := cap(y)
|
||||
if c == 0 {
|
||||
initSlice(unsafe.Pointer(x), sbase+p.scratch)
|
||||
y = *x
|
||||
c = cap(y)
|
||||
}
|
||||
l := len(y)
|
||||
if l >= c {
|
||||
g := l * 3 / 2
|
||||
z := make([]int64, l, g)
|
||||
copy(z, y)
|
||||
y = z
|
||||
}
|
||||
y = y[0 : l+1]
|
||||
y[l] = 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
|
||||
c := cap(y)
|
||||
if c == 0 {
|
||||
initSlice(unsafe.Pointer(x), sbase+p.scratch)
|
||||
y = *x
|
||||
c = cap(y)
|
||||
}
|
||||
l := len(y)
|
||||
if l >= c {
|
||||
g := l * 3 / 2
|
||||
z := make([]string, l, g)
|
||||
copy(z, y)
|
||||
y = z
|
||||
}
|
||||
y = y[0 : l+1]
|
||||
y[l] = s
|
||||
*x = y
|
||||
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
|
||||
c := cap(y)
|
||||
if c == 0 {
|
||||
initSlice(unsafe.Pointer(x), sbase+p.scratch)
|
||||
y = *x
|
||||
c = cap(y)
|
||||
}
|
||||
l := len(y)
|
||||
if l >= c {
|
||||
g := l * 3 / 2
|
||||
z := make([][]byte, l, g)
|
||||
copy(z, y)
|
||||
y = z
|
||||
}
|
||||
y = y[0 : l+1]
|
||||
y[l] = b
|
||||
*x = y
|
||||
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().(*reflect.StructType)
|
||||
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().(*reflect.StructType)
|
||||
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
|
||||
c := cap(y)
|
||||
if c == 0 {
|
||||
initSlice(unsafe.Pointer(x), sbase+p.scratch)
|
||||
y = *x
|
||||
c = cap(y)
|
||||
}
|
||||
|
||||
l := len(y)
|
||||
if l >= c {
|
||||
// Create a new slice with 1.5X the capacity.
|
||||
g := l * 3 / 2
|
||||
z := make([]*struct{}, l, g)
|
||||
copy(z, y)
|
||||
y = z
|
||||
}
|
||||
y = y[0 : l+1]
|
||||
*x = y
|
||||
|
||||
typ := p.stype.Elem().(*reflect.StructType)
|
||||
structv := unsafe.New(typ)
|
||||
bas := uintptr(structv)
|
||||
y[l] = (*struct{})(structv)
|
||||
|
||||
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[l]))
|
||||
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
|
||||
}
|
|
@ -0,0 +1,557 @@
|
|||
// 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 (
|
||||
"bytes"
|
||||
"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.
|
||||
var ErrRequiredNotSet = os.NewError("required fields not set")
|
||||
|
||||
// ErrRepeatedHasNil is the error returned if Marshal is called with
|
||||
// a protocol buffer struct with a repeated field containing a nil element.
|
||||
var ErrRepeatedHasNil = os.NewError("repeated field has nil")
|
||||
|
||||
// ErrNil is the error returned if Marshal is called with nil.
|
||||
var ErrNil = os.NewError("marshal called with nil")
|
||||
|
||||
// The fundamental encoders that put bytes on the wire.
|
||||
// Those that take integer types all accept uint64 and are
|
||||
// therefore of type valueEncoder.
|
||||
|
||||
// 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 [16]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 {
|
||||
l := len(p.buf)
|
||||
c := cap(p.buf)
|
||||
if l+10 > c {
|
||||
c += c/2 + 10
|
||||
obuf := make([]byte, c)
|
||||
copy(obuf, p.buf)
|
||||
p.buf = obuf
|
||||
}
|
||||
p.buf = p.buf[0:c]
|
||||
|
||||
for {
|
||||
if x < 1<<7 {
|
||||
break
|
||||
}
|
||||
p.buf[l] = uint8(x&0x7f | 0x80)
|
||||
l++
|
||||
x >>= 7
|
||||
}
|
||||
p.buf[l] = uint8(x)
|
||||
p.buf = p.buf[0 : l+1]
|
||||
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 {
|
||||
l := len(p.buf)
|
||||
c := cap(p.buf)
|
||||
if l+8 > c {
|
||||
c += c/2 + 8
|
||||
obuf := make([]byte, c)
|
||||
copy(obuf, p.buf)
|
||||
p.buf = obuf
|
||||
}
|
||||
p.buf = p.buf[0 : l+8]
|
||||
|
||||
p.buf[l] = uint8(x)
|
||||
p.buf[l+1] = uint8(x >> 8)
|
||||
p.buf[l+2] = uint8(x >> 16)
|
||||
p.buf[l+3] = uint8(x >> 24)
|
||||
p.buf[l+4] = uint8(x >> 32)
|
||||
p.buf[l+5] = uint8(x >> 40)
|
||||
p.buf[l+6] = uint8(x >> 48)
|
||||
p.buf[l+7] = 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 {
|
||||
l := len(p.buf)
|
||||
c := cap(p.buf)
|
||||
if l+4 > c {
|
||||
c += c/2 + 4
|
||||
obuf := make([]byte, c)
|
||||
copy(obuf, p.buf)
|
||||
p.buf = obuf
|
||||
}
|
||||
p.buf = p.buf[0 : l+4]
|
||||
|
||||
p.buf[l] = uint8(x)
|
||||
p.buf[l+1] = uint8(x >> 8)
|
||||
p.buf[l+2] = uint8(x >> 16)
|
||||
p.buf[l+3] = 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 = bytes.Add(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 = bytes.Add(p.buf, data)
|
||||
return nil
|
||||
}
|
||||
|
||||
mstat := runtime.MemStats.Mallocs
|
||||
|
||||
t, b, err := getbase(pb)
|
||||
if err == nil {
|
||||
err = p.enc_struct(t.Elem().(*reflect.StructType), 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 = bytes.Add(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 = bytes.Add(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 = bytes.Add(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 = bytes.Add(o.buf, p.tagcode)
|
||||
o.EncodeStringBytes(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
data, err := m.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.buf = bytes.Add(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().(*reflect.StructType)
|
||||
err := o.enc_struct(typ, b)
|
||||
|
||||
nbuf := o.buf
|
||||
o.buf = obuf
|
||||
if err != nil {
|
||||
o.buffree(nbuf)
|
||||
return err
|
||||
}
|
||||
o.buf = bytes.Add(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().(*reflect.StructType)
|
||||
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 = bytes.Add(o.buf, p.tagcode)
|
||||
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 the field is required, we must send something, even if it's an empty array.
|
||||
if !p.Required {
|
||||
l := len(s)
|
||||
if l == 0 {
|
||||
return ErrNil
|
||||
}
|
||||
// check default
|
||||
if l == len(p.Default) {
|
||||
same := true
|
||||
for i := 0; i < len(p.Default); i++ {
|
||||
if p.Default[i] != s[i] {
|
||||
same = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if same {
|
||||
return ErrNil
|
||||
}
|
||||
}
|
||||
}
|
||||
o.buf = bytes.Add(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 = bytes.Add(o.buf, p.tagcode)
|
||||
x := s[i]
|
||||
p.valEnc(o, uint64(x))
|
||||
}
|
||||
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 = bytes.Add(o.buf, p.tagcode)
|
||||
x := s[i]
|
||||
p.valEnc(o, uint64(x))
|
||||
}
|
||||
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 = bytes.Add(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 = bytes.Add(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().(*reflect.StructType)
|
||||
|
||||
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 {
|
||||
data, err := m.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.buf = bytes.Add(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 = bytes.Add(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().(*reflect.StructType)
|
||||
|
||||
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][]byte)(unsafe.Pointer(base + p.offset))
|
||||
for _, b := range v {
|
||||
o.buf = bytes.Add(o.buf, b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode a struct.
|
||||
func (o *Buffer) enc_struct(t *reflect.StructType, 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
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
// 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"
|
||||
"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][]byte
|
||||
}
|
||||
|
||||
// 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
|
||||
Tag string // PB(...) tag style
|
||||
}
|
||||
|
||||
// Return true iff the given field number is in an extension range.
|
||||
func isExtensionField(extended extendableProto, field int32) bool {
|
||||
for _, er := range extended.ExtensionRangeArray() {
|
||||
if er.Start <= field && field <= er.End {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func checkExtensionTypes(extended extendableProto, extension *ExtensionDesc) os.Error {
|
||||
// Check the extended type.
|
||||
if a, b := reflect.Typeof(extended), reflect.Typeof(extension.ExtendedType); a != b {
|
||||
return os.NewError("bad extended type; " + b.String() + " does not extend " + a.String())
|
||||
}
|
||||
// Check the range.
|
||||
if !isExtensionField(extended, extension.Field) {
|
||||
return os.NewError("bad extension number; not in declared ranges")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func HasExtension(extended extendableProto, extension *ExtensionDesc) bool {
|
||||
// TODO: Check types, field numbers, etc.?
|
||||
_, ok := extended.ExtensionMap()[extension.Field]
|
||||
return ok
|
||||
}
|
||||
|
||||
func ClearExtension(extended extendableProto, extension *ExtensionDesc) {
|
||||
// TODO: Check types, field numbers, etc.?
|
||||
extended.ExtensionMap()[extension.Field] = nil, false
|
||||
}
|
||||
|
||||
func GetExtension(extended extendableProto, extension *ExtensionDesc) (interface{}, os.Error) {
|
||||
if err := checkExtensionTypes(extended, extension); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, ok := extended.ExtensionMap()[extension.Field]
|
||||
if !ok {
|
||||
return nil, nil // not an error
|
||||
}
|
||||
|
||||
// Discard wire type and field number varint. It isn't needed.
|
||||
_, n := DecodeVarint(b)
|
||||
o := NewBuffer(b[n:])
|
||||
|
||||
t := reflect.Typeof(extension.ExtensionType).(*reflect.PtrType)
|
||||
props := &Properties{}
|
||||
props.Init(t, "irrelevant_name", extension.Tag, 0)
|
||||
|
||||
base := unsafe.New(t)
|
||||
var sbase uintptr
|
||||
if _, ok := t.Elem().(*reflect.StructType); ok {
|
||||
// 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
|
||||
}
|
||||
|
||||
// TODO(: (needed for repeated extensions)
|
||||
// - ExtensionSize
|
||||
// - AddExtension
|
||||
|
||||
func SetExtension(extended extendableProto, extension *ExtensionDesc, value interface{}) os.Error {
|
||||
if err := checkExtensionTypes(extended, extension); err != nil {
|
||||
return err
|
||||
}
|
||||
if reflect.Typeof(extension.ExtensionType) != reflect.Typeof(value) {
|
||||
return os.NewError("bad extension value type")
|
||||
}
|
||||
|
||||
props := new(Properties)
|
||||
props.Init(reflect.Typeof(extension.ExtensionType), "unknown_name", extension.Tag, 0)
|
||||
|
||||
p := NewBuffer(nil)
|
||||
v := reflect.NewValue(value)
|
||||
if err := props.enc(p, props, v.Addr()); err != nil {
|
||||
return err
|
||||
}
|
||||
extended.ExtensionMap()[extension.Field] = p.buf
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,537 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/goprotobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/*
|
||||
The proto package converts data structures to and from the
|
||||
wire format of protocol buffers. It works in concert with the
|
||||
Go source code generated for .proto files by the protocol compiler.
|
||||
|
||||
A summary of the properties of the protocol buffer interface
|
||||
for a protocol buffer variable v:
|
||||
|
||||
- Names are turned from camel_case to CamelCase for export.
|
||||
- There are no methods on v to set and get fields; just treat
|
||||
them as structure fields.
|
||||
- The zero value for a struct is its correct initialization state.
|
||||
All desired fields must be set before marshaling.
|
||||
- A Reset() method will restore a protobuf struct to its zero state.
|
||||
- Each type T has a method NewT() to create a new instance. It
|
||||
is equivalent to new(T).
|
||||
- Non-repeated fields are pointers to the values; nil means unset.
|
||||
That is, optional or required field int32 f becomes F *int32.
|
||||
- Repeated fields are slices.
|
||||
- Helper functions are available to simplify the getting and setting of fields:
|
||||
foo.String = proto.String("hello") // set field
|
||||
s := proto.GetString(foo.String) // get field
|
||||
- Constants are defined to hold the default values of all fields that
|
||||
have them. They have the form Default_StructName_FieldName.
|
||||
- Enums are given type names and maps between names to values,
|
||||
plus a helper function to create values. Enum values are prefixed
|
||||
with the enum's type name.
|
||||
- Nested groups and enums have type names prefixed with the name of
|
||||
the surrounding message type.
|
||||
- Marshal and Unmarshal are functions to encode and decode the wire format.
|
||||
|
||||
The simplest way to describe this is to see an example.
|
||||
Given file test.proto, containing
|
||||
|
||||
package example;
|
||||
|
||||
enum FOO { X = 17; };
|
||||
|
||||
message Test {
|
||||
required string label = 1;
|
||||
optional int32 type = 2 [default=77];
|
||||
repeated int64 reps = 3;
|
||||
optional group OptionalGroup = 4 {
|
||||
required string RequiredField = 5;
|
||||
};
|
||||
}
|
||||
|
||||
The resulting file, test.pb.go, is:
|
||||
|
||||
package example
|
||||
|
||||
import "goprotobuf.googlecode.com/hg/proto"
|
||||
|
||||
type FOO int32
|
||||
const (
|
||||
FOO_X = 17
|
||||
)
|
||||
var FOO_name = map[int32] string {
|
||||
17: "X",
|
||||
}
|
||||
var FOO_value = map[string] int32 {
|
||||
"X": 17,
|
||||
}
|
||||
func NewFOO(x int32) *FOO {
|
||||
e := FOO(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type Test struct {
|
||||
Label *string "PB(bytes,1,req,name=label)"
|
||||
Type *int32 "PB(varint,2,opt,name=type,def=77)"
|
||||
Reps []int64 "PB(varint,3,rep,name=reps)"
|
||||
Optionalgroup *Test_OptionalGroup "PB(group,4,opt,name=optionalgroup)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *Test) Reset() {
|
||||
*this = Test{}
|
||||
}
|
||||
func NewTest() *Test {
|
||||
return new(Test)
|
||||
}
|
||||
const Default_Test_Type int32 = 77
|
||||
|
||||
type Test_OptionalGroup struct {
|
||||
RequiredField *string "PB(bytes,5,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *Test_OptionalGroup) Reset() {
|
||||
*this = Test_OptionalGroup{}
|
||||
}
|
||||
func NewTest_OptionalGroup() *Test_OptionalGroup {
|
||||
return new(Test_OptionalGroup)
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
|
||||
}
|
||||
|
||||
To create and play with a Test object:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"goprotobuf.googlecode.com/hg/proto"
|
||||
"./example.pb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
test := &example.Test {
|
||||
Label: proto.String("hello"),
|
||||
Type: proto.Int32(17),
|
||||
Optionalgroup: &example.Test_OptionalGroup {
|
||||
RequiredField: proto.String("good bye"),
|
||||
},
|
||||
}
|
||||
data, err := proto.Marshal(test)
|
||||
if err != nil {
|
||||
log.Exit("marshaling error:", err)
|
||||
}
|
||||
newTest := example.NewTest()
|
||||
err = proto.Unmarshal(data, newTest)
|
||||
if err != nil {
|
||||
log.Exit("unmarshaling error:", err)
|
||||
}
|
||||
// Now test and newTest contain the same data.
|
||||
if proto.GetString(test.Label) != proto.GetString(newTest.Label) {
|
||||
log.Exit("data mismatch %q %q", proto.GetString(test.Label), proto.GetString(newTest.Label))
|
||||
}
|
||||
// etc.
|
||||
}
|
||||
*/
|
||||
package proto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Stats records allocation details about the protocol buffer encoders
|
||||
// and decoders. Useful for tuning the library itself.
|
||||
type Stats struct {
|
||||
Emalloc uint64 // mallocs in encode
|
||||
Dmalloc uint64 // mallocs in decode
|
||||
Encode uint64 // number of encodes
|
||||
Decode uint64 // number of decodes
|
||||
Chit uint64 // number of cache hits
|
||||
Cmiss uint64 // number of cache misses
|
||||
}
|
||||
|
||||
var stats Stats
|
||||
|
||||
// GetStats returns a copy of the global Stats structure.
|
||||
func GetStats() Stats { return stats }
|
||||
|
||||
// A Buffer is a buffer manager for marshaling and unmarshaling
|
||||
// protocol buffers. It may be reused between invocations to
|
||||
// reduce memory usage. It is not necessary to use a Buffer;
|
||||
// the global functions Marshal and Unmarshal create a
|
||||
// temporary Buffer and are fine for most applications.
|
||||
type Buffer struct {
|
||||
buf []byte // encode/decode byte stream
|
||||
index int // write point
|
||||
freelist [10][]byte // list of available buffers
|
||||
nfreelist int // number of free buffers
|
||||
ptr uintptr // scratch area for pointers
|
||||
}
|
||||
|
||||
// NewBuffer allocates a new Buffer and initializes its internal data to
|
||||
// the contents of the argument slice.
|
||||
func NewBuffer(e []byte) *Buffer {
|
||||
p := new(Buffer)
|
||||
if e == nil {
|
||||
e = p.bufalloc()
|
||||
}
|
||||
p.buf = e
|
||||
p.index = 0
|
||||
return p
|
||||
}
|
||||
|
||||
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
|
||||
func (p *Buffer) Reset() {
|
||||
if p.buf == nil {
|
||||
p.buf = p.bufalloc()
|
||||
}
|
||||
p.buf = p.buf[0:0] // for reading/writing
|
||||
p.index = 0 // for reading
|
||||
}
|
||||
|
||||
// SetBuf replaces the internal buffer with the slice,
|
||||
// ready for unmarshaling the contents of the slice.
|
||||
func (p *Buffer) SetBuf(s []byte) {
|
||||
p.buf = s
|
||||
p.index = 0
|
||||
}
|
||||
|
||||
// Bytes returns the contents of the Buffer.
|
||||
func (p *Buffer) Bytes() []byte { return p.buf }
|
||||
|
||||
// Allocate a buffer for the Buffer.
|
||||
func (p *Buffer) bufalloc() []byte {
|
||||
if p.nfreelist > 0 {
|
||||
// reuse an old one
|
||||
p.nfreelist--
|
||||
s := p.freelist[p.nfreelist]
|
||||
return s[0:0]
|
||||
}
|
||||
// make a new one
|
||||
s := make([]byte, 0, 16)
|
||||
return s
|
||||
}
|
||||
|
||||
// Free (and remember in freelist) a byte buffer for the Buffer.
|
||||
func (p *Buffer) buffree(s []byte) {
|
||||
if p.nfreelist < len(p.freelist) {
|
||||
// Take next slot.
|
||||
p.freelist[p.nfreelist] = s
|
||||
p.nfreelist++
|
||||
return
|
||||
}
|
||||
|
||||
// Find the smallest.
|
||||
besti := -1
|
||||
bestl := len(s)
|
||||
for i, b := range p.freelist {
|
||||
if len(b) < bestl {
|
||||
besti = i
|
||||
bestl = len(b)
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite the smallest.
|
||||
if besti >= 0 {
|
||||
p.freelist[besti] = s
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routines for simplifying the creation of optional fields of basic type.
|
||||
*/
|
||||
|
||||
// Bool is a helper routine that allocates a new bool value
|
||||
// to store v and returns a pointer to it.
|
||||
func Bool(v bool) *bool {
|
||||
p := new(bool)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// Int32 is a helper routine that allocates a new int32 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Int32(v int32) *int32 {
|
||||
p := new(int32)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// Int is a helper routine that allocates a new int32 value
|
||||
// to store v and returns a pointer to it, but unlike Int32
|
||||
// its argument value is an int.
|
||||
func Int(v int) *int32 {
|
||||
p := new(int32)
|
||||
*p = int32(v)
|
||||
return p
|
||||
}
|
||||
|
||||
// Int64 is a helper routine that allocates a new int64 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Int64(v int64) *int64 {
|
||||
p := new(int64)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// Float32 is a helper routine that allocates a new float32 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Float32(v float32) *float32 {
|
||||
p := new(float32)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// Float64 is a helper routine that allocates a new float64 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Float64(v float64) *float64 {
|
||||
p := new(float64)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// Uint32 is a helper routine that allocates a new uint32 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Uint32(v uint32) *uint32 {
|
||||
p := new(uint32)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// Uint64 is a helper routine that allocates a new uint64 value
|
||||
// to store v and returns a pointer to it.
|
||||
func Uint64(v uint64) *uint64 {
|
||||
p := new(uint64)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// String is a helper routine that allocates a new string value
|
||||
// to store v and returns a pointer to it.
|
||||
func String(v string) *string {
|
||||
p := new(string)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routines for simplifying the fetching of optional fields of basic type.
|
||||
* If the field is missing, they return the zero for the type.
|
||||
*/
|
||||
|
||||
// GetBool is a helper routine that returns an optional bool value.
|
||||
func GetBool(p *bool) bool {
|
||||
if p == nil {
|
||||
return false
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// GetInt32 is a helper routine that returns an optional int32 value.
|
||||
func GetInt32(p *int32) int32 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// GetInt64 is a helper routine that returns an optional int64 value.
|
||||
func GetInt64(p *int64) int64 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// GetFloat32 is a helper routine that returns an optional float32 value.
|
||||
func GetFloat32(p *float32) float32 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// GetFloat64 is a helper routine that returns an optional float64 value.
|
||||
func GetFloat64(p *float64) float64 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// GetUint32 is a helper routine that returns an optional uint32 value.
|
||||
func GetUint32(p *uint32) uint32 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// GetUint64 is a helper routine that returns an optional uint64 value.
|
||||
func GetUint64(p *uint64) uint64 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// GetString is a helper routine that returns an optional string value.
|
||||
func GetString(p *string) string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
// EnumName is a helper function to simplify printing protocol buffer enums
|
||||
// by name. Given an enum map and a value, it returns a useful string.
|
||||
func EnumName(m map[int32]string, v int32) string {
|
||||
s, ok := m[v]
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
return "unknown_enum_" + strconv.Itoa(int(v))
|
||||
}
|
||||
|
||||
// DebugPrint dumps the encoded data in b in a debugging format with a header
|
||||
// including the string s. Used in testing but made available for general debugging.
|
||||
func (o *Buffer) DebugPrint(s string, b []byte) {
|
||||
var u uint64
|
||||
|
||||
obuf := o.buf
|
||||
index := o.index
|
||||
o.buf = b
|
||||
o.index = 0
|
||||
depth := 0
|
||||
|
||||
fmt.Printf("\n--- %s ---\n", s)
|
||||
|
||||
out:
|
||||
for {
|
||||
for i := 0; i < depth; i++ {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
|
||||
index := o.index
|
||||
if index == len(o.buf) {
|
||||
break
|
||||
}
|
||||
|
||||
op, err := o.DecodeVarint()
|
||||
if err != nil {
|
||||
fmt.Printf("%3d: fetching op err %v\n", index, err)
|
||||
break out
|
||||
}
|
||||
tag := op >> 3
|
||||
wire := op & 7
|
||||
|
||||
switch wire {
|
||||
default:
|
||||
fmt.Printf("%3d: t=%3d unknown wire=%d\n",
|
||||
index, tag, wire)
|
||||
break out
|
||||
|
||||
case WireBytes:
|
||||
var r []byte
|
||||
|
||||
r, err = o.DecodeRawBytes(false)
|
||||
if err != nil {
|
||||
break out
|
||||
}
|
||||
fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
|
||||
if len(r) <= 6 {
|
||||
for i := 0; i < len(r); i++ {
|
||||
fmt.Printf(" %.2x", r[i])
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Printf(" %.2x", r[i])
|
||||
}
|
||||
fmt.Printf(" ..")
|
||||
for i := len(r) - 3; i < len(r); i++ {
|
||||
fmt.Printf(" %.2x", r[i])
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
case WireFixed32:
|
||||
u, err = o.DecodeFixed32()
|
||||
if err != nil {
|
||||
fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
|
||||
break out
|
||||
}
|
||||
fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
|
||||
|
||||
case WireFixed64:
|
||||
u, err = o.DecodeFixed64()
|
||||
if err != nil {
|
||||
fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
|
||||
break out
|
||||
}
|
||||
fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
|
||||
break
|
||||
|
||||
case WireVarint:
|
||||
u, err = o.DecodeVarint()
|
||||
if err != nil {
|
||||
fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
|
||||
break out
|
||||
}
|
||||
fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
|
||||
|
||||
case WireStartGroup:
|
||||
if err != nil {
|
||||
fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
|
||||
break out
|
||||
}
|
||||
fmt.Printf("%3d: t=%3d start\n", index, tag)
|
||||
depth++
|
||||
|
||||
case WireEndGroup:
|
||||
depth--
|
||||
if err != nil {
|
||||
fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
|
||||
break out
|
||||
}
|
||||
fmt.Printf("%3d: t=%3d end\n", index, tag)
|
||||
}
|
||||
}
|
||||
|
||||
if depth != 0 {
|
||||
fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
o.buf = obuf
|
||||
o.index = index
|
||||
}
|
|
@ -0,0 +1,515 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/goprotobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
/*
|
||||
* Routines for encoding data into the wire format for protocol buffers.
|
||||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const debug bool = false
|
||||
|
||||
// Constants that identify the encoding of a value on the wire.
|
||||
const (
|
||||
WireVarint = 0
|
||||
WireFixed64 = 1
|
||||
WireBytes = 2
|
||||
WireStartGroup = 3
|
||||
WireEndGroup = 4
|
||||
WireFixed32 = 5
|
||||
)
|
||||
|
||||
const startSize = 10 // initial slice/string sizes
|
||||
|
||||
// Encoders are defined in encoder.go
|
||||
// An encoder outputs the full representation of a field, including its
|
||||
// tag and encoder type.
|
||||
type encoder func(p *Buffer, prop *Properties, base uintptr) os.Error
|
||||
|
||||
// A valueEncoder encodes a single integer in a particular encoding.
|
||||
type valueEncoder func(o *Buffer, x uint64) os.Error
|
||||
|
||||
// Decoders are defined in decode.go
|
||||
// A decoder creates a value from its wire representation.
|
||||
// Unrecognized subelements are saved in unrec.
|
||||
type decoder func(p *Buffer, prop *Properties, base uintptr, sbase uintptr) os.Error
|
||||
|
||||
// A valueDecoder decodes a single integer in a particular encoding.
|
||||
type valueDecoder func(o *Buffer) (x uint64, err os.Error)
|
||||
|
||||
// StructProperties represents properties for all the fields of a struct.
|
||||
type StructProperties struct {
|
||||
Prop []*Properties // properties for each field
|
||||
reqCount int // required count
|
||||
tags map[int]int // map from proto tag to struct field number
|
||||
nscratch uintptr // size of scratch space
|
||||
}
|
||||
|
||||
// Properties represents the protocol-specific behavior of a single struct field.
|
||||
type Properties struct {
|
||||
Name string // name of the field, for error messages
|
||||
OrigName string // original name before protocol compiler (always set)
|
||||
Wire string
|
||||
WireType int
|
||||
Tag int
|
||||
Required bool
|
||||
Optional bool
|
||||
Repeated bool
|
||||
Enum string // set for enum types only
|
||||
Default string // default value
|
||||
def_uint64 uint64
|
||||
|
||||
enc encoder
|
||||
valEnc valueEncoder // set for bool and numeric types only
|
||||
offset uintptr
|
||||
tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
|
||||
tagbuf [8]byte
|
||||
stype *reflect.PtrType
|
||||
|
||||
dec decoder
|
||||
valDec valueDecoder // set for bool and numeric types only
|
||||
scratch uintptr
|
||||
sizeof int // calculations of scratch space
|
||||
alignof int
|
||||
}
|
||||
|
||||
// String formats the properties in the "PB(...)" struct tag style.
|
||||
func (p *Properties) String() string {
|
||||
s := p.Wire
|
||||
s = ","
|
||||
s += strconv.Itoa(p.Tag)
|
||||
if p.Required {
|
||||
s += ",req"
|
||||
}
|
||||
if p.Optional {
|
||||
s += ",opt"
|
||||
}
|
||||
if p.Repeated {
|
||||
s += ",rep"
|
||||
}
|
||||
if p.OrigName != p.Name {
|
||||
s += ",name=" + p.OrigName
|
||||
}
|
||||
if len(p.Enum) > 0 {
|
||||
s += ",enum=" + p.Enum
|
||||
}
|
||||
if len(p.Default) > 0 {
|
||||
s += ",def=" + p.Default
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Parse populates p by parsing a string in the "PB(...)" struct tag style.
|
||||
func (p *Properties) Parse(s string) {
|
||||
// "bytes,49,opt,def=hello!,name=foo"
|
||||
fields := strings.Split(s, ",", 0) // breaks def=, but handled below.
|
||||
if len(fields) < 2 {
|
||||
fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
|
||||
return
|
||||
}
|
||||
|
||||
p.Wire = fields[0]
|
||||
switch p.Wire {
|
||||
case "varint":
|
||||
p.WireType = WireVarint
|
||||
p.valEnc = (*Buffer).EncodeVarint
|
||||
p.valDec = (*Buffer).DecodeVarint
|
||||
case "fixed32":
|
||||
p.WireType = WireFixed32
|
||||
p.valEnc = (*Buffer).EncodeFixed32
|
||||
p.valDec = (*Buffer).DecodeFixed32
|
||||
case "fixed64":
|
||||
p.WireType = WireFixed64
|
||||
p.valEnc = (*Buffer).EncodeFixed64
|
||||
p.valDec = (*Buffer).DecodeFixed64
|
||||
case "zigzag32":
|
||||
p.WireType = WireVarint
|
||||
p.valEnc = (*Buffer).EncodeZigzag32
|
||||
p.valDec = (*Buffer).DecodeZigzag32
|
||||
case "zigzag64":
|
||||
p.WireType = WireVarint
|
||||
p.valEnc = (*Buffer).EncodeZigzag64
|
||||
p.valDec = (*Buffer).DecodeZigzag64
|
||||
case "bytes", "group":
|
||||
p.WireType = WireBytes
|
||||
// no numeric converter for non-numeric types
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
|
||||
return
|
||||
}
|
||||
|
||||
var err os.Error
|
||||
p.Tag, err = strconv.Atoi(fields[1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 2; i < len(fields); i++ {
|
||||
f := fields[i]
|
||||
switch {
|
||||
case f == "req":
|
||||
p.Required = true
|
||||
case f == "opt":
|
||||
p.Optional = true
|
||||
case f == "rep":
|
||||
p.Repeated = true
|
||||
case len(f) >= 5 && f[0:5] == "name=":
|
||||
p.OrigName = f[5:len(f)]
|
||||
case len(f) >= 5 && f[0:5] == "enum=":
|
||||
p.Enum = f[5:len(f)]
|
||||
case len(f) >= 4 && f[0:4] == "def=":
|
||||
p.Default = f[4:len(f)] // rest of string
|
||||
if i+1 < len(fields) {
|
||||
// Commas aren't escaped, and def is always last.
|
||||
p.Default += "," + strings.Join(fields[i+1:len(fields)], ",")
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the fields for encoding and decoding.
|
||||
func (p *Properties) setEncAndDec(typ reflect.Type) {
|
||||
var vbool bool
|
||||
var vbyte byte
|
||||
var vint32 int32
|
||||
var vint64 int64
|
||||
var vfloat32 float32
|
||||
var vfloat64 float64
|
||||
var vstring string
|
||||
var vslice []byte
|
||||
|
||||
p.enc = nil
|
||||
p.dec = nil
|
||||
|
||||
switch t1 := typ.(type) {
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "proto: no coders for %T\n", t1)
|
||||
break
|
||||
|
||||
case *reflect.PtrType:
|
||||
switch t2 := t1.Elem().(type) {
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "proto: no encoder function for %T -> %T\n", t1, t2)
|
||||
break
|
||||
case *reflect.BoolType:
|
||||
p.enc = (*Buffer).enc_bool
|
||||
p.dec = (*Buffer).dec_bool
|
||||
p.alignof = unsafe.Alignof(vbool)
|
||||
p.sizeof = unsafe.Sizeof(vbool)
|
||||
case *reflect.Int32Type, *reflect.Uint32Type:
|
||||
p.enc = (*Buffer).enc_int32
|
||||
p.dec = (*Buffer).dec_int32
|
||||
p.alignof = unsafe.Alignof(vint32)
|
||||
p.sizeof = unsafe.Sizeof(vint32)
|
||||
case *reflect.Int64Type, *reflect.Uint64Type:
|
||||
p.enc = (*Buffer).enc_int64
|
||||
p.dec = (*Buffer).dec_int64
|
||||
p.alignof = unsafe.Alignof(vint64)
|
||||
p.sizeof = unsafe.Sizeof(vint64)
|
||||
case *reflect.Float32Type:
|
||||
p.enc = (*Buffer).enc_int32 // can just treat them as bits
|
||||
p.dec = (*Buffer).dec_int32
|
||||
p.alignof = unsafe.Alignof(vfloat32)
|
||||
p.sizeof = unsafe.Sizeof(vfloat32)
|
||||
case *reflect.Float64Type:
|
||||
p.enc = (*Buffer).enc_int64 // can just treat them as bits
|
||||
p.dec = (*Buffer).dec_int64
|
||||
p.alignof = unsafe.Alignof(vfloat64)
|
||||
p.sizeof = unsafe.Sizeof(vfloat64)
|
||||
case *reflect.StringType:
|
||||
p.enc = (*Buffer).enc_string
|
||||
p.dec = (*Buffer).dec_string
|
||||
p.alignof = unsafe.Alignof(vstring)
|
||||
p.sizeof = unsafe.Sizeof(vstring) + startSize*unsafe.Sizeof(vbyte)
|
||||
case *reflect.StructType:
|
||||
p.stype = t1
|
||||
if p.Wire == "bytes" {
|
||||
p.enc = (*Buffer).enc_struct_message
|
||||
p.dec = (*Buffer).dec_struct_message
|
||||
} else {
|
||||
p.enc = (*Buffer).enc_struct_group
|
||||
p.dec = (*Buffer).dec_struct_group
|
||||
}
|
||||
}
|
||||
|
||||
case *reflect.SliceType:
|
||||
switch t2 := t1.Elem().(type) {
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "proto: no oenc for %T -> %T\n", t1, t2)
|
||||
break
|
||||
case *reflect.Uint8Type:
|
||||
p.enc = (*Buffer).enc_slice_byte
|
||||
p.dec = (*Buffer).dec_slice_byte
|
||||
p.alignof = unsafe.Alignof(vbyte)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vbyte)
|
||||
case *reflect.BoolType:
|
||||
p.enc = (*Buffer).enc_slice_bool
|
||||
p.dec = (*Buffer).dec_slice_bool
|
||||
p.alignof = unsafe.Alignof(vbool)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vbool)
|
||||
case *reflect.Int32Type, *reflect.Uint32Type:
|
||||
p.enc = (*Buffer).enc_slice_int32
|
||||
p.dec = (*Buffer).dec_slice_int32
|
||||
p.alignof = unsafe.Alignof(vint32)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vint32)
|
||||
case *reflect.Int64Type, *reflect.Uint64Type:
|
||||
p.enc = (*Buffer).enc_slice_int64
|
||||
p.dec = (*Buffer).dec_slice_int64
|
||||
p.alignof = unsafe.Alignof(vint64)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vint64)
|
||||
case *reflect.Float32Type:
|
||||
p.enc = (*Buffer).enc_slice_int32 // can just treat them as bits
|
||||
p.dec = (*Buffer).dec_slice_int32
|
||||
p.alignof = unsafe.Alignof(vfloat32)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vfloat32)
|
||||
case *reflect.Float64Type:
|
||||
p.enc = (*Buffer).enc_slice_int64 // can just treat them as bits
|
||||
p.dec = (*Buffer).dec_slice_int64
|
||||
p.alignof = unsafe.Alignof(vfloat64)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vfloat64)
|
||||
case *reflect.StringType:
|
||||
p.enc = (*Buffer).enc_slice_string
|
||||
p.dec = (*Buffer).dec_slice_string
|
||||
p.alignof = unsafe.Alignof(vstring)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vstring)
|
||||
case *reflect.PtrType:
|
||||
switch t3 := t2.Elem().(type) {
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "proto: no oenc for %T -> %T -> %T\n", t1, t2, t3)
|
||||
break
|
||||
case *reflect.StructType:
|
||||
p.stype = t2
|
||||
p.enc = (*Buffer).enc_slice_struct_group
|
||||
p.dec = (*Buffer).dec_slice_struct_group
|
||||
if p.Wire == "bytes" {
|
||||
p.enc = (*Buffer).enc_slice_struct_message
|
||||
p.dec = (*Buffer).dec_slice_struct_message
|
||||
}
|
||||
p.alignof = unsafe.Alignof(vslice)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vslice)
|
||||
}
|
||||
case *reflect.SliceType:
|
||||
switch t3 := t2.Elem().(type) {
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "proto: no oenc for %T -> %T -> %T\n", t1, t2, t3)
|
||||
break
|
||||
case *reflect.Uint8Type:
|
||||
p.enc = (*Buffer).enc_slice_slice_byte
|
||||
p.dec = (*Buffer).dec_slice_slice_byte
|
||||
p.alignof = unsafe.Alignof(vslice)
|
||||
p.sizeof = startSize * unsafe.Sizeof(vslice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// precalculate tag code
|
||||
x := p.Tag<<3 | p.WireType
|
||||
i := 0
|
||||
for i = 0; x > 127; i++ {
|
||||
p.tagbuf[i] = 0x80 | uint8(x&0x7F)
|
||||
x >>= 7
|
||||
}
|
||||
p.tagbuf[i] = uint8(x)
|
||||
p.tagcode = p.tagbuf[0 : i+1]
|
||||
}
|
||||
|
||||
// Init populates the properties from a protocol buffer struct field.
|
||||
func (p *Properties) Init(typ reflect.Type, name, tag string, offset uintptr) {
|
||||
// "PB(bytes,49,opt,def=hello!)"
|
||||
// TODO: should not assume the only thing is PB(...)
|
||||
p.Name = name
|
||||
p.OrigName = name
|
||||
p.offset = offset
|
||||
|
||||
if len(tag) < 4 || tag[0:3] != "PB(" || tag[len(tag)-1] != ')' {
|
||||
return
|
||||
}
|
||||
p.Parse(tag[3 : len(tag)-1])
|
||||
p.setEncAndDec(typ)
|
||||
}
|
||||
|
||||
var (
|
||||
mutex sync.Mutex
|
||||
propertiesMap = make(map[*reflect.StructType]*StructProperties)
|
||||
)
|
||||
|
||||
// GetProperties returns the list of properties for the type represented by t.
|
||||
func GetProperties(t *reflect.StructType) *StructProperties {
|
||||
mutex.Lock()
|
||||
if prop, ok := propertiesMap[t]; ok {
|
||||
mutex.Unlock()
|
||||
stats.Chit++
|
||||
return prop
|
||||
}
|
||||
stats.Cmiss++
|
||||
|
||||
prop := new(StructProperties)
|
||||
|
||||
// build properties
|
||||
prop.Prop = make([]*Properties, t.NumField())
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
p := new(Properties)
|
||||
p.Init(f.Type, f.Name, f.Tag, f.Offset)
|
||||
if f.Name == "XXX_extensions" { // special case
|
||||
var vmap map[int32][]byte
|
||||
p.enc = (*Buffer).enc_map
|
||||
p.dec = nil // not needed
|
||||
p.alignof = unsafe.Alignof(vmap)
|
||||
p.sizeof = unsafe.Sizeof(vmap)
|
||||
}
|
||||
prop.Prop[i] = p
|
||||
if debug {
|
||||
print(i, " ", f.Name, " ", t.String(), " ")
|
||||
if p.Tag > 0 {
|
||||
print(p.String())
|
||||
}
|
||||
print("\n")
|
||||
}
|
||||
if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") {
|
||||
fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
|
||||
}
|
||||
}
|
||||
|
||||
// build required counts
|
||||
// build scratch offsets
|
||||
// build tags
|
||||
reqCount := 0
|
||||
scratch := uintptr(0)
|
||||
prop.tags = make(map[int]int)
|
||||
for i, p := range prop.Prop {
|
||||
if p.Required {
|
||||
reqCount++
|
||||
}
|
||||
scratch = align(scratch, p.alignof)
|
||||
p.scratch = scratch
|
||||
scratch += uintptr(p.sizeof)
|
||||
prop.tags[p.Tag] = i
|
||||
}
|
||||
prop.reqCount = reqCount
|
||||
prop.nscratch = scratch
|
||||
|
||||
propertiesMap[t] = prop
|
||||
mutex.Unlock()
|
||||
return prop
|
||||
}
|
||||
|
||||
// Alignment of the data in the scratch area. It doesn't have to be
|
||||
// exact, just conservative. Returns the first number >= o that divides s.
|
||||
func align(o uintptr, s int) uintptr {
|
||||
if s != 0 {
|
||||
for o%uintptr(s) != 0 {
|
||||
o++
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// Return the field index of the named field.
|
||||
// Returns nil if there is no such field.
|
||||
func fieldIndex(t *reflect.StructType, name string) []int {
|
||||
if field, ok := t.FieldByName(name); ok {
|
||||
return field.Index
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return the Properties object for the x[0]'th field of the structure.
|
||||
func propByIndex(t *reflect.StructType, x []int) *Properties {
|
||||
if len(x) != 1 {
|
||||
fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
|
||||
return nil
|
||||
}
|
||||
prop := GetProperties(t)
|
||||
return prop.Prop[x[0]]
|
||||
}
|
||||
|
||||
// Get the address and type of a pointer to the structure from an interface.
|
||||
// unsafe.Reflect can do this, but does multiple mallocs.
|
||||
func getbase(pb interface{}) (t *reflect.PtrType, b uintptr, err os.Error) {
|
||||
// get pointer
|
||||
x := *(*[2]uintptr)(unsafe.Pointer(&pb))
|
||||
b = x[1]
|
||||
if b == 0 {
|
||||
err = ErrNil
|
||||
return
|
||||
}
|
||||
|
||||
// get the reflect type of the struct.
|
||||
t1 := unsafe.Typeof(pb).(*runtime.PtrType)
|
||||
t = (*reflect.PtrType)(unsafe.Pointer(t1))
|
||||
return
|
||||
}
|
||||
|
||||
// Allocate the aux space containing all the decoded data. The structure
|
||||
// handed into Unmarshal is filled with pointers to this newly allocated
|
||||
// data.
|
||||
func getsbase(prop *StructProperties) uintptr {
|
||||
var vbyteptr *byte
|
||||
if prop.nscratch == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// allocate the decode space as pointers
|
||||
// so that the GC will scan it for pointers
|
||||
n := uintptr(unsafe.Sizeof(vbyteptr))
|
||||
b := make([]*byte, (prop.nscratch+n-1)/n)
|
||||
sbase := uintptr(unsafe.Pointer(&b[0]))
|
||||
return sbase
|
||||
}
|
||||
|
||||
// A global registry of enum types.
|
||||
// The generated code will register the generated maps by calling RegisterEnum.
|
||||
|
||||
var enumNameMaps = make(map[string]map[int32]string)
|
||||
var enumValueMaps = make(map[string]map[string]int32)
|
||||
|
||||
// RegisterEnum is called from the generated code to install the enum descriptor
|
||||
// maps into the global table to aid parsing ASCII protocol buffers.
|
||||
func RegisterEnum(typeName string, nameMap map[int32]string, valueMap map[string]int32) {
|
||||
if _, ok := enumNameMaps[typeName]; ok {
|
||||
panicln("proto: duplicate enum registered: ", typeName)
|
||||
}
|
||||
enumNameMaps[typeName] = nameMap
|
||||
enumValueMaps[typeName] = valueMap
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
# 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.$(GOARCH)
|
||||
include $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/Make.protobuf
|
||||
|
||||
TARG=test_proto
|
||||
GOFILES=\
|
||||
test.pb.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
|
||||
CLEANFILES+=test.pb.go
|
||||
|
||||
# These rules are just aids to development. Not needed for testing.
|
||||
regenerate:
|
||||
rm test.pb.go
|
||||
make test.pb.go
|
||||
|
||||
restore:
|
||||
cp test.pb.go.golden test.pb.go
|
||||
|
||||
preserve:
|
||||
cp test.pb.go test.pb.go.golden
|
|
@ -0,0 +1,334 @@
|
|||
// Code generated by protoc-gen-go from "test.proto"
|
||||
// DO NOT EDIT!
|
||||
|
||||
package test_proto
|
||||
|
||||
import "goprotobuf.googlecode.com/hg/proto"
|
||||
|
||||
type FOO int32
|
||||
const (
|
||||
FOO_FOO1 = 1
|
||||
)
|
||||
var FOO_name = map[int32] string {
|
||||
1: "FOO1",
|
||||
}
|
||||
var FOO_value = map[string] int32 {
|
||||
"FOO1": 1,
|
||||
}
|
||||
func NewFOO(x int32) *FOO {
|
||||
e := FOO(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type GoTest_KIND int32
|
||||
const (
|
||||
GoTest_VOID = 0
|
||||
GoTest_BOOL = 1
|
||||
GoTest_BYTES = 2
|
||||
GoTest_FINGERPRINT = 3
|
||||
GoTest_FLOAT = 4
|
||||
GoTest_INT = 5
|
||||
GoTest_STRING = 6
|
||||
GoTest_TIME = 7
|
||||
GoTest_TUPLE = 8
|
||||
GoTest_ARRAY = 9
|
||||
GoTest_MAP = 10
|
||||
GoTest_TABLE = 11
|
||||
GoTest_FUNCTION = 12
|
||||
)
|
||||
var GoTest_KIND_name = map[int32] string {
|
||||
0: "VOID",
|
||||
1: "BOOL",
|
||||
2: "BYTES",
|
||||
3: "FINGERPRINT",
|
||||
4: "FLOAT",
|
||||
5: "INT",
|
||||
6: "STRING",
|
||||
7: "TIME",
|
||||
8: "TUPLE",
|
||||
9: "ARRAY",
|
||||
10: "MAP",
|
||||
11: "TABLE",
|
||||
12: "FUNCTION",
|
||||
}
|
||||
var GoTest_KIND_value = map[string] int32 {
|
||||
"VOID": 0,
|
||||
"BOOL": 1,
|
||||
"BYTES": 2,
|
||||
"FINGERPRINT": 3,
|
||||
"FLOAT": 4,
|
||||
"INT": 5,
|
||||
"STRING": 6,
|
||||
"TIME": 7,
|
||||
"TUPLE": 8,
|
||||
"ARRAY": 9,
|
||||
"MAP": 10,
|
||||
"TABLE": 11,
|
||||
"FUNCTION": 12,
|
||||
}
|
||||
func NewGoTest_KIND(x int32) *GoTest_KIND {
|
||||
e := GoTest_KIND(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type MyMessage_Color int32
|
||||
const (
|
||||
MyMessage_RED = 0
|
||||
MyMessage_GREEN = 1
|
||||
MyMessage_BLUE = 2
|
||||
)
|
||||
var MyMessage_Color_name = map[int32] string {
|
||||
0: "RED",
|
||||
1: "GREEN",
|
||||
2: "BLUE",
|
||||
}
|
||||
var MyMessage_Color_value = map[string] int32 {
|
||||
"RED": 0,
|
||||
"GREEN": 1,
|
||||
"BLUE": 2,
|
||||
}
|
||||
func NewMyMessage_Color(x int32) *MyMessage_Color {
|
||||
e := MyMessage_Color(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type GoEnum struct {
|
||||
Foo *FOO "PB(varint,1,req,name=foo,enum=test_proto.FOO)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoEnum) Reset() {
|
||||
*this = GoEnum{}
|
||||
}
|
||||
func NewGoEnum() *GoEnum {
|
||||
return new(GoEnum)
|
||||
}
|
||||
|
||||
type GoTestField struct {
|
||||
Label *string "PB(bytes,1,req)"
|
||||
Type *string "PB(bytes,2,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTestField) Reset() {
|
||||
*this = GoTestField{}
|
||||
}
|
||||
func NewGoTestField() *GoTestField {
|
||||
return new(GoTestField)
|
||||
}
|
||||
|
||||
type GoTest struct {
|
||||
Kind *int32 "PB(varint,1,req)"
|
||||
Table *string "PB(bytes,2,opt)"
|
||||
Param *int32 "PB(varint,3,opt)"
|
||||
RequiredField *GoTestField "PB(bytes,4,req)"
|
||||
RepeatedField []*GoTestField "PB(bytes,5,rep)"
|
||||
OptionalField *GoTestField "PB(bytes,6,opt)"
|
||||
F_BoolRequired *bool "PB(varint,10,req,name=F_Bool_required)"
|
||||
F_Int32Required *int32 "PB(varint,11,req,name=F_Int32_required)"
|
||||
F_Int64Required *int64 "PB(varint,12,req,name=F_Int64_required)"
|
||||
F_Fixed32Required *uint32 "PB(fixed32,13,req,name=F_Fixed32_required)"
|
||||
F_Fixed64Required *uint64 "PB(fixed64,14,req,name=F_Fixed64_required)"
|
||||
F_Uint32Required *uint32 "PB(varint,15,req,name=F_Uint32_required)"
|
||||
F_Uint64Required *uint64 "PB(varint,16,req,name=F_Uint64_required)"
|
||||
F_FloatRequired *float32 "PB(fixed32,17,req,name=F_Float_required)"
|
||||
F_DoubleRequired *float64 "PB(fixed64,18,req,name=F_Double_required)"
|
||||
F_StringRequired *string "PB(bytes,19,req,name=F_String_required)"
|
||||
F_BytesRequired []byte "PB(bytes,101,req,name=F_Bytes_required)"
|
||||
F_Sint32Required *int32 "PB(zigzag32,102,req,name=F_Sint32_required)"
|
||||
F_Sint64Required *int64 "PB(zigzag64,103,req,name=F_Sint64_required)"
|
||||
F_BoolRepeated []bool "PB(varint,20,rep,name=F_Bool_repeated)"
|
||||
F_Int32Repeated []int32 "PB(varint,21,rep,name=F_Int32_repeated)"
|
||||
F_Int64Repeated []int64 "PB(varint,22,rep,name=F_Int64_repeated)"
|
||||
F_Fixed32Repeated []uint32 "PB(fixed32,23,rep,name=F_Fixed32_repeated)"
|
||||
F_Fixed64Repeated []uint64 "PB(fixed64,24,rep,name=F_Fixed64_repeated)"
|
||||
F_Uint32Repeated []uint32 "PB(varint,25,rep,name=F_Uint32_repeated)"
|
||||
F_Uint64Repeated []uint64 "PB(varint,26,rep,name=F_Uint64_repeated)"
|
||||
F_FloatRepeated []float32 "PB(fixed32,27,rep,name=F_Float_repeated)"
|
||||
F_DoubleRepeated []float64 "PB(fixed64,28,rep,name=F_Double_repeated)"
|
||||
F_StringRepeated []string "PB(bytes,29,rep,name=F_String_repeated)"
|
||||
F_BytesRepeated [][]byte "PB(bytes,201,rep,name=F_Bytes_repeated)"
|
||||
F_Sint32Repeated []int32 "PB(zigzag32,202,rep,name=F_Sint32_repeated)"
|
||||
F_Sint64Repeated []int64 "PB(zigzag64,203,rep,name=F_Sint64_repeated)"
|
||||
F_BoolOptional *bool "PB(varint,30,opt,name=F_Bool_optional)"
|
||||
F_Int32Optional *int32 "PB(varint,31,opt,name=F_Int32_optional)"
|
||||
F_Int64Optional *int64 "PB(varint,32,opt,name=F_Int64_optional)"
|
||||
F_Fixed32Optional *uint32 "PB(fixed32,33,opt,name=F_Fixed32_optional)"
|
||||
F_Fixed64Optional *uint64 "PB(fixed64,34,opt,name=F_Fixed64_optional)"
|
||||
F_Uint32Optional *uint32 "PB(varint,35,opt,name=F_Uint32_optional)"
|
||||
F_Uint64Optional *uint64 "PB(varint,36,opt,name=F_Uint64_optional)"
|
||||
F_FloatOptional *float32 "PB(fixed32,37,opt,name=F_Float_optional)"
|
||||
F_DoubleOptional *float64 "PB(fixed64,38,opt,name=F_Double_optional)"
|
||||
F_StringOptional *string "PB(bytes,39,opt,name=F_String_optional)"
|
||||
F_BytesOptional []byte "PB(bytes,301,opt,name=F_Bytes_optional)"
|
||||
F_Sint32Optional *int32 "PB(zigzag32,302,opt,name=F_Sint32_optional)"
|
||||
F_Sint64Optional *int64 "PB(zigzag64,303,opt,name=F_Sint64_optional)"
|
||||
F_BoolDefaulted *bool "PB(varint,40,opt,name=F_Bool_defaulted,def=1)"
|
||||
F_Int32Defaulted *int32 "PB(varint,41,opt,name=F_Int32_defaulted,def=32)"
|
||||
F_Int64Defaulted *int64 "PB(varint,42,opt,name=F_Int64_defaulted,def=64)"
|
||||
F_Fixed32Defaulted *uint32 "PB(fixed32,43,opt,name=F_Fixed32_defaulted,def=320)"
|
||||
F_Fixed64Defaulted *uint64 "PB(fixed64,44,opt,name=F_Fixed64_defaulted,def=640)"
|
||||
F_Uint32Defaulted *uint32 "PB(varint,45,opt,name=F_Uint32_defaulted,def=3200)"
|
||||
F_Uint64Defaulted *uint64 "PB(varint,46,opt,name=F_Uint64_defaulted,def=6400)"
|
||||
F_FloatDefaulted *float32 "PB(fixed32,47,opt,name=F_Float_defaulted,def=314159)"
|
||||
F_DoubleDefaulted *float64 "PB(fixed64,48,opt,name=F_Double_defaulted,def=271828)"
|
||||
F_StringDefaulted *string "PB(bytes,49,opt,name=F_String_defaulted,def=hello, \\\"world!\\\"\\n)"
|
||||
F_BytesDefaulted []byte "PB(bytes,401,opt,name=F_Bytes_defaulted,def=Bignose)"
|
||||
F_Sint32Defaulted *int32 "PB(zigzag32,402,opt,name=F_Sint32_defaulted,def=-32)"
|
||||
F_Sint64Defaulted *int64 "PB(zigzag64,403,opt,name=F_Sint64_defaulted,def=-64)"
|
||||
Requiredgroup *GoTest_RequiredGroup "PB(group,70,req,name=requiredgroup)"
|
||||
Repeatedgroup []*GoTest_RepeatedGroup "PB(group,80,rep,name=repeatedgroup)"
|
||||
Optionalgroup *GoTest_OptionalGroup "PB(group,90,opt,name=optionalgroup)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest) Reset() {
|
||||
*this = GoTest{}
|
||||
}
|
||||
func NewGoTest() *GoTest {
|
||||
return new(GoTest)
|
||||
}
|
||||
const Default_GoTest_F_BoolDefaulted bool = true
|
||||
const Default_GoTest_F_Int32Defaulted int32 = 32
|
||||
const Default_GoTest_F_Int64Defaulted int64 = 64
|
||||
const Default_GoTest_F_Fixed32Defaulted uint32 = 320
|
||||
const Default_GoTest_F_Fixed64Defaulted uint64 = 640
|
||||
const Default_GoTest_F_Uint32Defaulted uint32 = 3200
|
||||
const Default_GoTest_F_Uint64Defaulted uint64 = 6400
|
||||
const Default_GoTest_F_FloatDefaulted float32 = 314159
|
||||
const Default_GoTest_F_DoubleDefaulted float64 = 271828
|
||||
const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n"
|
||||
var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose")
|
||||
const Default_GoTest_F_Sint32Defaulted int32 = -32
|
||||
const Default_GoTest_F_Sint64Defaulted int64 = -64
|
||||
|
||||
type GoTest_RequiredGroup struct {
|
||||
RequiredField *string "PB(bytes,71,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest_RequiredGroup) Reset() {
|
||||
*this = GoTest_RequiredGroup{}
|
||||
}
|
||||
func NewGoTest_RequiredGroup() *GoTest_RequiredGroup {
|
||||
return new(GoTest_RequiredGroup)
|
||||
}
|
||||
|
||||
type GoTest_RepeatedGroup struct {
|
||||
RequiredField *string "PB(bytes,81,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest_RepeatedGroup) Reset() {
|
||||
*this = GoTest_RepeatedGroup{}
|
||||
}
|
||||
func NewGoTest_RepeatedGroup() *GoTest_RepeatedGroup {
|
||||
return new(GoTest_RepeatedGroup)
|
||||
}
|
||||
|
||||
type GoTest_OptionalGroup struct {
|
||||
RequiredField *string "PB(bytes,91,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest_OptionalGroup) Reset() {
|
||||
*this = GoTest_OptionalGroup{}
|
||||
}
|
||||
func NewGoTest_OptionalGroup() *GoTest_OptionalGroup {
|
||||
return new(GoTest_OptionalGroup)
|
||||
}
|
||||
|
||||
type GoSkipTest struct {
|
||||
SkipInt32 *int32 "PB(varint,11,req,name=skip_int32)"
|
||||
SkipFixed32 *uint32 "PB(fixed32,12,req,name=skip_fixed32)"
|
||||
SkipFixed64 *uint64 "PB(fixed64,13,req,name=skip_fixed64)"
|
||||
SkipString *string "PB(bytes,14,req,name=skip_string)"
|
||||
Skipgroup *GoSkipTest_SkipGroup "PB(group,15,req,name=skipgroup)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoSkipTest) Reset() {
|
||||
*this = GoSkipTest{}
|
||||
}
|
||||
func NewGoSkipTest() *GoSkipTest {
|
||||
return new(GoSkipTest)
|
||||
}
|
||||
|
||||
type GoSkipTest_SkipGroup struct {
|
||||
GroupInt32 *int32 "PB(varint,16,req,name=group_int32)"
|
||||
GroupString *string "PB(bytes,17,req,name=group_string)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoSkipTest_SkipGroup) Reset() {
|
||||
*this = GoSkipTest_SkipGroup{}
|
||||
}
|
||||
func NewGoSkipTest_SkipGroup() *GoSkipTest_SkipGroup {
|
||||
return new(GoSkipTest_SkipGroup)
|
||||
}
|
||||
|
||||
type InnerMessage struct {
|
||||
Host *string "PB(bytes,1,req,name=host)"
|
||||
Port *int32 "PB(varint,2,opt,name=port,def=4000)"
|
||||
Connected *bool "PB(varint,3,opt,name=connected)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *InnerMessage) Reset() {
|
||||
*this = InnerMessage{}
|
||||
}
|
||||
func NewInnerMessage() *InnerMessage {
|
||||
return new(InnerMessage)
|
||||
}
|
||||
const Default_InnerMessage_Port int32 = 4000
|
||||
|
||||
type OtherMessage struct {
|
||||
Key *int64 "PB(varint,1,opt,name=key)"
|
||||
Value []byte "PB(bytes,2,opt,name=value)"
|
||||
Weight *float32 "PB(fixed32,3,opt,name=weight)"
|
||||
Inner *InnerMessage "PB(bytes,4,opt,name=inner)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *OtherMessage) Reset() {
|
||||
*this = OtherMessage{}
|
||||
}
|
||||
func NewOtherMessage() *OtherMessage {
|
||||
return new(OtherMessage)
|
||||
}
|
||||
|
||||
type MyMessage struct {
|
||||
Count *int32 "PB(varint,1,req,name=count)"
|
||||
Name *string "PB(bytes,2,opt,name=name)"
|
||||
Quote *string "PB(bytes,3,opt,name=quote)"
|
||||
Pet []string "PB(bytes,4,rep,name=pet)"
|
||||
Inner *InnerMessage "PB(bytes,5,opt,name=inner)"
|
||||
Others []*OtherMessage "PB(bytes,6,rep,name=others)"
|
||||
Bikeshed *MyMessage_Color "PB(varint,7,opt,name=bikeshed,enum=test_proto.MyMessage_Color)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MyMessage) Reset() {
|
||||
*this = MyMessage{}
|
||||
}
|
||||
func NewMyMessage() *MyMessage {
|
||||
return new(MyMessage)
|
||||
}
|
||||
|
||||
type MessageList struct {
|
||||
Message []*MessageList_Message "PB(group,1,rep,name=message)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MessageList) Reset() {
|
||||
*this = MessageList{}
|
||||
}
|
||||
func NewMessageList() *MessageList {
|
||||
return new(MessageList)
|
||||
}
|
||||
|
||||
type MessageList_Message struct {
|
||||
Name *string "PB(bytes,2,req,name=name)"
|
||||
Count *int32 "PB(varint,3,req,name=count)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MessageList_Message) Reset() {
|
||||
*this = MessageList_Message{}
|
||||
}
|
||||
func NewMessageList_Message() *MessageList_Message {
|
||||
return new(MessageList_Message)
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("test_proto.FOO", FOO_name, FOO_value)
|
||||
proto.RegisterEnum("test_proto.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value)
|
||||
proto.RegisterEnum("test_proto.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value)
|
||||
}
|
|
@ -0,0 +1,334 @@
|
|||
// Code generated by protoc-gen-go from "test.proto"
|
||||
// DO NOT EDIT!
|
||||
|
||||
package test_proto
|
||||
|
||||
import "goprotobuf.googlecode.com/hg/proto"
|
||||
|
||||
type FOO int32
|
||||
const (
|
||||
FOO_FOO1 = 1
|
||||
)
|
||||
var FOO_name = map[int32] string {
|
||||
1: "FOO1",
|
||||
}
|
||||
var FOO_value = map[string] int32 {
|
||||
"FOO1": 1,
|
||||
}
|
||||
func NewFOO(x int32) *FOO {
|
||||
e := FOO(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type GoTest_KIND int32
|
||||
const (
|
||||
GoTest_VOID = 0
|
||||
GoTest_BOOL = 1
|
||||
GoTest_BYTES = 2
|
||||
GoTest_FINGERPRINT = 3
|
||||
GoTest_FLOAT = 4
|
||||
GoTest_INT = 5
|
||||
GoTest_STRING = 6
|
||||
GoTest_TIME = 7
|
||||
GoTest_TUPLE = 8
|
||||
GoTest_ARRAY = 9
|
||||
GoTest_MAP = 10
|
||||
GoTest_TABLE = 11
|
||||
GoTest_FUNCTION = 12
|
||||
)
|
||||
var GoTest_KIND_name = map[int32] string {
|
||||
0: "VOID",
|
||||
1: "BOOL",
|
||||
2: "BYTES",
|
||||
3: "FINGERPRINT",
|
||||
4: "FLOAT",
|
||||
5: "INT",
|
||||
6: "STRING",
|
||||
7: "TIME",
|
||||
8: "TUPLE",
|
||||
9: "ARRAY",
|
||||
10: "MAP",
|
||||
11: "TABLE",
|
||||
12: "FUNCTION",
|
||||
}
|
||||
var GoTest_KIND_value = map[string] int32 {
|
||||
"VOID": 0,
|
||||
"BOOL": 1,
|
||||
"BYTES": 2,
|
||||
"FINGERPRINT": 3,
|
||||
"FLOAT": 4,
|
||||
"INT": 5,
|
||||
"STRING": 6,
|
||||
"TIME": 7,
|
||||
"TUPLE": 8,
|
||||
"ARRAY": 9,
|
||||
"MAP": 10,
|
||||
"TABLE": 11,
|
||||
"FUNCTION": 12,
|
||||
}
|
||||
func NewGoTest_KIND(x int32) *GoTest_KIND {
|
||||
e := GoTest_KIND(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type MyMessage_Color int32
|
||||
const (
|
||||
MyMessage_RED = 0
|
||||
MyMessage_GREEN = 1
|
||||
MyMessage_BLUE = 2
|
||||
)
|
||||
var MyMessage_Color_name = map[int32] string {
|
||||
0: "RED",
|
||||
1: "GREEN",
|
||||
2: "BLUE",
|
||||
}
|
||||
var MyMessage_Color_value = map[string] int32 {
|
||||
"RED": 0,
|
||||
"GREEN": 1,
|
||||
"BLUE": 2,
|
||||
}
|
||||
func NewMyMessage_Color(x int32) *MyMessage_Color {
|
||||
e := MyMessage_Color(x)
|
||||
return &e
|
||||
}
|
||||
|
||||
type GoEnum struct {
|
||||
Foo *FOO "PB(varint,1,req,name=foo,enum=test_proto.FOO)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoEnum) Reset() {
|
||||
*this = GoEnum{}
|
||||
}
|
||||
func NewGoEnum() *GoEnum {
|
||||
return new(GoEnum)
|
||||
}
|
||||
|
||||
type GoTestField struct {
|
||||
Label *string "PB(bytes,1,req)"
|
||||
Type *string "PB(bytes,2,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTestField) Reset() {
|
||||
*this = GoTestField{}
|
||||
}
|
||||
func NewGoTestField() *GoTestField {
|
||||
return new(GoTestField)
|
||||
}
|
||||
|
||||
type GoTest struct {
|
||||
Kind *int32 "PB(varint,1,req)"
|
||||
Table *string "PB(bytes,2,opt)"
|
||||
Param *int32 "PB(varint,3,opt)"
|
||||
RequiredField *GoTestField "PB(bytes,4,req)"
|
||||
RepeatedField []*GoTestField "PB(bytes,5,rep)"
|
||||
OptionalField *GoTestField "PB(bytes,6,opt)"
|
||||
F_BoolRequired *bool "PB(varint,10,req,name=F_Bool_required)"
|
||||
F_Int32Required *int32 "PB(varint,11,req,name=F_Int32_required)"
|
||||
F_Int64Required *int64 "PB(varint,12,req,name=F_Int64_required)"
|
||||
F_Fixed32Required *uint32 "PB(fixed32,13,req,name=F_Fixed32_required)"
|
||||
F_Fixed64Required *uint64 "PB(fixed64,14,req,name=F_Fixed64_required)"
|
||||
F_Uint32Required *uint32 "PB(varint,15,req,name=F_Uint32_required)"
|
||||
F_Uint64Required *uint64 "PB(varint,16,req,name=F_Uint64_required)"
|
||||
F_FloatRequired *float32 "PB(fixed32,17,req,name=F_Float_required)"
|
||||
F_DoubleRequired *float64 "PB(fixed64,18,req,name=F_Double_required)"
|
||||
F_StringRequired *string "PB(bytes,19,req,name=F_String_required)"
|
||||
F_BytesRequired []byte "PB(bytes,101,req,name=F_Bytes_required)"
|
||||
F_Sint32Required *int32 "PB(zigzag32,102,req,name=F_Sint32_required)"
|
||||
F_Sint64Required *int64 "PB(zigzag64,103,req,name=F_Sint64_required)"
|
||||
F_BoolRepeated []bool "PB(varint,20,rep,name=F_Bool_repeated)"
|
||||
F_Int32Repeated []int32 "PB(varint,21,rep,name=F_Int32_repeated)"
|
||||
F_Int64Repeated []int64 "PB(varint,22,rep,name=F_Int64_repeated)"
|
||||
F_Fixed32Repeated []uint32 "PB(fixed32,23,rep,name=F_Fixed32_repeated)"
|
||||
F_Fixed64Repeated []uint64 "PB(fixed64,24,rep,name=F_Fixed64_repeated)"
|
||||
F_Uint32Repeated []uint32 "PB(varint,25,rep,name=F_Uint32_repeated)"
|
||||
F_Uint64Repeated []uint64 "PB(varint,26,rep,name=F_Uint64_repeated)"
|
||||
F_FloatRepeated []float32 "PB(fixed32,27,rep,name=F_Float_repeated)"
|
||||
F_DoubleRepeated []float64 "PB(fixed64,28,rep,name=F_Double_repeated)"
|
||||
F_StringRepeated []string "PB(bytes,29,rep,name=F_String_repeated)"
|
||||
F_BytesRepeated [][]byte "PB(bytes,201,rep,name=F_Bytes_repeated)"
|
||||
F_Sint32Repeated []int32 "PB(zigzag32,202,rep,name=F_Sint32_repeated)"
|
||||
F_Sint64Repeated []int64 "PB(zigzag64,203,rep,name=F_Sint64_repeated)"
|
||||
F_BoolOptional *bool "PB(varint,30,opt,name=F_Bool_optional)"
|
||||
F_Int32Optional *int32 "PB(varint,31,opt,name=F_Int32_optional)"
|
||||
F_Int64Optional *int64 "PB(varint,32,opt,name=F_Int64_optional)"
|
||||
F_Fixed32Optional *uint32 "PB(fixed32,33,opt,name=F_Fixed32_optional)"
|
||||
F_Fixed64Optional *uint64 "PB(fixed64,34,opt,name=F_Fixed64_optional)"
|
||||
F_Uint32Optional *uint32 "PB(varint,35,opt,name=F_Uint32_optional)"
|
||||
F_Uint64Optional *uint64 "PB(varint,36,opt,name=F_Uint64_optional)"
|
||||
F_FloatOptional *float32 "PB(fixed32,37,opt,name=F_Float_optional)"
|
||||
F_DoubleOptional *float64 "PB(fixed64,38,opt,name=F_Double_optional)"
|
||||
F_StringOptional *string "PB(bytes,39,opt,name=F_String_optional)"
|
||||
F_BytesOptional []byte "PB(bytes,301,opt,name=F_Bytes_optional)"
|
||||
F_Sint32Optional *int32 "PB(zigzag32,302,opt,name=F_Sint32_optional)"
|
||||
F_Sint64Optional *int64 "PB(zigzag64,303,opt,name=F_Sint64_optional)"
|
||||
F_BoolDefaulted *bool "PB(varint,40,opt,name=F_Bool_defaulted,def=1)"
|
||||
F_Int32Defaulted *int32 "PB(varint,41,opt,name=F_Int32_defaulted,def=32)"
|
||||
F_Int64Defaulted *int64 "PB(varint,42,opt,name=F_Int64_defaulted,def=64)"
|
||||
F_Fixed32Defaulted *uint32 "PB(fixed32,43,opt,name=F_Fixed32_defaulted,def=320)"
|
||||
F_Fixed64Defaulted *uint64 "PB(fixed64,44,opt,name=F_Fixed64_defaulted,def=640)"
|
||||
F_Uint32Defaulted *uint32 "PB(varint,45,opt,name=F_Uint32_defaulted,def=3200)"
|
||||
F_Uint64Defaulted *uint64 "PB(varint,46,opt,name=F_Uint64_defaulted,def=6400)"
|
||||
F_FloatDefaulted *float32 "PB(fixed32,47,opt,name=F_Float_defaulted,def=314159)"
|
||||
F_DoubleDefaulted *float64 "PB(fixed64,48,opt,name=F_Double_defaulted,def=271828)"
|
||||
F_StringDefaulted *string "PB(bytes,49,opt,name=F_String_defaulted,def=hello, \\\"world!\\\"\\n)"
|
||||
F_BytesDefaulted []byte "PB(bytes,401,opt,name=F_Bytes_defaulted,def=Bignose)"
|
||||
F_Sint32Defaulted *int32 "PB(zigzag32,402,opt,name=F_Sint32_defaulted,def=-32)"
|
||||
F_Sint64Defaulted *int64 "PB(zigzag64,403,opt,name=F_Sint64_defaulted,def=-64)"
|
||||
Requiredgroup *GoTest_RequiredGroup "PB(group,70,req,name=requiredgroup)"
|
||||
Repeatedgroup []*GoTest_RepeatedGroup "PB(group,80,rep,name=repeatedgroup)"
|
||||
Optionalgroup *GoTest_OptionalGroup "PB(group,90,opt,name=optionalgroup)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest) Reset() {
|
||||
*this = GoTest{}
|
||||
}
|
||||
func NewGoTest() *GoTest {
|
||||
return new(GoTest)
|
||||
}
|
||||
const Default_GoTest_F_BoolDefaulted bool = true
|
||||
const Default_GoTest_F_Int32Defaulted int32 = 32
|
||||
const Default_GoTest_F_Int64Defaulted int64 = 64
|
||||
const Default_GoTest_F_Fixed32Defaulted uint32 = 320
|
||||
const Default_GoTest_F_Fixed64Defaulted uint64 = 640
|
||||
const Default_GoTest_F_Uint32Defaulted uint32 = 3200
|
||||
const Default_GoTest_F_Uint64Defaulted uint64 = 6400
|
||||
const Default_GoTest_F_FloatDefaulted float32 = 314159
|
||||
const Default_GoTest_F_DoubleDefaulted float64 = 271828
|
||||
const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n"
|
||||
var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose")
|
||||
const Default_GoTest_F_Sint32Defaulted int32 = -32
|
||||
const Default_GoTest_F_Sint64Defaulted int64 = -64
|
||||
|
||||
type GoTest_RequiredGroup struct {
|
||||
RequiredField *string "PB(bytes,71,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest_RequiredGroup) Reset() {
|
||||
*this = GoTest_RequiredGroup{}
|
||||
}
|
||||
func NewGoTest_RequiredGroup() *GoTest_RequiredGroup {
|
||||
return new(GoTest_RequiredGroup)
|
||||
}
|
||||
|
||||
type GoTest_RepeatedGroup struct {
|
||||
RequiredField *string "PB(bytes,81,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest_RepeatedGroup) Reset() {
|
||||
*this = GoTest_RepeatedGroup{}
|
||||
}
|
||||
func NewGoTest_RepeatedGroup() *GoTest_RepeatedGroup {
|
||||
return new(GoTest_RepeatedGroup)
|
||||
}
|
||||
|
||||
type GoTest_OptionalGroup struct {
|
||||
RequiredField *string "PB(bytes,91,req)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoTest_OptionalGroup) Reset() {
|
||||
*this = GoTest_OptionalGroup{}
|
||||
}
|
||||
func NewGoTest_OptionalGroup() *GoTest_OptionalGroup {
|
||||
return new(GoTest_OptionalGroup)
|
||||
}
|
||||
|
||||
type GoSkipTest struct {
|
||||
SkipInt32 *int32 "PB(varint,11,req,name=skip_int32)"
|
||||
SkipFixed32 *uint32 "PB(fixed32,12,req,name=skip_fixed32)"
|
||||
SkipFixed64 *uint64 "PB(fixed64,13,req,name=skip_fixed64)"
|
||||
SkipString *string "PB(bytes,14,req,name=skip_string)"
|
||||
Skipgroup *GoSkipTest_SkipGroup "PB(group,15,req,name=skipgroup)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoSkipTest) Reset() {
|
||||
*this = GoSkipTest{}
|
||||
}
|
||||
func NewGoSkipTest() *GoSkipTest {
|
||||
return new(GoSkipTest)
|
||||
}
|
||||
|
||||
type GoSkipTest_SkipGroup struct {
|
||||
GroupInt32 *int32 "PB(varint,16,req,name=group_int32)"
|
||||
GroupString *string "PB(bytes,17,req,name=group_string)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *GoSkipTest_SkipGroup) Reset() {
|
||||
*this = GoSkipTest_SkipGroup{}
|
||||
}
|
||||
func NewGoSkipTest_SkipGroup() *GoSkipTest_SkipGroup {
|
||||
return new(GoSkipTest_SkipGroup)
|
||||
}
|
||||
|
||||
type InnerMessage struct {
|
||||
Host *string "PB(bytes,1,req,name=host)"
|
||||
Port *int32 "PB(varint,2,opt,name=port,def=4000)"
|
||||
Connected *bool "PB(varint,3,opt,name=connected)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *InnerMessage) Reset() {
|
||||
*this = InnerMessage{}
|
||||
}
|
||||
func NewInnerMessage() *InnerMessage {
|
||||
return new(InnerMessage)
|
||||
}
|
||||
const Default_InnerMessage_Port int32 = 4000
|
||||
|
||||
type OtherMessage struct {
|
||||
Key *int64 "PB(varint,1,opt,name=key)"
|
||||
Value []byte "PB(bytes,2,opt,name=value)"
|
||||
Weight *float32 "PB(fixed32,3,opt,name=weight)"
|
||||
Inner *InnerMessage "PB(bytes,4,opt,name=inner)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *OtherMessage) Reset() {
|
||||
*this = OtherMessage{}
|
||||
}
|
||||
func NewOtherMessage() *OtherMessage {
|
||||
return new(OtherMessage)
|
||||
}
|
||||
|
||||
type MyMessage struct {
|
||||
Count *int32 "PB(varint,1,req,name=count)"
|
||||
Name *string "PB(bytes,2,opt,name=name)"
|
||||
Quote *string "PB(bytes,3,opt,name=quote)"
|
||||
Pet []string "PB(bytes,4,rep,name=pet)"
|
||||
Inner *InnerMessage "PB(bytes,5,opt,name=inner)"
|
||||
Others []*OtherMessage "PB(bytes,6,rep,name=others)"
|
||||
Bikeshed *MyMessage_Color "PB(varint,7,opt,name=bikeshed,enum=test_proto.MyMessage_Color)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MyMessage) Reset() {
|
||||
*this = MyMessage{}
|
||||
}
|
||||
func NewMyMessage() *MyMessage {
|
||||
return new(MyMessage)
|
||||
}
|
||||
|
||||
type MessageList struct {
|
||||
Message []*MessageList_Message "PB(group,1,rep,name=message)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MessageList) Reset() {
|
||||
*this = MessageList{}
|
||||
}
|
||||
func NewMessageList() *MessageList {
|
||||
return new(MessageList)
|
||||
}
|
||||
|
||||
type MessageList_Message struct {
|
||||
Name *string "PB(bytes,2,req,name=name)"
|
||||
Count *int32 "PB(varint,3,req,name=count)"
|
||||
XXX_unrecognized []byte
|
||||
}
|
||||
func (this *MessageList_Message) Reset() {
|
||||
*this = MessageList_Message{}
|
||||
}
|
||||
func NewMessageList_Message() *MessageList_Message {
|
||||
return new(MessageList_Message)
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("test_proto.FOO", FOO_name, FOO_value)
|
||||
proto.RegisterEnum("test_proto.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value)
|
||||
proto.RegisterEnum("test_proto.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value)
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/goprotobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A feature-rich test file for the protocol compiler and libraries.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package test_proto;
|
||||
|
||||
enum FOO { FOO1 = 1; };
|
||||
|
||||
message GoEnum {
|
||||
required FOO foo = 1;
|
||||
}
|
||||
|
||||
message GoTestField {
|
||||
required string Label = 1;
|
||||
required string Type = 2;
|
||||
}
|
||||
|
||||
message GoTest {
|
||||
// An enum, for completeness.
|
||||
enum KIND {
|
||||
VOID = 0;
|
||||
|
||||
// Basic types
|
||||
BOOL = 1;
|
||||
BYTES = 2;
|
||||
FINGERPRINT = 3;
|
||||
FLOAT = 4;
|
||||
INT = 5;
|
||||
STRING = 6;
|
||||
TIME = 7;
|
||||
|
||||
// Groupings
|
||||
TUPLE = 8;
|
||||
ARRAY = 9;
|
||||
MAP = 10;
|
||||
|
||||
// Table types
|
||||
TABLE = 11;
|
||||
|
||||
// Functions
|
||||
FUNCTION = 12; // last tag
|
||||
};
|
||||
|
||||
// Some typical parameters
|
||||
required int32 Kind = 1;
|
||||
optional string Table = 2;
|
||||
optional int32 Param = 3;
|
||||
|
||||
// Required, repeated and optional foreign fields.
|
||||
required GoTestField RequiredField = 4;
|
||||
repeated GoTestField RepeatedField = 5;
|
||||
optional GoTestField OptionalField = 6;
|
||||
|
||||
// Required fields of all basic types
|
||||
required bool F_Bool_required = 10;
|
||||
required int32 F_Int32_required = 11;
|
||||
required int64 F_Int64_required = 12;
|
||||
required fixed32 F_Fixed32_required = 13;
|
||||
required fixed64 F_Fixed64_required = 14;
|
||||
required uint32 F_Uint32_required = 15;
|
||||
required uint64 F_Uint64_required = 16;
|
||||
required float F_Float_required = 17;
|
||||
required double F_Double_required = 18;
|
||||
required string F_String_required = 19;
|
||||
required bytes F_Bytes_required = 101;
|
||||
required sint32 F_Sint32_required = 102;
|
||||
required sint64 F_Sint64_required = 103;
|
||||
|
||||
// Repeated fields of all basic types
|
||||
repeated bool F_Bool_repeated = 20;
|
||||
repeated int32 F_Int32_repeated = 21;
|
||||
repeated int64 F_Int64_repeated = 22;
|
||||
repeated fixed32 F_Fixed32_repeated = 23;
|
||||
repeated fixed64 F_Fixed64_repeated = 24;
|
||||
repeated uint32 F_Uint32_repeated = 25;
|
||||
repeated uint64 F_Uint64_repeated = 26;
|
||||
repeated float F_Float_repeated = 27;
|
||||
repeated double F_Double_repeated = 28;
|
||||
repeated string F_String_repeated = 29;
|
||||
repeated bytes F_Bytes_repeated = 201;
|
||||
repeated sint32 F_Sint32_repeated = 202;
|
||||
repeated sint64 F_Sint64_repeated = 203;
|
||||
|
||||
// Optional fields of all basic types
|
||||
optional bool F_Bool_optional = 30;
|
||||
optional int32 F_Int32_optional = 31;
|
||||
optional int64 F_Int64_optional = 32;
|
||||
optional fixed32 F_Fixed32_optional = 33;
|
||||
optional fixed64 F_Fixed64_optional = 34;
|
||||
optional uint32 F_Uint32_optional = 35;
|
||||
optional uint64 F_Uint64_optional = 36;
|
||||
optional float F_Float_optional = 37;
|
||||
optional double F_Double_optional = 38;
|
||||
optional string F_String_optional = 39;
|
||||
optional bytes F_Bytes_optional = 301;
|
||||
optional sint32 F_Sint32_optional = 302;
|
||||
optional sint64 F_Sint64_optional = 303;
|
||||
|
||||
// Default-valued fields of all basic types
|
||||
optional bool F_Bool_defaulted = 40 [default=true];
|
||||
optional int32 F_Int32_defaulted = 41 [default=32];
|
||||
optional int64 F_Int64_defaulted = 42 [default=64];
|
||||
optional fixed32 F_Fixed32_defaulted = 43 [default=320];
|
||||
optional fixed64 F_Fixed64_defaulted = 44 [default=640];
|
||||
optional uint32 F_Uint32_defaulted = 45 [default=3200];
|
||||
optional uint64 F_Uint64_defaulted = 46 [default=6400];
|
||||
optional float F_Float_defaulted = 47 [default=314159.];
|
||||
optional double F_Double_defaulted = 48 [default=271828.];
|
||||
optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"];
|
||||
optional bytes F_Bytes_defaulted = 401 [default="Bignose"];
|
||||
optional sint32 F_Sint32_defaulted = 402 [default = -32];
|
||||
optional sint64 F_Sint64_defaulted = 403 [default = -64];
|
||||
|
||||
// Required, repeated, and optional groups.
|
||||
required group RequiredGroup = 70 {
|
||||
required string RequiredField = 71;
|
||||
};
|
||||
|
||||
repeated group RepeatedGroup = 80 {
|
||||
required string RequiredField = 81;
|
||||
};
|
||||
|
||||
optional group OptionalGroup = 90 {
|
||||
required string RequiredField = 91;
|
||||
};
|
||||
};
|
||||
|
||||
// For testing skipping of unrecognized fields.
|
||||
// Numbers are all big, larger than tag numbers in GoTestField,
|
||||
// the message used in the corresponding test.
|
||||
message GoSkipTest {
|
||||
required int32 skip_int32 = 11;
|
||||
required fixed32 skip_fixed32 = 12;
|
||||
required fixed64 skip_fixed64 = 13;
|
||||
required string skip_string = 14;
|
||||
required group SkipGroup = 15 {
|
||||
required int32 group_int32 = 16;
|
||||
required string group_string = 17;
|
||||
}
|
||||
}
|
||||
|
||||
// Smaller tests for ASCII formatting.
|
||||
|
||||
message InnerMessage {
|
||||
required string host = 1;
|
||||
optional int32 port = 2 [default=4000];
|
||||
optional bool connected = 3;
|
||||
}
|
||||
|
||||
message OtherMessage {
|
||||
optional int64 key = 1;
|
||||
optional bytes value = 2;
|
||||
optional float weight = 3;
|
||||
optional InnerMessage inner = 4;
|
||||
}
|
||||
|
||||
message MyMessage {
|
||||
required int32 count = 1;
|
||||
optional string name = 2;
|
||||
optional string quote = 3;
|
||||
repeated string pet = 4;
|
||||
optional InnerMessage inner = 5;
|
||||
repeated OtherMessage others = 6;
|
||||
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
};
|
||||
optional Color bikeshed = 7;
|
||||
}
|
||||
|
||||
message MessageList {
|
||||
repeated group Message = 1 {
|
||||
required string name = 2;
|
||||
required int32 count = 3;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,221 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/goprotobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
// Functions for writing the Text protocol buffer format.
|
||||
// TODO:
|
||||
// - groups.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// An io.Writer wrapper that tracks its indentation level.
|
||||
type textWriter struct {
|
||||
indent_level int
|
||||
complete bool // if the current position is a complete line
|
||||
compact bool // whether to write out as a one-liner
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
func (w *textWriter) Write(p []byte) (n int, err os.Error) {
|
||||
n, err = len(p), nil
|
||||
|
||||
frags := strings.Split(string(p), "\n", 0)
|
||||
if w.compact {
|
||||
w.writer.Write([]byte(strings.Join(frags, " ")))
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(frags); i++ {
|
||||
if w.complete {
|
||||
for j := 0; j < w.indent_level; j++ {
|
||||
w.writer.Write([]byte{' ', ' '})
|
||||
}
|
||||
w.complete = false
|
||||
}
|
||||
|
||||
w.writer.Write([]byte(frags[i]))
|
||||
if i+1 < len(frags) {
|
||||
w.writer.Write([]byte{'\n'})
|
||||
}
|
||||
}
|
||||
w.complete = len(frags[len(frags)-1]) == 0
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (w *textWriter) indent() { w.indent_level++ }
|
||||
|
||||
func (w *textWriter) unindent() {
|
||||
if w.indent_level == 0 {
|
||||
fmt.Fprintln(os.Stderr, "proto: textWriter unindented too far!")
|
||||
} else {
|
||||
w.indent_level--
|
||||
}
|
||||
}
|
||||
|
||||
func writeStruct(w *textWriter, sv *reflect.StructValue) {
|
||||
st := sv.Type().(*reflect.StructType)
|
||||
sprops := GetProperties(st)
|
||||
for i := 0; i < sv.NumField(); i++ {
|
||||
if strings.HasPrefix(st.Field(i).Name, "XXX_") {
|
||||
continue
|
||||
}
|
||||
props := sprops.Prop[i]
|
||||
fv := sv.Field(i)
|
||||
if pv, ok := fv.(*reflect.PtrValue); ok && pv.IsNil() {
|
||||
// Field not filled in. This could be an optional field or
|
||||
// a required field that wasn't filled in. Either way, there
|
||||
// isn't anything we can show for it.
|
||||
continue
|
||||
}
|
||||
if av, ok := fv.(*reflect.SliceValue); ok && av.IsNil() {
|
||||
// Repeated field that is empty, or a bytes field that is unused.
|
||||
continue
|
||||
}
|
||||
|
||||
if props.Repeated {
|
||||
if av, ok := fv.(*reflect.SliceValue); ok {
|
||||
// Repeated field.
|
||||
for j := 0; j < av.Len(); j++ {
|
||||
fmt.Fprintf(w, "%v:", props.OrigName)
|
||||
if !w.compact {
|
||||
w.Write([]byte{' '})
|
||||
}
|
||||
writeAny(w, av.Elem(j))
|
||||
fmt.Fprint(w, "\n")
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%v:", props.OrigName)
|
||||
if !w.compact {
|
||||
w.Write([]byte{' '})
|
||||
}
|
||||
if len(props.Enum) == 0 || !tryWriteEnum(w, props.Enum, fv) {
|
||||
writeAny(w, fv)
|
||||
}
|
||||
fmt.Fprint(w, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func tryWriteEnum(w *textWriter, enum string, v reflect.Value) bool {
|
||||
val, ok := reflect.Indirect(v).(*reflect.Int32Value)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
m, ok := enumNameMaps[enum]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
str, ok := m[val.Get()]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
fmt.Fprintf(w, str)
|
||||
return true
|
||||
}
|
||||
|
||||
func writeAny(w *textWriter, v reflect.Value) {
|
||||
v = reflect.Indirect(v)
|
||||
|
||||
// We don't attempt to serialise every possible value type; only those
|
||||
// that can occur in protocol buffers, plus a few extra that were easy.
|
||||
switch val := v.(type) {
|
||||
case *reflect.SliceValue:
|
||||
// Should only be a []byte; repeated fields are handled in writeStruct.
|
||||
// TODO: Handle other cases cleaner.
|
||||
bytes := make([]byte, val.Len())
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
bytes[i] = val.Elem(i).(*reflect.Uint8Value).Get()
|
||||
}
|
||||
// TODO: Should be strconv.QuoteC, which doesn't exist yet
|
||||
fmt.Fprint(w, strconv.Quote(string(bytes)))
|
||||
case *reflect.StringValue:
|
||||
// TODO: Should be strconv.QuoteC, which doesn't exist yet
|
||||
fmt.Fprint(w, strconv.Quote(val.Get()))
|
||||
case *reflect.StructValue:
|
||||
// Required/optional group/message.
|
||||
// TODO: groups use { } instead of < >, and no colon.
|
||||
if !w.compact {
|
||||
fmt.Fprint(w, "<\n")
|
||||
} else {
|
||||
fmt.Fprint(w, "<")
|
||||
}
|
||||
w.indent()
|
||||
writeStruct(w, val)
|
||||
w.unindent()
|
||||
fmt.Fprint(w, ">")
|
||||
default:
|
||||
fmt.Fprint(w, val.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
func marshalText(w io.Writer, pb interface{}, compact bool) {
|
||||
aw := new(textWriter)
|
||||
aw.writer = w
|
||||
aw.complete = true
|
||||
aw.compact = compact
|
||||
|
||||
v := reflect.NewValue(pb)
|
||||
// We should normally be passed a struct, or a pointer to a struct,
|
||||
// and we don't want the outer < and > in that case.
|
||||
v = reflect.Indirect(v)
|
||||
if sv, ok := v.(*reflect.StructValue); ok {
|
||||
writeStruct(aw, sv)
|
||||
} else {
|
||||
writeAny(aw, v)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalText writes a given protobuffer in Text format.
|
||||
// Non-protobuffers can also be written, but their formatting is not guaranteed.
|
||||
func MarshalText(w io.Writer, pb interface{}) { marshalText(w, pb, false) }
|
||||
|
||||
// CompactText writes a given protobuffer in compact Text format (one line).
|
||||
// Non-protobuffers can also be written, but their formatting is not guaranteed.
|
||||
func CompactText(w io.Writer, pb interface{}) { marshalText(w, pb, true) }
|
||||
|
||||
// CompactTextString is the same as CompactText, but returns the string directly.
|
||||
func CompactTextString(pb interface{}) string {
|
||||
buf := new(bytes.Buffer)
|
||||
marshalText(buf, pb, true)
|
||||
return buf.String()
|
||||
}
|
|
@ -0,0 +1,473 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/goprotobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
// Functions for parsing the Text protocol buffer format.
|
||||
// TODO:
|
||||
// - groups.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ParseError satisfies the os.Error interface.
|
||||
type ParseError struct {
|
||||
Message string
|
||||
Line int // 1-based line number
|
||||
Offset int // 0-based byte offset from start of input
|
||||
}
|
||||
|
||||
func (p *ParseError) String() string {
|
||||
if p.Line == 1 {
|
||||
// show offset only for first line
|
||||
return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
|
||||
}
|
||||
return fmt.Sprintf("line %d: %v", p.Line, p.Message)
|
||||
}
|
||||
|
||||
type token struct {
|
||||
value string
|
||||
err *ParseError
|
||||
line int // line number
|
||||
offset int // byte number from start of input, not start of line
|
||||
unquoted string // the unquoted version of value, if it was a quoted string
|
||||
}
|
||||
|
||||
func (t *token) String() string {
|
||||
if t.err == nil {
|
||||
return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
|
||||
}
|
||||
return fmt.Sprintf("parse error: %v", t.err)
|
||||
}
|
||||
|
||||
type textParser struct {
|
||||
s string // remaining input
|
||||
done bool // whether the parsing is finished (success or error)
|
||||
backed bool // whether back() was called
|
||||
offset, line int
|
||||
cur token
|
||||
}
|
||||
|
||||
func newTextParser(s string) *textParser {
|
||||
p := new(textParser)
|
||||
p.s = s
|
||||
p.line = 1
|
||||
p.cur.line = 1
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *textParser) error(format string, a ...interface{}) *ParseError {
|
||||
pe := &ParseError{fmt.Sprintf(format, a), p.cur.line, p.cur.offset}
|
||||
p.cur.err = pe
|
||||
p.done = true
|
||||
return pe
|
||||
}
|
||||
|
||||
// Numbers and identifiers are matched by [-+._A-Za-z0-9]
|
||||
func isIdentOrNumberChar(c byte) bool {
|
||||
switch {
|
||||
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
|
||||
return true
|
||||
case '0' <= c && c <= '9':
|
||||
return true
|
||||
}
|
||||
switch c {
|
||||
case '-', '+', '.', '_':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isWhitespace(c byte) bool {
|
||||
switch c {
|
||||
case ' ', '\t', '\n', '\r':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *textParser) skipWhitespace() {
|
||||
i := 0
|
||||
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
|
||||
if p.s[i] == '#' {
|
||||
// comment; skip to end of line or input
|
||||
for i < len(p.s) && p.s[i] != '\n' {
|
||||
i++
|
||||
}
|
||||
if i == len(p.s) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if p.s[i] == '\n' {
|
||||
p.line++
|
||||
}
|
||||
i++
|
||||
}
|
||||
p.offset += i
|
||||
p.s = p.s[i:len(p.s)]
|
||||
if len(p.s) == 0 {
|
||||
p.done = true
|
||||
}
|
||||
}
|
||||
|
||||
func (p *textParser) advance() {
|
||||
// Skip whitespace
|
||||
p.skipWhitespace()
|
||||
if p.done {
|
||||
return
|
||||
}
|
||||
|
||||
// Start of non-whitespace
|
||||
p.cur.err = nil
|
||||
p.cur.offset, p.cur.line = p.offset, p.line
|
||||
p.cur.unquoted = ""
|
||||
switch p.s[0] {
|
||||
case '<', '>', '{', '}', ':':
|
||||
// Single symbol
|
||||
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
|
||||
case '"':
|
||||
// Quoted string
|
||||
i := 1
|
||||
for i < len(p.s) && p.s[i] != '"' && p.s[i] != '\n' {
|
||||
if p.s[i] == '\\' && i+1 < len(p.s) {
|
||||
// skip escaped char
|
||||
i++
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i >= len(p.s) || p.s[i] != '"' {
|
||||
p.error("unmatched quote")
|
||||
return
|
||||
}
|
||||
// TODO: Should be UnquoteC.
|
||||
unq, err := strconv.Unquote(p.s[0 : i+1])
|
||||
if err != nil {
|
||||
p.error("invalid quoted string %v", p.s[0:i+1])
|
||||
return
|
||||
}
|
||||
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
|
||||
p.cur.unquoted = unq
|
||||
default:
|
||||
i := 0
|
||||
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
|
||||
i++
|
||||
}
|
||||
if i == 0 {
|
||||
p.error("unexpected byte %#x", p.s[0])
|
||||
return
|
||||
}
|
||||
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
|
||||
}
|
||||
p.offset += len(p.cur.value)
|
||||
}
|
||||
|
||||
// Back off the parser by one token. Can only be done between calls to next().
|
||||
// It makes the next advance() a no-op.
|
||||
func (p *textParser) back() { p.backed = true }
|
||||
|
||||
// Advances the parser and returns the new current token.
|
||||
func (p *textParser) next() *token {
|
||||
if p.backed || p.done {
|
||||
p.backed = false
|
||||
return &p.cur
|
||||
}
|
||||
p.advance()
|
||||
if p.done {
|
||||
p.cur.value = ""
|
||||
} else if len(p.cur.value) > 0 && p.cur.value[0] == '"' {
|
||||
// Look for multiple quoted strings separated by whitespace,
|
||||
// and concatenate them.
|
||||
cat := p.cur
|
||||
for {
|
||||
p.skipWhitespace()
|
||||
if p.done || p.s[0] != '"' {
|
||||
break
|
||||
}
|
||||
p.advance()
|
||||
if p.cur.err != nil {
|
||||
return &p.cur
|
||||
}
|
||||
cat.value += " " + p.cur.value
|
||||
cat.unquoted += p.cur.unquoted
|
||||
}
|
||||
p.done = false // parser may have seen EOF, but we want to return cat
|
||||
p.cur = cat
|
||||
}
|
||||
return &p.cur
|
||||
}
|
||||
|
||||
type nillable interface {
|
||||
IsNil() bool
|
||||
}
|
||||
|
||||
// Return an error indicating which required field was not set.
|
||||
func (p *textParser) missingRequiredFieldError(sv *reflect.StructValue) *ParseError {
|
||||
st := sv.Type().(*reflect.StructType)
|
||||
sprops := GetProperties(st)
|
||||
for i := 0; i < st.NumField(); i++ {
|
||||
// All protocol buffer fields are nillable, but let's be careful.
|
||||
nfv, ok := sv.Field(i).(nillable)
|
||||
if !ok || !nfv.IsNil() {
|
||||
continue
|
||||
}
|
||||
|
||||
props := sprops.Prop[i]
|
||||
if props.Required {
|
||||
return p.error("message %v missing required field %q", st, props.OrigName)
|
||||
}
|
||||
}
|
||||
return p.error("message %v missing required field", st) // should not happen
|
||||
}
|
||||
|
||||
// Returns the index in the struct for the named field, as well as the parsed tag properties.
|
||||
func structFieldByName(st *reflect.StructType, name string) (int, *Properties, bool) {
|
||||
sprops := GetProperties(st)
|
||||
for i := 0; i < st.NumField(); i++ {
|
||||
props := sprops.Prop[i]
|
||||
if props.OrigName == name {
|
||||
return i, props, true
|
||||
}
|
||||
}
|
||||
return -1, nil, false
|
||||
}
|
||||
|
||||
func (p *textParser) readStruct(sv *reflect.StructValue, terminator string) *ParseError {
|
||||
st := sv.Type().(*reflect.StructType)
|
||||
reqCount := GetProperties(st).reqCount
|
||||
// A struct is a sequence of "name: value", terminated by one of
|
||||
// '>' or '}', or the end of the input.
|
||||
for {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value == terminator {
|
||||
break
|
||||
}
|
||||
|
||||
fi, props, ok := structFieldByName(st, tok.value)
|
||||
if !ok {
|
||||
return p.error("unknown field name %q in %v", tok.value, st)
|
||||
}
|
||||
|
||||
// Check that it's not already set if it's not a repeated field.
|
||||
if !props.Repeated {
|
||||
if nfv, ok := sv.Field(fi).(nillable); ok && !nfv.IsNil() {
|
||||
return p.error("non-repeated field %q was repeated", tok.value)
|
||||
}
|
||||
}
|
||||
|
||||
tok = p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value != ":" {
|
||||
// Colon is optional when the field is a group or message.
|
||||
needColon := true
|
||||
switch props.Wire {
|
||||
case "group":
|
||||
needColon = false
|
||||
case "bytes":
|
||||
// A "bytes" field is either a message, a string, or a repeated field;
|
||||
// those three become *T, *string and []T respectively, so we can check for
|
||||
// this field being a pointer to a non-string.
|
||||
typ := st.Field(fi).Type
|
||||
pt, ok := typ.(*reflect.PtrType)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
_, ok = pt.Elem().(*reflect.StringType)
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
needColon = false
|
||||
}
|
||||
if needColon {
|
||||
return p.error("expected ':', found %q", tok.value)
|
||||
}
|
||||
p.back()
|
||||
}
|
||||
|
||||
// Parse into the field.
|
||||
if err := p.readAny(sv.Field(fi), props); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if props.Required {
|
||||
reqCount--
|
||||
}
|
||||
}
|
||||
|
||||
if reqCount > 0 {
|
||||
return p.missingRequiredFieldError(sv)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
minInt32 = -1 << 31
|
||||
maxInt32 = 1<<31 - 1
|
||||
maxUint32 = 1<<32 - 1
|
||||
)
|
||||
|
||||
func (p *textParser) readAny(v reflect.Value, props *Properties) *ParseError {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value == "" {
|
||||
return p.error("unexpected EOF")
|
||||
}
|
||||
|
||||
switch fv := v.(type) {
|
||||
case *reflect.SliceValue:
|
||||
at := v.Type().(*reflect.SliceType)
|
||||
if _, ok := at.Elem().(*reflect.Uint8Type); ok {
|
||||
// Special case for []byte
|
||||
if tok.value[0] != '"' {
|
||||
// Deliberately written out here, as the error after
|
||||
// this switch statement would write "invalid []byte: ...",
|
||||
// which is not as user-friendly.
|
||||
return p.error("invalid string: %v", tok.value)
|
||||
}
|
||||
bytes := []byte(tok.unquoted)
|
||||
fv.Set(reflect.NewValue(bytes).(*reflect.SliceValue))
|
||||
return nil
|
||||
}
|
||||
// Repeated field. May already exist.
|
||||
cnt := fv.Len()
|
||||
nav := reflect.MakeSlice(at, cnt, cnt+1)
|
||||
reflect.ArrayCopy(nav, fv)
|
||||
fv.Set(nav)
|
||||
fv.SetLen(cnt + 1)
|
||||
|
||||
// Read one.
|
||||
p.back()
|
||||
return p.readAny(fv.Elem(cnt), nil) // TODO: pass properties?
|
||||
case *reflect.BoolValue:
|
||||
// Either "true", "false", 1 or 0.
|
||||
switch tok.value {
|
||||
case "true", "1":
|
||||
fv.Set(true)
|
||||
return nil
|
||||
case "false", "0":
|
||||
fv.Set(false)
|
||||
return nil
|
||||
}
|
||||
case *reflect.Float32Value:
|
||||
if f, err := strconv.Atof32(tok.value); err == nil {
|
||||
fv.Set(f)
|
||||
return nil
|
||||
}
|
||||
case *reflect.Float64Value:
|
||||
if f, err := strconv.Atof64(tok.value); err == nil {
|
||||
fv.Set(f)
|
||||
return nil
|
||||
}
|
||||
case *reflect.Int32Value:
|
||||
if x, err := strconv.Atoi64(tok.value); err == nil && minInt32 <= x && x <= maxInt32 {
|
||||
fv.Set(int32(x))
|
||||
return nil
|
||||
}
|
||||
if len(props.Enum) == 0 {
|
||||
break
|
||||
}
|
||||
m, ok := enumValueMaps[props.Enum]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
x, ok := m[tok.value]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
fv.Set(x)
|
||||
return nil
|
||||
case *reflect.Int64Value:
|
||||
if x, err := strconv.Atoi64(tok.value); err == nil {
|
||||
fv.Set(x)
|
||||
return nil
|
||||
}
|
||||
case *reflect.PtrValue:
|
||||
// A basic field (indirected through pointer), or a repeated message/group
|
||||
p.back()
|
||||
fv.PointTo(reflect.MakeZero(fv.Type().(*reflect.PtrType).Elem()))
|
||||
return p.readAny(fv.Elem(), props)
|
||||
case *reflect.StringValue:
|
||||
if tok.value[0] == '"' {
|
||||
fv.Set(tok.unquoted)
|
||||
return nil
|
||||
}
|
||||
case *reflect.StructValue:
|
||||
var terminator string
|
||||
switch tok.value {
|
||||
case "{":
|
||||
terminator = "}"
|
||||
case "<":
|
||||
terminator = ">"
|
||||
default:
|
||||
return p.error("expected '{' or '<', found %q", tok.value)
|
||||
}
|
||||
return p.readStruct(fv, terminator)
|
||||
case *reflect.Uint32Value:
|
||||
if x, err := strconv.Atoui64(tok.value); err == nil && x <= maxUint32 {
|
||||
fv.Set(uint32(x))
|
||||
return nil
|
||||
}
|
||||
case *reflect.Uint64Value:
|
||||
if x, err := strconv.Atoui64(tok.value); err == nil {
|
||||
fv.Set(x)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return p.error("invalid %v: %v", v.Type(), tok.value)
|
||||
}
|
||||
|
||||
var notPtrStruct os.Error = &ParseError{"destination is not a pointer to a struct", 0, 0}
|
||||
|
||||
// UnmarshalText reads a protobuffer in Text format.
|
||||
func UnmarshalText(s string, pb interface{}) os.Error {
|
||||
pv, ok := reflect.NewValue(pb).(*reflect.PtrValue)
|
||||
if !ok {
|
||||
return notPtrStruct
|
||||
}
|
||||
sv, ok := pv.Elem().(*reflect.StructValue)
|
||||
if !ok {
|
||||
return notPtrStruct
|
||||
}
|
||||
if pe := newTextParser(s).readStruct(sv, ""); pe != nil {
|
||||
return pe
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/goprotobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
. "goprotobuf.googlecode.com/hg/proto"
|
||||
. "./testdata/_obj/test_proto"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type UnmarshalTextTest struct {
|
||||
in string
|
||||
error string // if "", no error expected
|
||||
out *MyMessage
|
||||
}
|
||||
|
||||
var unMarshalTextTests = []UnmarshalTextTest{
|
||||
// Basic
|
||||
UnmarshalTextTest{
|
||||
in: " count:42\n name:\"Dave\" ",
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("Dave"),
|
||||
},
|
||||
},
|
||||
|
||||
// Empty quoted string
|
||||
UnmarshalTextTest{
|
||||
in: `count:42 name:""`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String(""),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string concatenation
|
||||
UnmarshalTextTest{
|
||||
in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("My name is elsewhere"),
|
||||
},
|
||||
},
|
||||
|
||||
// Bad quoted string
|
||||
UnmarshalTextTest{
|
||||
in: `inner: < host: "\0" >` + "\n",
|
||||
error: `line 1.15: invalid quoted string "\0"`,
|
||||
},
|
||||
|
||||
// Number too large for int64
|
||||
UnmarshalTextTest{
|
||||
in: "count: 123456789012345678901",
|
||||
error: "line 1.7: invalid int32: 123456789012345678901",
|
||||
},
|
||||
|
||||
// Number too large for int32
|
||||
UnmarshalTextTest{
|
||||
in: "count: 1234567890123",
|
||||
error: "line 1.7: invalid int32: 1234567890123",
|
||||
},
|
||||
|
||||
// Number too large for float32
|
||||
UnmarshalTextTest{
|
||||
in: "others:< weight: 12345678901234567890123456789012345678901234567890 >",
|
||||
error: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
|
||||
},
|
||||
|
||||
// Number posing as a quoted string
|
||||
UnmarshalTextTest{
|
||||
in: `inner: < host: 12 >` + "\n",
|
||||
error: `line 1.15: invalid string: 12`,
|
||||
},
|
||||
|
||||
// Quoted string posing as int32
|
||||
UnmarshalTextTest{
|
||||
in: `count: "12"`,
|
||||
error: `line 1.7: invalid int32: "12"`,
|
||||
},
|
||||
|
||||
// Quoted string posing a float32
|
||||
UnmarshalTextTest{
|
||||
in: `others:< weight: "17.4" >`,
|
||||
error: `line 1.17: invalid float32: "17.4"`,
|
||||
},
|
||||
|
||||
// Enum
|
||||
UnmarshalTextTest{
|
||||
in: `count:42 bikeshed: BLUE`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Bikeshed: NewMyMessage_Color(MyMessage_BLUE),
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated field
|
||||
UnmarshalTextTest{
|
||||
in: `count:42 pet: "horsey" pet:"bunny"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Pet: []string{"horsey", "bunny"},
|
||||
},
|
||||
},
|
||||
|
||||
// Missing colon for inner message
|
||||
UnmarshalTextTest{
|
||||
in: `count:42 inner < host: "cauchy.syd" >`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Inner: &InnerMessage{
|
||||
Host: String("cauchy.syd"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Missing colon for string field
|
||||
UnmarshalTextTest{
|
||||
in: `name "Dave"`,
|
||||
error: `line 1.5: expected ':', found "\"Dave\""`,
|
||||
},
|
||||
|
||||
// Missing colon for int32 field
|
||||
UnmarshalTextTest{
|
||||
in: `count 42`,
|
||||
error: `line 1.6: expected ':', found "42"`,
|
||||
},
|
||||
|
||||
// Missing required field
|
||||
UnmarshalTextTest{
|
||||
in: ``,
|
||||
error: `line 1.0: message test_proto.MyMessage missing required field "count"`,
|
||||
},
|
||||
|
||||
// Repeated non-repeated field
|
||||
UnmarshalTextTest{
|
||||
in: `name: "Rob" name: "Russ"`,
|
||||
error: `line 1.12: non-repeated field "name" was repeated`,
|
||||
},
|
||||
|
||||
// Big all-in-one
|
||||
UnmarshalTextTest{
|
||||
in: "count:42 # Meaning\n" +
|
||||
`name:"Dave" ` +
|
||||
`quote:"\"I didn't want to go.\"" ` +
|
||||
`pet:"bunny" ` +
|
||||
`pet:"kitty" ` +
|
||||
`pet:"horsey" ` +
|
||||
`inner:<` +
|
||||
` host:"footrest.syd" ` +
|
||||
` port:7001 ` +
|
||||
` connected:true ` +
|
||||
`> ` +
|
||||
`others:<` +
|
||||
` key:3735928559 ` +
|
||||
` value:"\x01A\a\f" ` +
|
||||
`> ` +
|
||||
`others:<` +
|
||||
" weight:58.9 # Atomic weight of Co\n" +
|
||||
` inner:<` +
|
||||
` host:"lesha.mtv" ` +
|
||||
` port:8002 ` +
|
||||
` >` +
|
||||
`>`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("Dave"),
|
||||
Quote: String(`"I didn't want to go."`),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &InnerMessage{
|
||||
Host: String("footrest.syd"),
|
||||
Port: Int32(7001),
|
||||
Connected: Bool(true),
|
||||
},
|
||||
Others: []*OtherMessage{
|
||||
&OtherMessage{
|
||||
Key: Int64(3735928559),
|
||||
Value: []byte{0x1, 'A', '\a', '\f'},
|
||||
},
|
||||
&OtherMessage{
|
||||
Weight: Float32(58.9),
|
||||
Inner: &InnerMessage{
|
||||
Host: String("lesha.mtv"),
|
||||
Port: Int32(8002),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestUnmarshalText(t *testing.T) {
|
||||
for i, test := range unMarshalTextTests {
|
||||
pb := new(MyMessage)
|
||||
err := UnmarshalText(test.in, pb)
|
||||
if test.error == "" {
|
||||
// We don't expect failure.
|
||||
if err != nil {
|
||||
t.Errorf("Test %d: Unexpected error: %v", i, err)
|
||||
} else if !reflect.DeepEqual(pb, test.out) {
|
||||
t.Errorf("Test %d: Incorrect populated \n"+
|
||||
"Have: %v\nWant: %v",
|
||||
i, CompactTextString(pb), CompactTextString(test.out))
|
||||
}
|
||||
} else {
|
||||
// We do expect failure.
|
||||
if err == nil {
|
||||
t.Errorf("Test %d: Didn't get expected error: %v", i, test.error)
|
||||
} else if err.String() != test.error {
|
||||
t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
|
||||
i, err.String(), test.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
// 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"
|
||||
. "goprotobuf.googlecode.com/hg/proto"
|
||||
. "./testdata/_obj/test_proto"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newTestMessage() *MyMessage {
|
||||
return &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("Dave"),
|
||||
Quote: String(`"I didn't want to go."`),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &InnerMessage{
|
||||
Host: String("footrest.syd"),
|
||||
Port: Int32(7001),
|
||||
Connected: Bool(true),
|
||||
},
|
||||
Others: []*OtherMessage{
|
||||
&OtherMessage{
|
||||
Key: Int64(0xdeadbeef),
|
||||
Value: []byte{1, 65, 7, 12},
|
||||
},
|
||||
&OtherMessage{
|
||||
Weight: Float32(6.022),
|
||||
Inner: &InnerMessage{
|
||||
Host: String("lesha.mtv"),
|
||||
Port: Int32(8002),
|
||||
},
|
||||
},
|
||||
},
|
||||
Bikeshed: NewMyMessage_Color(MyMessage_BLUE),
|
||||
}
|
||||
}
|
||||
|
||||
const text = `count: 42
|
||||
name: "Dave"
|
||||
quote: "\"I didn't want to go.\""
|
||||
pet: "bunny"
|
||||
pet: "kitty"
|
||||
pet: "horsey"
|
||||
inner: <
|
||||
host: "footrest.syd"
|
||||
port: 7001
|
||||
connected: true
|
||||
>
|
||||
others: <
|
||||
key: 3735928559
|
||||
value: "\x01A\a\f"
|
||||
>
|
||||
others: <
|
||||
weight: 6.022
|
||||
inner: <
|
||||
host: "lesha.mtv"
|
||||
port: 8002
|
||||
>
|
||||
>
|
||||
bikeshed: BLUE
|
||||
`
|
||||
|
||||
func TestMarshalTextFull(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
MarshalText(buf, newTestMessage())
|
||||
s := buf.String()
|
||||
if s != text {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text)
|
||||
}
|
||||
}
|
||||
|
||||
func compact(src string) string {
|
||||
// ,s/[ \n]+/ /g; s/ $//;
|
||||
dst := make([]byte, len(src))
|
||||
space := false
|
||||
j := 0
|
||||
for i := 0; i < len(src); i++ {
|
||||
c := src[i]
|
||||
if c == ' ' || c == '\n' {
|
||||
space = true
|
||||
continue
|
||||
}
|
||||
if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<') {
|
||||
space = false
|
||||
}
|
||||
if space {
|
||||
dst[j] = ' '
|
||||
j++
|
||||
space = false
|
||||
}
|
||||
dst[j] = c
|
||||
j++
|
||||
}
|
||||
if space {
|
||||
dst[j] = ' '
|
||||
j++
|
||||
}
|
||||
return string(dst[0:j])
|
||||
}
|
||||
|
||||
var compactText = compact(text)
|
||||
|
||||
func TestCompactText(t *testing.T) {
|
||||
s := CompactTextString(newTestMessage())
|
||||
if s != compactText {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, compactText)
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче