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:
Rob Pike 2010-03-20 22:32:34 -07:00
Родитель fceca43ab4
Коммит aaa3a62e62
37 изменённых файлов: 8367 добавлений и 0 удалений

11
CONTRIBUTORS Normal file
Просмотреть файл

@ -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>

31
LICENSE Normal file
Просмотреть файл

@ -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.

46
Make.protobuf Normal file
Просмотреть файл

@ -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=. $<

53
Makefile Normal file
Просмотреть файл

@ -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

160
README Normal file
Просмотреть файл

@ -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.
}

44
compiler/Makefile Normal file
Просмотреть файл

@ -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)
}

51
compiler/doc.go Normal file
Просмотреть файл

@ -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

903
compiler/main.go Normal file
Просмотреть файл

@ -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
}

54
compiler/plugin/Makefile Normal file
Просмотреть файл

@ -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() {
}

63
compiler/testdata/Makefile поставляемый Normal file
Просмотреть файл

@ -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

41
compiler/testdata/imp.proto поставляемый Normal file
Просмотреть файл

@ -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;
}
}

44
compiler/testdata/main.go поставляемый Normal file
Просмотреть файл

@ -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()
}

42
compiler/testdata/multi1.proto поставляемый Normal file
Просмотреть файл

@ -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;
}

44
compiler/testdata/multi2.proto поставляемый Normal file
Просмотреть файл

@ -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;
}

41
compiler/testdata/multi3.proto поставляемый Normal file
Просмотреть файл

@ -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;
}

124
compiler/testdata/test.pb.go.golden поставляемый Normal file
Просмотреть файл

@ -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)
}

75
compiler/testdata/test.proto поставляемый Normal file
Просмотреть файл

@ -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;
}
}

45
proto/Makefile Normal file
Просмотреть файл

@ -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

1042
proto/all_test.go Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

741
proto/decode.go Normal file
Просмотреть файл

@ -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
}

557
proto/encode.go Normal file
Просмотреть файл

@ -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
}

153
proto/extensions.go Normal file
Просмотреть файл

@ -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
}

537
proto/lib.go Normal file
Просмотреть файл

@ -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
}

515
proto/properties.go Normal file
Просмотреть файл

@ -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
}

53
proto/testdata/Makefile поставляемый Normal file
Просмотреть файл

@ -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

334
proto/testdata/test.pb.go поставляемый Normal file
Просмотреть файл

@ -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)
}

334
proto/testdata/test.pb.go.golden поставляемый Normal file
Просмотреть файл

@ -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)
}

209
proto/testdata/test.proto поставляемый Normal file
Просмотреть файл

@ -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;
};
};

221
proto/text.go Normal file
Просмотреть файл

@ -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()
}

473
proto/text_parser.go Normal file
Просмотреть файл

@ -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
}

244
proto/text_parser_test.go Normal file
Просмотреть файл

@ -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)
}
}
}
}

139
proto/text_test.go Normal file
Просмотреть файл

@ -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)
}
}