Commit 6803686b authored by Jon Skeet's avatar Jon Skeet

First cut at new layout

parent f0589506
# Untracked files # Untracked files
csharp/ProtocolBuffers/bin/ src/ProtocolBuffers/bin/
csharp/ProtocolBuffers/obj/ src/ProtocolBuffers/obj/
csharp/ProtocolBuffers.Test/bin/ src/ProtocolBuffers.Test/bin/
csharp/ProtocolBuffers.Test/obj/ src/ProtocolBuffers.Test/obj/
csharp/ProtoGen/bin/ src/ProtoGen/bin/
csharp/ProtoGen/obj/ src/ProtoGen/obj/
csharp/ProtoGen.Test/bin/ src/ProtoGen.Test/bin/
csharp/ProtoGen.Test/obj/ src/ProtoGen.Test/obj/
csharp/TestBed
java/.classpath
java/.project
java/.settings/
java/bin/
java/lib/
java/src/.classpath
java/src/.project
java/src/bin/
java/target/
src/tmp/
tmp/ tmp/
vsprojects/* *.user
vsprojects/protobuf.sln *.suo
benchmark.txt _ReSharper.*
\ No newline at end of file
<?xml version="1.0"?>
<project name="Protocol Buffers" default="build" basedir=".">
<description>Port of Google's Protocol Buffers to C#/.NET</description>
<!-- NAntContrib configuration. TODO(jonskeet): Improve this? -->
<property name="nantcontrib-dir"
value="${path::combine(nant::get-base-directory(), '../../NAntContrib')}"
overwrite="false" />
<loadtasks assembly="${path::combine(nantcontrib-dir, 'bin/NAnt.Contrib.Tasks.dll')}" />
<property name="build-configuration"
value="Debug"
overwrite="false" />
<property name="src"
value="${project::get-base-directory()}/src" />
<property name="tools-protoc"
value="${project::get-base-directory()}/lib/protoc.exe"
overwrite="false" />
<!-- Base directory to find protos (core, C# options, tests) -->
<property name="protos-dir"
value="${path::combine(project::get-base-directory(), 'protos')}"
overwrite="false" />
<!-- Scratch directory used when generating code -->
<property name="tmp-dir"
value="${path::combine(project::get-base-directory(), 'tmp')}"
overwrite="false" />
<!-- Which version of protogen to use when regenerating source -->
<property name="tools-protogen-config"
value="Debug"
overwrite="false" />
<property name="tools-protogen"
value="${src}/ProtoGen/bin/${tools-protogen-config}/protogen.exe"
overwrite="false"/>
<target name="clean"
description="Removes built binaries (of all configurations) and the source generation directory">
<delete>
<fileset>
<include name="${src}/ProtoGen/bin/**" />
<include name="${src}/ProtoGen/obj/**" />
<include name="${src}/ProtoGen.Test/bin/**" />
<include name="${src}/ProtoGen.Test/obj/**" />
<include name="${src}/ProtocolBuffers/bin/**" />
<include name="${src}/ProtocolBuffers/obj/**" />
<include name="${src}/ProtocolBuffers.Test/bin/**" />
<include name="${src}/ProtocolBuffers.Test/obj/**" />
<include name="${tmp-dir}" />
</fileset>
</delete>
</target>
<target name="generate-source"
description="Generate source (unit tests, core messages etc). Does not copy source.">
<fail message="protoc and protogen must both exist"
unless="${file::exists(tools-protoc) and file::exists(tools-protogen)}" />
<delete dir="${tmp-dir}" />
<mkdir dir="${tmp-dir}" />
<exec program="${tools-protoc}"
workingdir="${tmp-dir}">
<arg value="--proto_path=${protos-dir}" />
<arg value="--descriptor_set_out=compiled.pb" />
<arg file="${protos-dir}/google/protobuf/descriptor.proto" />
<arg file="${protos-dir}/google/protobuf/csharp_options.proto" />
<arg file="${protos-dir}/google/protobuf/unittest.proto" />
<arg file="${protos-dir}/google/protobuf/unittest_custom_options.proto" />
<arg file="${protos-dir}/google/protobuf/unittest_embed_optimize_for.proto" />
<arg file="${protos-dir}/google/protobuf/unittest_import.proto" />
<arg file="${protos-dir}/google/protobuf/unittest_mset.proto" />
<arg file="${protos-dir}/google/protobuf/unittest_optimize_for.proto" />
</exec>
<exec program="${tools-protogen}"
workingdir="${tmp-dir}">
<arg value="compiled.pb" />
</exec>
</target>
<target name="copy-generated-source"
description="Copies generated source from temporary directory to source tree. Use with care!">
<copy todir="${src}/ProtocolBuffers/DescriptorProtos">
<fileset basedir="${tmp-dir}">
<include name="DescriptorProtoFile.cs" />
<include name="CSharpOptions.cs" />
</fileset>
</copy>
<copy todir="${src}/ProtocolBuffers.Test/TestProtos">
<fileset basedir="${tmp-dir}">
<include name="UnitTestProtoFile.cs" />
<include name="UnitTestCustomOptionsProtoFile.cs" />
<include name="UnitTestEmbedOptimizeForProtoFile.cs" />
<include name="UnitTestImportProtoFile.cs" />
<include name="UnitTestMessageSetProtoFile.cs" />
<include name="UnitTestOptimizeForProtoFile.cs" />
</fileset>
</copy>
</target>
<target name="build" description="Builds all C# code">
<msbuild project="${src}/ProtocolBuffers.sln">
<property name="Configuration"
value="${build-configuration}" />
</msbuild>
</target>
<target name="test" description="Runs all unit tests">
<nunit2>
<formatter type="Plain" />
<test assemblyname="${src}/ProtocolBuffers.Test/bin/${build-configuration}/Google.ProtocolBuffers.Test.dll" />
<test assemblyname="${src}/Protogen.Test/bin/${build-configuration}/Google.ProtocolBuffers.ProtoGen.Test.dll" />
</nunit2>
</target>
<target name="perf-test" description="Runs all performance tests">
<fail message="Performance tests not implemented yet" />
</target>
</project>
This diff is collapsed.
Copyright © 2002-2007 Charlie Poole
Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
Copyright © 2000-2002 Philip A. Craig
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required.
Portions Copyright © 2002-2007 Charlie Poole or Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
protoc.exe was built from the original source at http://code.google.com/p/protobuf/
The licence for this code is as follows:
Copyright 2008, Google Inc.
All rights reserved.
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.
Code generated by the Protocol Buffer compiler is owned by the owner
of the input file used when generating it. This code is not
standalone and requires a support library to be linked with it. This
support library is itself covered by the above license.
\ No newline at end of file
File added
Copyright (c) 2005 - 2008 Ayende Rahien (ayende@ayende.com)
All rights reserved.
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 Ayende Rahien 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.
\ No newline at end of file
// Extra options for C# generator
import "google/protobuf/descriptor.proto";
package google.protobuf;
option (CSharpNamespace) = "Google.ProtocolBuffers.DescriptorProtos";
option (CSharpUmbrellaClassname) = "CSharpOptions";
extend FileOptions {
optional string CSharpNamespace = 20000;
optional string CSharpUmbrellaClassname = 20001;
optional bool CSharpMultipleFiles = 20002;
optional bool CSharpNestClasses = 20003;
optional bool CSharpPublicClasses = 20004;
}
This diff is collapsed.
This diff is collapsed.
// Additional options required for C# generation. File from copyright
// line onwards is as per original distribution.
import "google/protobuf/csharp_options.proto";
option (google.protobuf.CSharpNamespace) = "Google.ProtocolBuffers.TestProtos";
option (google.protobuf.CSharpUmbrellaClassname) = "UnitTestCustomOptionsProtoFile";
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: benjy@google.com (Benjy Weinberger)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file used to test the "custom options" feature of proto2.
// A custom file option (defined below).
option (file_opt1) = 9876543210;
import "google/protobuf/descriptor.proto";
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
package protobuf_unittest;
// Some simple test custom options of various types.
extend google.protobuf.FileOptions {
optional uint64 file_opt1 = 7736974;
}
extend google.protobuf.MessageOptions {
optional int32 message_opt1 = 7739036;
}
extend google.protobuf.FieldOptions {
optional fixed64 field_opt1 = 7740936;
// This is useful for testing that we correctly register default values for
// extension options.
optional int32 field_opt2 = 7753913 [default=42];
}
extend google.protobuf.EnumOptions {
optional sfixed32 enum_opt1 = 7753576;
}
// TODO(benjy): Test options on enum values when the parser supports them.
extend google.protobuf.ServiceOptions {
optional sint64 service_opt1 = 7887650;
}
enum MethodOpt1 {
METHODOPT1_VAL1 = 1;
METHODOPT1_VAL2 = 2;
}
extend google.protobuf.MethodOptions {
optional MethodOpt1 method_opt1 = 7890860;
}
// A test message with custom options at all possible locations (and also some
// regular options, to make sure they interact nicely).
message TestMessageWithCustomOptions {
option message_set_wire_format = false;
option (message_opt1) = -56;
optional string field1 = 1 [ctype=CORD,
(field_opt1)=8765432109];
enum AnEnum {
option (enum_opt1) = -789;
ANENUM_VAL1 = 1;
ANENUM_VAL2 = 2;
}
}
// A test RPC service with custom options at all possible locations (and also
// some regular options, to make sure they interact nicely).
message CustomOptionFooRequest {
}
message CustomOptionFooResponse {
}
service TestServiceWithCustomOptions {
option (service_opt1) = -9876543210;
rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) {
option (method_opt1) = METHODOPT1_VAL2;
}
}
// Options of every possible field type, so we can test them all exhaustively.
message DummyMessageContainingEnum {
enum TestEnumType {
TEST_OPTION_ENUM_TYPE1 = 22;
TEST_OPTION_ENUM_TYPE2 = -23;
}
}
message DummyMessageInvalidAsOptionType {
}
extend google.protobuf.MessageOptions {
optional bool bool_opt = 7706090;
optional int32 int32_opt = 7705709;
optional int64 int64_opt = 7705542;
optional uint32 uint32_opt = 7704880;
optional uint64 uint64_opt = 7702367;
optional sint32 sint32_opt = 7701568;
optional sint64 sint64_opt = 7700863;
optional fixed32 fixed32_opt = 7700307;
optional fixed64 fixed64_opt = 7700194;
optional sfixed32 sfixed32_opt = 7698645;
optional sfixed64 sfixed64_opt = 7685475;
optional float float_opt = 7675390;
optional double double_opt = 7673293;
optional string string_opt = 7673285;
optional bytes bytes_opt = 7673238;
optional DummyMessageContainingEnum.TestEnumType enum_opt = 7673233;
optional DummyMessageInvalidAsOptionType message_type_opt = 7665967;
}
message CustomOptionMinIntegerValues {
option (bool_opt) = false;
option (int32_opt) = -0x80000000;
option (int64_opt) = -0x8000000000000000;
option (uint32_opt) = 0;
option (uint64_opt) = 0;
option (sint32_opt) = -0x80000000;
option (sint64_opt) = -0x8000000000000000;
option (fixed32_opt) = 0;
option (fixed64_opt) = 0;
option (sfixed32_opt) = -0x80000000;
option (sfixed64_opt) = -0x8000000000000000;
}
message CustomOptionMaxIntegerValues {
option (bool_opt) = true;
option (int32_opt) = 0x7FFFFFFF;
option (int64_opt) = 0x7FFFFFFFFFFFFFFF;
option (uint32_opt) = 0xFFFFFFFF;
option (uint64_opt) = 0xFFFFFFFFFFFFFFFF;
option (sint32_opt) = 0x7FFFFFFF;
option (sint64_opt) = 0x7FFFFFFFFFFFFFFF;
option (fixed32_opt) = 0xFFFFFFFF;
option (fixed64_opt) = 0xFFFFFFFFFFFFFFFF;
option (sfixed32_opt) = 0x7FFFFFFF;
option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF;
}
message CustomOptionOtherValues {
option (int32_opt) = -100; // To test sign-extension.
option (float_opt) = 12.3456789;
option (double_opt) = 1.234567890123456789;
option (string_opt) = "Hello, \"World\"";
option (bytes_opt) = "Hello\0World";
option (enum_opt) = TEST_OPTION_ENUM_TYPE2;
}
message SettingRealsFromPositiveInts {
option (float_opt) = 12;
option (double_opt) = 154;
}
message SettingRealsFromNegativeInts {
option (float_opt) = -12;
option (double_opt) = -154;
}
// Options of complex message types, themselves combined and extended in
// various ways.
message ComplexOptionType1 {
optional int32 foo = 1;
extensions 100 to max;
}
message ComplexOptionType2 {
optional ComplexOptionType1 bar = 1;
optional int32 baz = 2;
message ComplexOptionType4 {
optional int32 waldo = 1;
extend google.protobuf.MessageOptions {
optional ComplexOptionType4 complex_opt4 = 7633546;
}
}
optional ComplexOptionType4 fred = 3;
extensions 100 to max;
}
message ComplexOptionType3 {
optional int32 qux = 1;
optional group ComplexOptionType5 = 2 {
optional int32 plugh = 3;
}
}
extend ComplexOptionType1 {
optional int32 quux = 7663707;
optional ComplexOptionType3 corge = 7663442;
}
extend ComplexOptionType2 {
optional int32 grault = 7650927;
optional ComplexOptionType1 garply = 7649992;
}
extend google.protobuf.MessageOptions {
optional protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756;
optional ComplexOptionType2 complex_opt2 = 7636949;
optional ComplexOptionType3 complex_opt3 = 7636463;
optional group ComplexOpt6 = 7595468 {
optional int32 xyzzy = 7593951;
}
}
// Note that we try various different ways of naming the same extension.
message VariousComplexOptions {
option (.protobuf_unittest.complex_opt1).foo = 42;
option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324;
option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876;
option (complex_opt2).baz = 987;
option (complex_opt2).(grault) = 654;
option (complex_opt2).bar.foo = 743;
option (complex_opt2).bar.(quux) = 1999;
option (complex_opt2).bar.(protobuf_unittest.corge).qux = 2008;
option (complex_opt2).(garply).foo = 741;
option (complex_opt2).(garply).(.protobuf_unittest.quux) = 1998;
option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121;
option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971;
option (complex_opt2).fred.waldo = 321;
option (protobuf_unittest.complex_opt3).qux = 9;
option (complex_opt3).complexoptiontype5.plugh = 22;
option (complexopt6).xyzzy = 24;
}
// Additional options required for C# generation. File from copyright
// line onwards is as per original distribution.
import "google/protobuf/csharp_options.proto";
import "google/protobuf/descriptor.proto";
option (google.protobuf.CSharpNamespace) = "Google.ProtocolBuffers.TestProtos";
option (google.protobuf.CSharpUmbrellaClassname) = "UnitTestEmbedOptimizeForProtoFile";
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
import "google/protobuf/unittest_optimize_for.proto";
package protobuf_unittest;
// We optimize for speed here, but we are importing a proto that is optimized
// for code size.
option optimize_for = SPEED;
message TestEmbedOptimizedForSize {
// Test that embedding a message which has optimize_for = CODE_SIZE into
// one optimized for speed works.
optional TestOptimizedForSize optional_message = 1;
repeated TestOptimizedForSize repeated_message = 2;
}
// Additional options required for C# generation. File from copyright
// line onwards is as per original distribution.
import "google/protobuf/csharp_options.proto";
import "google/protobuf/descriptor.proto";
option (google.protobuf.CSharpNamespace) = "Google.ProtocolBuffers.TestProtos";
option (google.protobuf.CSharpUmbrellaClassname) = "UnitTestImportProtoFile";
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which is imported by unittest.proto to test importing.
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
// In test_util.h we do
// "using namespace unittest_import = protobuf_unittest_import".
package protobuf_unittest_import;
option optimize_for = SPEED;
// Excercise the java_package option.
option java_package = "com.google.protobuf.test";
// Do not set a java_outer_classname here to verify that Proto2 works without
// one.
message ImportMessage {
optional int32 d = 1;
}
enum ImportEnum {
IMPORT_FOO = 7;
IMPORT_BAR = 8;
IMPORT_BAZ = 9;
}
// Additional options required for C# generation. File from copyright
// line onwards is as per original distribution.
import "google/protobuf/csharp_options.proto";
import "google/protobuf/descriptor.proto";
option (google.protobuf.CSharpNamespace) = "Google.ProtocolBuffers.TestProtos";
option (google.protobuf.CSharpUmbrellaClassname) = "UnitTestMessageSetProtoFile";
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// This file contains messages for testing message_set_wire_format.
package protobuf_unittest;
option optimize_for = SPEED;
// A message with message_set_wire_format.
message TestMessageSet {
option message_set_wire_format = true;
extensions 4 to max;
}
message TestMessageSetContainer {
optional TestMessageSet message_set = 1;
}
message TestMessageSetExtension1 {
extend TestMessageSet {
optional TestMessageSetExtension1 message_set_extension = 1545008;
}
optional int32 i = 15;
}
message TestMessageSetExtension2 {
extend TestMessageSet {
optional TestMessageSetExtension2 message_set_extension = 1547769;
}
optional string str = 25;
}
// MessageSet wire format is equivalent to this.
message RawMessageSet {
repeated group Item = 1 {
required int32 type_id = 2;
required bytes message = 3;
}
}
// Additional options required for C# generation. File from copyright
// line onwards is as per original distribution.
import "google/protobuf/csharp_options.proto";
import "google/protobuf/descriptor.proto";
option (google.protobuf.CSharpNamespace) = "Google.ProtocolBuffers.TestProtos";
option (google.protobuf.CSharpUmbrellaClassname) = "UnitTestOptimizeForProtoFile";
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which uses optimize_for = CODE_SIZE.
import "google/protobuf/unittest.proto";
package protobuf_unittest;
option optimize_for = CODE_SIZE;
message TestOptimizedForSize {
optional int32 i = 1;
optional ForeignMessage msg = 19;
extensions 1000 to max;
extend TestOptimizedForSize {
optional int32 test_extension = 1234;
}
}
message TestRequiredOptimizedForSize {
required int32 x = 1;
}
message TestOptionalOptimizedForSize {
optional TestRequiredOptimizedForSize o = 1;
}
Welcome! This is, of course, a placeholder file.
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
using NUnit.Framework;
using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.ProtoGen;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Tests for the dependency resolution in Generator.
/// </summary>
[TestFixture]
public class DependencyResolutionTest {
[Test]
public void TwoDistinctFiles() {
FileDescriptorProto first = new FileDescriptorProto.Builder { Name="First" }.Build();
FileDescriptorProto second = new FileDescriptorProto.Builder { Name="Second" }.Build();
FileDescriptorSet set = new FileDescriptorSet { FileList = { first, second } };
IList<FileDescriptor> converted = Generator.ConvertDescriptors(set);
Assert.AreEqual(2, converted.Count);
Assert.AreEqual("First", converted[0].Name);
Assert.AreEqual(0, converted[0].Dependencies.Count);
Assert.AreEqual("Second", converted[1].Name);
Assert.AreEqual(0, converted[1].Dependencies.Count);
}
[Test]
public void FirstDependsOnSecond() {
FileDescriptorProto first = new FileDescriptorProto.Builder { Name = "First", DependencyList = {"Second"} }.Build();
FileDescriptorProto second = new FileDescriptorProto.Builder { Name = "Second" }.Build();
FileDescriptorSet set = new FileDescriptorSet { FileList = { first, second } };
IList<FileDescriptor> converted = Generator.ConvertDescriptors(set);
Assert.AreEqual(2, converted.Count);
Assert.AreEqual("First", converted[0].Name);
Assert.AreEqual(1, converted[0].Dependencies.Count);
Assert.AreEqual(converted[1], converted[0].Dependencies[0]);
Assert.AreEqual("Second", converted[1].Name);
Assert.AreEqual(0, converted[1].Dependencies.Count);
}
[Test]
public void SecondDependsOnFirst() {
FileDescriptorProto first = new FileDescriptorProto.Builder { Name = "First" }.Build();
FileDescriptorProto second = new FileDescriptorProto.Builder { Name = "Second", DependencyList = {"First"} }.Build();
FileDescriptorSet set = new FileDescriptorSet { FileList = { first, second } };
IList<FileDescriptor> converted = Generator.ConvertDescriptors(set);
Assert.AreEqual(2, converted.Count);
Assert.AreEqual("First", converted[0].Name);
Assert.AreEqual(0, converted[0].Dependencies.Count);
Assert.AreEqual("Second", converted[1].Name);
Assert.AreEqual(1, converted[1].Dependencies.Count);
Assert.AreEqual(converted[0], converted[1].Dependencies[0]);
}
[Test]
public void CircularDependency() {
FileDescriptorProto first = new FileDescriptorProto.Builder { Name = "First", DependencyList = { "Second" } }.Build();
FileDescriptorProto second = new FileDescriptorProto.Builder { Name = "Second", DependencyList = { "First" } }.Build();
FileDescriptorSet set = new FileDescriptorSet { FileList = { first, second } };
try {
Generator.ConvertDescriptors(set);
Assert.Fail("Expected exception");
} catch (DependencyResolutionException) {
// Expected
}
}
[Test]
public void MissingDependency() {
FileDescriptorProto first = new FileDescriptorProto.Builder { Name = "First", DependencyList = { "Second" } }.Build();
FileDescriptorSet set = new FileDescriptorSet { FileList = { first } };
try {
Generator.ConvertDescriptors(set);
Assert.Fail("Expected exception");
} catch (DependencyResolutionException) {
// Expected
}
}
[Test]
public void SelfDependency() {
FileDescriptorProto first = new FileDescriptorProto.Builder { Name = "First", DependencyList = { "First" } }.Build();
FileDescriptorSet set = new FileDescriptorSet { FileList = { first } };
try {
Generator.ConvertDescriptors(set);
Assert.Fail("Expected exception");
} catch (DependencyResolutionException) {
// Expected
}
}
}
}
\ No newline at end of file
using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.Descriptors;
using NUnit.Framework;
namespace Google.ProtocolBuffers.ProtoGen {
[TestFixture]
public class DescriptorUtilTest {
[Test]
public void ExplicitNamespace() {
FileDescriptorProto proto = new FileDescriptorProto.Builder {
Name = "x", Package = "pack", Options = new FileOptions.Builder().SetExtension(CSharpOptions.CSharpNamespace, "Foo.Bar").Build()
}.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("Foo.Bar", DescriptorUtil.GetNamespace(descriptor));
}
[Test]
public void NoNamespaceFallsBackToPackage() {
FileDescriptorProto proto = new FileDescriptorProto.Builder { Name = "x", Package = "pack" }.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("pack", DescriptorUtil.GetNamespace(descriptor));
}
[Test]
public void NoNamespaceOrPackageFallsBackToEmptyString() {
FileDescriptorProto proto = new FileDescriptorProto.Builder { Name = "x" }.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("", DescriptorUtil.GetNamespace(descriptor));
}
[Test]
public void ExplicitlyNamedFileClass() {
FileDescriptorProto proto = new FileDescriptorProto.Builder {
Name = "x", Options = new FileOptions.Builder().SetExtension(CSharpOptions.CSharpUmbrellaClassname, "Foo").Build()
}.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("Foo", DescriptorUtil.GetUmbrellaClassName(descriptor));
}
[Test]
public void ImplicitFileClassWithProtoSuffix() {
FileDescriptorProto proto = new FileDescriptorProto.Builder { Name = "foo_bar.proto" }.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("FooBar", DescriptorUtil.GetUmbrellaClassName(descriptor));
}
[Test]
public void ImplicitFileClassWithProtoDevelSuffix() {
FileDescriptorProto proto = new FileDescriptorProto.Builder { Name = "foo_bar.protodevel" }.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("FooBar", DescriptorUtil.GetUmbrellaClassName(descriptor));
}
[Test]
public void ImplicitFileClassWithNoSuffix() {
FileDescriptorProto proto = new FileDescriptorProto.Builder { Name = "foo_bar" }.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("FooBar", DescriptorUtil.GetUmbrellaClassName(descriptor));
}
[Test]
public void ImplicitFileClassWithDirectoryStructure() {
FileDescriptorProto proto = new FileDescriptorProto.Builder { Name = "x/y/foo_bar" }.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("FooBar", DescriptorUtil.GetUmbrellaClassName(descriptor));
}
}
}
using Google.ProtocolBuffers.DescriptorProtos;
using NUnit.Framework;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
[TestFixture]
public class GeneratorTest {
}
}
\ No newline at end of file
using Google.ProtocolBuffers.ProtoGen;
using NUnit.Framework;
namespace Google.ProtocolBuffers.ProtoGen {
[TestFixture]
public class HelpersTest {
[Test]
public void UnderscoresToPascalCase() {
Assert.AreEqual("FooBar", Helpers.UnderscoresToPascalCase("Foo_bar"));
Assert.AreEqual("FooBar", Helpers.UnderscoresToPascalCase("foo_bar"));
Assert.AreEqual("Foo0Bar", Helpers.UnderscoresToPascalCase("Foo0bar"));
Assert.AreEqual("FooBar", Helpers.UnderscoresToPascalCase("Foo_+_Bar"));
}
[Test]
public void UnderscoresToCamelCase() {
Assert.AreEqual("fooBar", Helpers.UnderscoresToCamelCase("Foo_bar"));
Assert.AreEqual("fooBar", Helpers.UnderscoresToCamelCase("foo_bar"));
Assert.AreEqual("foo0Bar", Helpers.UnderscoresToCamelCase("Foo0bar"));
Assert.AreEqual("fooBar", Helpers.UnderscoresToCamelCase("Foo_+_Bar"));
}
[Test]
public void StripSuffix() {
string text = "FooBar";
Assert.IsFalse(Helpers.StripSuffix(ref text, "Foo"));
Assert.AreEqual("FooBar", text);
Assert.IsTrue(Helpers.StripSuffix(ref text, "Bar"));
Assert.AreEqual("Foo", text);
}
}
}
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ProtoGen.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProtoGen.Test")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("40720ee3-2d15-4271-8c42-8f9cfd01b52f")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C268DA4C-4004-47DA-AF23-44C983281A68}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Google.ProtocolBuffers.ProtoGen</RootNamespace>
<AssemblyName>Google.ProtocolBuffers.ProtoGen.Test</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.ProtoGen.Test.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Rhino.Mocks, Version=3.5.0.2, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\Rhino.Mocks.dll</HintPath>
</Reference>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="DependencyResolutionTest.cs" />
<Compile Include="DescriptorUtilTest.cs" />
<Compile Include="GeneratorTest.cs" />
<Compile Include="HelpersTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">
<Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
<Name>ProtocolBuffers</Name>
</ProjectReference>
<ProjectReference Include="..\ProtoGen\ProtoGen.csproj">
<Project>{250ADE34-82FD-4BAE-86D5-985FBE589C4A}</Project>
<Name>ProtoGen</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Properties\Google.ProtocolBuffers.ProtoGen.Test.snk" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Exception thrown when dependencies within a descriptor set can't be resolved.
/// </summary>
public sealed class DependencyResolutionException : Exception {
public DependencyResolutionException(string message) : base(message) {
}
public DependencyResolutionException(string format, params object[] args)
: base(string.Format(format, args)) {
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.DescriptorProtos;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Utility class for determining namespaces etc.
/// </summary>
internal static class DescriptorUtil {
internal static bool NestClasses(IDescriptor descriptor) {
// Defaults to false
return descriptor.File.Options.GetExtension(CSharpOptions.CSharpNestClasses);
}
internal static string GetNamespace(FileDescriptor descriptor) {
if (descriptor.Name == "google/protobuf/descriptor.proto") {
return typeof(DescriptorProtoFile).Namespace;
}
return descriptor.Options.HasExtension(CSharpOptions.CSharpNamespace) ?
descriptor.Options.GetExtension(CSharpOptions.CSharpNamespace) : descriptor.Package;
}
// Groups are hacky: The name of the field is just the lower-cased name
// of the group type. In C#, though, we would like to retain the original
// capitalization of the type name.
internal static string GetFieldName(FieldDescriptor descriptor) {
if (descriptor.FieldType == FieldType.Group) {
return descriptor.MessageType.Name;
} else {
return descriptor.Name;
}
}
internal static string GetClassName(IDescriptor descriptor) {
return ToCSharpName(descriptor.FullName, descriptor.File);
}
internal static string GetFullUmbrellaClassName(FileDescriptor descriptor) {
string result = GetNamespace(descriptor);
if (result != "") result += '.';
result += GetUmbrellaClassName(descriptor);
return "global::" + result;
}
internal static string GetUmbrellaClassName(FileDescriptor descriptor) {
if (descriptor.Name == "google/protobuf/descriptor.proto") {
return typeof(DescriptorProtoFile).Name;
}
FileOptions options = descriptor.Options;
if (options.HasExtension(CSharpOptions.CSharpUmbrellaClassname)) {
return descriptor.Options.GetExtension(CSharpOptions.CSharpUmbrellaClassname);
}
int lastSlash = descriptor.Name.LastIndexOf('/');
string baseName = descriptor.Name.Substring(lastSlash + 1);
return Helpers.UnderscoresToPascalCase(StripProto(baseName));
}
private static string StripProto(string text) {
if (!Helpers.StripSuffix(ref text, ".protodevel")) {
Helpers.StripSuffix(ref text, ".proto");
}
return text;
}
private static string ToCSharpName(string name, FileDescriptor file) {
string result;
if (!NestClasses(file)) {
result = GetNamespace(file);
} else {
result = GetUmbrellaClassName(file);
}
if (result != "") {
result += '.';
}
string classname;
if (file.Package == "") {
classname = name;
} else {
// Strip the proto package from full_name since we've replaced it with
// the C# namespace.
classname = name.Substring(file.Package.Length + 1);
}
result += classname.Replace(".", ".Types.");
return "global::" + result;
}
internal static string GetMappedTypeName(MappedType type) {
switch(type) {
case MappedType.Int32: return "int";
case MappedType.Int64: return "long";
case MappedType.UInt32: return "uint";
case MappedType.UInt64: return "ulong";
case MappedType.Single: return "float";
case MappedType.Double: return "double";
case MappedType.Boolean: return "bool";
case MappedType.String: return "string";
case MappedType.ByteString: return "pb::ByteString";
case MappedType.Enum: return null;
case MappedType.Message: return null;
default:
throw new ArgumentOutOfRangeException("Unknown mapped type " + type);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class EnumFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
internal EnumFieldGenerator(FieldDescriptor descriptor)
: base(descriptor) {
}
public void GenerateMembers(TextGenerator writer) {
writer.WriteLine("private bool has{0};", CapitalizedName);
writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
writer.WriteLine("public bool Has{0} {{", CapitalizedName);
writer.WriteLine(" get {{ return has{0}; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
writer.WriteLine(" get {{ return {0}_; }}", Name);
writer.WriteLine("}");
}
public void GenerateBuilderMembers(TextGenerator writer) {
writer.WriteLine("public bool Has{0} {{", CapitalizedName);
writer.WriteLine(" get {{ return result.Has{0}; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
writer.WriteLine(" set {{ Set{0}(value); }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public Builder Set{0}({1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.has{0} = true;", CapitalizedName);
writer.WriteLine(" result.{0}_ = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Clear{0}() {{", CapitalizedName);
writer.WriteLine(" result.has{0} = false;", CapitalizedName);
writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
writer.WriteLine(" return this;");
writer.WriteLine("}");
}
public void GenerateMergingCode(TextGenerator writer) {
writer.WriteLine("if (other.Has{0}) {{", CapitalizedName);
writer.WriteLine(" {0} = other.{0};", PropertyName);
writer.WriteLine("}");
}
public void GenerateBuildingCode(TextGenerator writer) {
// Nothing to do here for enum types
}
public void GenerateParsingCode(TextGenerator writer) {
// TODO(jonskeet): Make a more efficient way of doing this
writer.WriteLine("int rawValue = input.ReadEnum();");
writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
writer.WriteLine(" unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
writer.WriteLine("} else {");
writer.WriteLine(" {0} = ({1}) rawValue;", PropertyName, TypeName);
writer.WriteLine("}");
}
public void GenerateSerializationCode(TextGenerator writer) {
writer.WriteLine("if (Has{0}) {{", CapitalizedName);
writer.WriteLine(" output.WriteEnum({0}, (int) {1});", Number, PropertyName);
writer.WriteLine("}");
}
public void GenerateSerializedSizeCode(TextGenerator writer) {
writer.WriteLine("if (Has{0}) {{", CapitalizedName);
writer.WriteLine(" size += pb::CodedOutputStream.ComputeEnumSize({0}, (int) {1});", Number, PropertyName);
writer.WriteLine("}");
}
}
}
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class EnumGenerator : SourceGeneratorBase<EnumDescriptor>, ISourceGenerator {
internal EnumGenerator(EnumDescriptor descriptor) : base(descriptor) {
}
public void Generate(TextGenerator writer) {
writer.WriteLine("{0} enum {1} {{", ClassAccessLevel, Descriptor.Name);
writer.Indent();
foreach (EnumValueDescriptor value in Descriptor.Values) {
writer.WriteLine("{0} = {1},", value.Name, value.Number);
}
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class ExtensionGenerator : SourceGeneratorBase<FieldDescriptor>, ISourceGenerator {
internal ExtensionGenerator(FieldDescriptor descriptor) : base(descriptor) {
}
public void Generate(TextGenerator writer) {
string name = Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(Descriptor));
string type;
switch (Descriptor.MappedType) {
case MappedType.Message:
type = DescriptorUtil.GetClassName(Descriptor.MessageType);
break;
case MappedType.Enum:
type = DescriptorUtil.GetClassName(Descriptor.EnumType);
break;
default:
type = DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
break;
}
if (Descriptor.IsRepeated) {
writer.WriteLine("{0} static readonly", ClassAccessLevel);
writer.WriteLine(" pb::GeneratedExtensionBase<scg::IList<{0}>> {1} =", type, name);
writer.WriteLine(" pb::GeneratedRepeatExtension<{0}>.CreateInstance(Descriptor.Extensions[{1}]);", type, Descriptor.Index);
} else {
writer.WriteLine("{0} static readonly pb::GeneratedExtensionBase<{1}> {2} =", ClassAccessLevel, type, name);
writer.WriteLine(" pb::GeneratedSingleExtension<{0}>.CreateInstance(Descriptor.Extensions[{1}]);", type, Descriptor.Index);
}
}
}
}
using System;
using Google.ProtocolBuffers.Descriptors;
using System.Globalization;
namespace Google.ProtocolBuffers.ProtoGen {
internal abstract class FieldGeneratorBase : SourceGeneratorBase<FieldDescriptor> {
protected FieldGeneratorBase(FieldDescriptor descriptor)
: base(descriptor) {
}
private static bool AllPrintableAscii(string text) {
foreach (char c in text) {
if (c < 0x20 || c > 0x7e) {
return false;
}
}
return true;
}
protected string DefaultValue {
get {
string suffix = "";
switch (Descriptor.FieldType) {
case FieldType.Float: suffix = "F"; break;
case FieldType.Double: suffix = "D"; break;
case FieldType.Int64: suffix = "L"; break;
case FieldType.UInt64: suffix = "UL"; break;
}
switch (Descriptor.FieldType) {
case FieldType.Float:
case FieldType.Double:
case FieldType.Int32:
case FieldType.Int64:
case FieldType.SInt32:
case FieldType.SInt64:
case FieldType.SFixed32:
case FieldType.SFixed64:
case FieldType.UInt32:
case FieldType.UInt64:
case FieldType.Fixed32:
case FieldType.Fixed64:
// The simple Object.ToString converts using the current culture.
// We want to always use the invariant culture so it's predictable.
IConvertible value = (IConvertible) Descriptor.DefaultValue;
return value.ToString(CultureInfo.InvariantCulture) + suffix;
case FieldType.Bool:
return (bool) Descriptor.DefaultValue ? "true" : "false";
case FieldType.Bytes:
if (!Descriptor.HasDefaultValue) {
return "pb::ByteString.Empty";
}
return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue", DescriptorUtil.GetClassName(Descriptor.ContainingType), Descriptor.Index);
case FieldType.String:
if (AllPrintableAscii(Descriptor.Proto.DefaultValue)) {
// All chars are ASCII and printable. In this case we only
// need to escape quotes and backslashes.
return "\"" + Descriptor.Proto.DefaultValue
.Replace("\\", "\\\\")
.Replace("'", "\\'")
.Replace("\"", "\\\"")
+ "\"";
}
return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue", DescriptorUtil.GetClassName(Descriptor.ContainingType), Descriptor.Index);
case FieldType.Enum:
return TypeName + "." + ((EnumValueDescriptor) Descriptor.DefaultValue).Name;
case FieldType.Message:
case FieldType.Group:
return TypeName + ".DefaultInstance";
default:
throw new InvalidOperationException("Invalid field descriptor type");
}
}
}
/// <summary>
/// Usually the same as CapitalizedName, except when the enclosing type has the same name,
/// in which case an underscore is appended.
/// </summary>
protected string PropertyName {
get {
string ret = CapitalizedName;
if (ret == Descriptor.ContainingType.Name) {
ret += "_";
}
return ret;
}
}
protected string CapitalizedName {
get { return Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(Descriptor)); }
}
protected string Name {
get { return Helpers.UnderscoresToCamelCase(DescriptorUtil.GetFieldName(Descriptor)); }
}
protected int Number {
get { return Descriptor.FieldNumber; }
}
protected string TypeName {
get {
switch (Descriptor.FieldType) {
case FieldType.Enum:
return DescriptorUtil.GetClassName(Descriptor.EnumType);
case FieldType.Message:
case FieldType.Group:
return DescriptorUtil.GetClassName(Descriptor.MessageType);
default:
return DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
}
}
}
protected string MessageOrGroup {
get { return Descriptor.FieldType == FieldType.Group ? "Group" : "Message"; }
}
/// <summary>
/// Returns the type name as used in CodedInputStream method names: SFixed32, UInt32 etc.
/// </summary>
protected string CapitalizedTypeName {
get {
// Our enum names match perfectly. How serendipitous.
return Descriptor.FieldType.ToString();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.DescriptorProtos;
using System.IO;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Code generator for protocol buffers. Only C# is supported at the moment.
/// </summary>
public sealed class Generator {
readonly GeneratorOptions options;
private Generator(GeneratorOptions options) {
options.Validate();
this.options = options;
}
/// <summary>
/// Returns a generator configured with the specified options.
/// </summary>
public static Generator CreateGenerator(GeneratorOptions options) {
return new Generator(options);
}
public void Generate() {
foreach (string inputFile in options.InputFiles) {
FileDescriptorSet descriptorProtos;
ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
extensionRegistry.Add(CSharpOptions.CSharpUmbrellaClassname);
extensionRegistry.Add(CSharpOptions.CSharpMultipleFiles);
extensionRegistry.Add(CSharpOptions.CSharpNamespace);
extensionRegistry.Add(CSharpOptions.CSharpNestClasses);
extensionRegistry.Add(CSharpOptions.CSharpPublicClasses);
using (Stream inputStream = File.OpenRead(inputFile)) {
descriptorProtos = FileDescriptorSet.ParseFrom(inputStream, extensionRegistry);
}
IList<FileDescriptor> descriptors = ConvertDescriptors(descriptorProtos);
foreach (FileDescriptor descriptor in descriptors) {
Generate(descriptor);
}
}
}
/// <summary>
/// Generates code for a particular file. All dependencies must
/// already have been resolved.
/// </summary>
private void Generate(FileDescriptor descriptor) {
string umbrellaClass = DescriptorUtil.GetUmbrellaClassName(descriptor);
string ns = DescriptorUtil.GetNamespace(descriptor);
using (TextWriter textWriter = File.CreateText(Path.Combine(options.OutputDirectory, umbrellaClass + ".cs"))) {
TextGenerator writer = new TextGenerator(textWriter);
UmbrellaClassGenerator ucg = new UmbrellaClassGenerator(descriptor);
ucg.Generate(writer);
/*
GenerateSiblings(umbrellaSource, descriptor, descriptor.MessageTypes);
GenerateSiblings(umbrellaSource, descriptor, descriptor.EnumTypes);
GenerateSiblings(umbrellaSource, descriptor, descriptor.Services);*/
}
}
private static void GenerateSiblings<T>(SourceFileGenerator parentSourceGenerator, FileDescriptor file, IEnumerable<T> siblings)
where T : IDescriptor {
}
/// <summary>
/// Resolves any dependencies and converts FileDescriptorProtos into FileDescriptors.
/// The list returned is in the same order as the protos are listed in the descriptor set.
/// Note: this method is internal rather than private to allow testing.
/// </summary>
/// <exception cref="DependencyResolutionException">Not all dependencies could be resolved.</exception>
internal static IList<FileDescriptor> ConvertDescriptors(FileDescriptorSet descriptorProtos) {
// Simple strategy: Keep going through the list of protos to convert, only doing ones where
// we've already converted all the dependencies, until we get to a stalemate
IList<FileDescriptorProto> fileList = descriptorProtos.FileList;
FileDescriptor[] converted = new FileDescriptor[fileList.Count];
Dictionary<string, FileDescriptor> convertedMap = new Dictionary<string, FileDescriptor>();
int totalConverted = 0;
bool madeProgress = true;
while (madeProgress && totalConverted < converted.Length) {
madeProgress = false;
for (int i = 0; i < converted.Length; i++) {
if (converted[i] != null) {
// Already done this one
continue;
}
FileDescriptorProto candidate = fileList[i];
FileDescriptor[] dependencies = new FileDescriptor[candidate.DependencyList.Count];
bool foundAllDependencies = true;
for (int j = 0; j < dependencies.Length; j++) {
if (!convertedMap.TryGetValue(candidate.DependencyList[j], out dependencies[j])) {
foundAllDependencies = false;
break;
}
}
if (!foundAllDependencies) {
continue;
}
madeProgress = true;
totalConverted++;
converted[i] = FileDescriptor.BuildFrom(candidate, dependencies);
convertedMap[candidate.Name] = converted[i];
}
}
if (!madeProgress) {
StringBuilder remaining = new StringBuilder();
for (int i = 0; i < converted.Length; i++) {
if (converted[i] == null) {
if (remaining.Length != 0) {
remaining.Append(", ");
}
FileDescriptorProto failure = fileList[i];
remaining.Append(failure.Name);
remaining.Append(":");
foreach (string dependency in failure.DependencyList) {
if (!convertedMap.ContainsKey(dependency)) {
remaining.Append(" ");
remaining.Append(dependency);
}
}
remaining.Append(";");
}
}
throw new DependencyResolutionException("Unable to resolve all dependencies: " + remaining);
}
return Lists.AsReadOnly(converted);
}
}
}
using System.Collections.Generic;
using System.IO;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// All the configuration required for the generator - where to generate
/// output files, the location of input files etc. While this isn't immutable
/// in practice, the contents shouldn't be changed after being passed to
/// the generator.
/// </summary>
public sealed class GeneratorOptions {
public string OutputDirectory { get; set; }
public IList<string> InputFiles { get; set; }
/// <summary>
/// Attempts to validate the options, but doesn't throw an exception if they're invalid.
/// Instead, when this method returns false, the output variable will contain a collection
/// of reasons for the validation failure.
/// </summary>
/// <param name="reasons">Variable to receive a list of reasons in case of validation failure.</param>
/// <returns>true if the options are valid; false otherwise</returns>
public bool TryValidate(out IList<string> reasons) {
List<string> tmpReasons = new List<string>();
// Output directory validation
if (string.IsNullOrEmpty(OutputDirectory)) {
tmpReasons.Add("No output directory specified");
} else {
if (!Directory.Exists(OutputDirectory)) {
tmpReasons.Add("Specified output directory (" + OutputDirectory + " doesn't exist.");
}
}
// Input file validation (just in terms of presence)
if (InputFiles == null || InputFiles.Count == 0) {
tmpReasons.Add("No input files specified");
} else {
foreach (string input in InputFiles) {
FileInfo fi = new FileInfo(input);
if (!fi.Exists) {
tmpReasons.Add("Input file " + input + " doesn't exist.");
}
}
}
if (tmpReasons.Count != 0) {
reasons = tmpReasons;
return false;
}
reasons = null;
return true;
}
/// <summary>
/// Validates that all the options have been set and are valid,
/// throwing an exception if they haven't.
/// </summary>
/// <exception cref="InvalidOptionsException">The options are invalid.</exception>
public void Validate() {
IList<string> reasons;
if (!TryValidate(out reasons)) {
throw new InvalidOptionsException(reasons);
}
}
}
}
using System;
using System.Text;
using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Helpers to resolve class names etc.
/// </summary>
internal static class Helpers {
internal static string UnderscoresToPascalCase(string input) {
return UnderscoresToPascalOrCamelCase(input, true);
}
internal static string UnderscoresToCamelCase(string input) {
return UnderscoresToPascalOrCamelCase(input, false);
}
internal static void WriteNamespaces(TextGenerator writer) {
writer.WriteLine("using pb = global::Google.ProtocolBuffers;");
writer.WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;");
writer.WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;");
writer.WriteLine("using scg = global::System.Collections.Generic;");
}
/// <summary>
/// Converts a string to Pascal or Camel case. The first letter is capitalized or
/// lower-cased depending on <paramref name="pascal"/> is true.
/// After the first letter, any punctuation is removed but triggers capitalization
/// of the next letter. Digits are preserved but trigger capitalization of the next
/// letter.
/// All capitalisation is done in the invariant culture.
/// </summary>
private static string UnderscoresToPascalOrCamelCase(string input, bool pascal) {
StringBuilder result = new StringBuilder();
bool capitaliseNext = pascal;
for (int i=0; i < input.Length; i++) {
char c = input[i];
if ('a' <= c && c <= 'z') {
if (capitaliseNext) {
result.Append(char.ToUpperInvariant(c));
} else {
result.Append(c);
}
capitaliseNext = false;
} else if ('A' <= c && c <= 'Z') {
if (i == 0 && !pascal) {
// Force first letter to lower-case unless explicitly told to
// capitalize it.
result.Append(char.ToLowerInvariant(c));
} else {
// Capital letters after the first are left as-is.
result.Append(c);
}
capitaliseNext = false;
} else if ('0' <= c && c <= '9') {
result.Append(c);
capitaliseNext = true;
} else {
capitaliseNext = true;
}
}
return result.ToString();
}
/// <summary>
/// Attempts to strip a suffix from a string, returning whether
/// or not the suffix was actually present.
/// </summary>
internal static bool StripSuffix(ref string text, string suffix) {
if (text.EndsWith(suffix)) {
text = text.Substring(0, text.Length - suffix.Length);
return true;
}
return false;
}
}
}
namespace Google.ProtocolBuffers.ProtoGen {
internal interface IFieldSourceGenerator {
void GenerateMembers(TextGenerator writer);
void GenerateBuilderMembers(TextGenerator writer);
void GenerateMergingCode(TextGenerator writer);
void GenerateBuildingCode(TextGenerator writer);
void GenerateParsingCode(TextGenerator writer);
void GenerateSerializationCode(TextGenerator writer);
void GenerateSerializedSizeCode(TextGenerator writer);
}
}
namespace Google.ProtocolBuffers.ProtoGen {
internal interface ISourceGenerator {
void Generate(TextGenerator writer);
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Exception thrown to indicate that the options passed were invalid.
/// </summary>
public sealed class InvalidOptionsException : Exception {
private readonly IList<string> reasons;
/// <summary>
/// An immutable list of reasons why the options were invalid.
/// </summary>
public IList<string> Reasons {
get { return reasons; }
}
public InvalidOptionsException(IList<string> reasons)
: base(BuildMessage(reasons)) {
this.reasons = Lists.AsReadOnly(reasons);
}
private static string BuildMessage(IEnumerable<string> reasons) {
StringBuilder builder = new StringBuilder("Invalid options:");
builder.AppendLine();
foreach (string reason in reasons) {
builder.Append(" ");
builder.AppendLine(reason);
}
return builder.ToString();
}
}
}
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class MessageFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
internal MessageFieldGenerator(FieldDescriptor descriptor)
: base(descriptor) {
}
public void GenerateMembers(TextGenerator writer) {
writer.WriteLine("private bool has{0};", CapitalizedName);
writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
writer.WriteLine("public bool Has{0} {{", CapitalizedName);
writer.WriteLine(" get {{ return has{0}; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} {1} {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return {0}_; }}", Name);
writer.WriteLine("}");
}
public void GenerateBuilderMembers(TextGenerator writer) {
writer.WriteLine("public bool Has{0} {{", CapitalizedName);
writer.WriteLine(" get {{ return result.Has{0}; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} {1} {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return result.{0}; }}", CapitalizedName);
writer.WriteLine(" set {{ Set{0}(value); }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public Builder Set{0}({1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.has{0} = true;", CapitalizedName);
writer.WriteLine(" result.{0}_ = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Set{0}({1}.Builder builderForValue) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.has{0} = true;", CapitalizedName);
writer.WriteLine(" result.{0}_ = builderForValue.Build();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Merge{0}({1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" if (result.Has{0} &&", CapitalizedName);
writer.WriteLine(" result.{0}_ != {1}) {{", Name, DefaultValue);
writer.WriteLine(" result.{0}_ = {1}.CreateBuilder(result.{0}_).MergeFrom(value).BuildPartial();", Name, TypeName);
writer.WriteLine(" } else {");
writer.WriteLine(" result.{0}_ = value;", Name);
writer.WriteLine(" }");
writer.WriteLine(" result.has{0} = true;", CapitalizedName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Clear{0}() {{", CapitalizedName);
writer.WriteLine(" result.has{0} = false;", CapitalizedName);
writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
writer.WriteLine(" return this;");
writer.WriteLine("}");
}
public void GenerateMergingCode(TextGenerator writer) {
writer.WriteLine("if (other.Has{0}) {{", CapitalizedName);
writer.WriteLine(" Merge{0}(other.{0});", CapitalizedName);
writer.WriteLine("}");
}
public void GenerateBuildingCode(TextGenerator writer) {
// Nothing to do for singular fields
}
public void GenerateParsingCode(TextGenerator writer) {
writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
writer.WriteLine("if (Has{0}) {{", CapitalizedName);
writer.WriteLine(" subBuilder.MergeFrom({0});", CapitalizedName);
writer.WriteLine("}");
if (Descriptor.FieldType == FieldType.Group) {
writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
} else {
writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
}
writer.WriteLine("{0} = subBuilder.BuildPartial();", CapitalizedName);
}
public void GenerateSerializationCode(TextGenerator writer) {
writer.WriteLine("if (Has{0}) {{", CapitalizedName);
writer.WriteLine(" output.Write{0}({1}, {2});", MessageOrGroup, Number, CapitalizedName);
writer.WriteLine("}");
}
public void GenerateSerializedSizeCode(TextGenerator writer) {
writer.WriteLine("if (Has{0}) {{", CapitalizedName);
writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, {2});",
MessageOrGroup, Number, CapitalizedName);
writer.WriteLine("}");
}
}
}
This diff is collapsed.
using System;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
// TODO(jonskeet): Refactor this. There's loads of common code here.
internal class PrimitiveFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
internal PrimitiveFieldGenerator(FieldDescriptor descriptor)
: base(descriptor) {
}
public void GenerateMembers(TextGenerator writer) {
writer.WriteLine("private bool has{0};", CapitalizedName);
writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
writer.WriteLine("public bool Has{0} {{", CapitalizedName);
writer.WriteLine(" get {{ return has{0}; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
writer.WriteLine(" get {{ return {0}_; }}", Name);
writer.WriteLine("}");
}
public void GenerateBuilderMembers(TextGenerator writer) {
writer.WriteLine("public bool Has{0} {{", CapitalizedName);
writer.WriteLine(" get {{ return result.Has{0}; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
writer.WriteLine(" set {{ Set{0}(value); }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public Builder Set{0}({1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.has{0} = true;", CapitalizedName);
writer.WriteLine(" result.{0}_ = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Clear{0}() {{", CapitalizedName);
writer.WriteLine(" result.has{0} = false;", CapitalizedName);
writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
writer.WriteLine(" return this;");
writer.WriteLine("}");
}
public void GenerateMergingCode(TextGenerator writer) {
writer.WriteLine("if (other.Has{0}) {{", CapitalizedName);
writer.WriteLine(" {0} = other.{0};", PropertyName);
writer.WriteLine("}");
}
public void GenerateBuildingCode(TextGenerator writer) {
// Nothing to do here for primitive types
}
public void GenerateParsingCode(TextGenerator writer) {
writer.WriteLine("{0} = input.Read{1}();", PropertyName, CapitalizedTypeName);
}
public void GenerateSerializationCode(TextGenerator writer) {
writer.WriteLine("if (Has{0}) {{", CapitalizedName);
writer.WriteLine(" output.Write{0}({1}, {2});", CapitalizedTypeName, Number, PropertyName);
writer.WriteLine("}");
}
public void GenerateSerializedSizeCode(TextGenerator writer) {
writer.WriteLine("if (Has{0}) {{", CapitalizedName);
writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, {2});",
CapitalizedTypeName, Number, PropertyName);
writer.WriteLine("}");
}
}
}
using System;
using System.Collections.Generic;
using Google.ProtocolBuffers.DescriptorProtos;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Entry point for the Protocol Buffers generator.
/// </summary>
class Program {
static int Main(string[] args) {
try {
// Hack to make sure everything's initialized
DescriptorProtoFile.Descriptor.ToString();
GeneratorOptions options = ParseCommandLineArguments(args);
IList<string> validationFailures;
if (!options.TryValidate(out validationFailures)) {
// We've already got the message-building logic in the exception...
InvalidOptionsException exception = new InvalidOptionsException(validationFailures);
Console.WriteLine(exception.Message);
return 1;
}
Generator generator = Generator.CreateGenerator(options);
generator.Generate();
return 0;
} catch (Exception e) {
Console.Error.WriteLine("Error: {0}", e.Message);
Console.Error.WriteLine();
Console.Error.WriteLine("Detailed exception information: {0}", e);
return 1;
}
}
private static GeneratorOptions ParseCommandLineArguments(string[] args) {
GeneratorOptions options = new GeneratorOptions();
//string baseDir = "c:\\Users\\Jon\\Documents\\Visual Studio 2008\\Projects\\ProtocolBuffers";
//options.OutputDirectory = baseDir + "\\tmp";
//options.InputFiles = new[] { baseDir + "\\protos\\nwind-solo.protobin" };
options.OutputDirectory = ".";
options.InputFiles = args;
return options;
}
}
}
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ProtoGen")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProtoGen")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7101763b-7a38-41be-87f5-7ede4c554509")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("Google.ProtocolBuffers.ProtoGen.Test,PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000100cf43741ffc3e65" +
"c85707245e144e90f1bb82f20d1b1555846008d4d5d5c9270a980350dcb1ddd40fcdde13c2780c" +
"75c9057123daa5613cb6551e2b8bd2254e8f84b3893369869e5119b752442aef7156c4defc489b" +
"96c44ff801fe8d94199e048f8ff414813c9c811a029bcd697040700dc66982539e9b368cb5e725" +
"feed60f2")]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{250ADE34-82FD-4BAE-86D5-985FBE589C4A}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Google.ProtocolBuffers.ProtoGen</RootNamespace>
<AssemblyName>ProtoGen</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkSubset>
</TargetFrameworkSubset>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.ProtoGen.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="DescriptorUtil.cs" />
<Compile Include="EnumFieldGenerator.cs" />
<Compile Include="EnumGenerator.cs" />
<Compile Include="ExtensionGenerator.cs" />
<Compile Include="FieldGeneratorBase.cs" />
<Compile Include="IFieldSourceGenerator.cs" />
<Compile Include="ISourceGenerator.cs" />
<Compile Include="MessageFieldGenerator.cs" />
<Compile Include="MessageGenerator.cs" />
<Compile Include="PrimitiveFieldGenerator.cs" />
<Compile Include="RepeatedEnumFieldGenerator.cs" />
<Compile Include="RepeatedMessageFieldGenerator.cs" />
<Compile Include="RepeatedPrimitiveFieldGenerator.cs" />
<Compile Include="ServiceGenerator.cs" />
<Compile Include="SourceFileGenerator.cs" />
<Compile Include="DependencyResolutionException.cs" />
<Compile Include="Generator.cs" />
<Compile Include="GeneratorOptions.cs" />
<Compile Include="Helpers.cs" />
<Compile Include="InvalidOptionsException.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SourceGeneratorBase.cs" />
<Compile Include="SourceGenerators.cs" />
<Compile Include="UmbrellaClassGenerator.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="Properties\Google.ProtocolBuffers.ProtoGen.snk" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">
<Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
<Name>ProtocolBuffers</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class RepeatedEnumFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
internal RepeatedEnumFieldGenerator(FieldDescriptor descriptor)
: base(descriptor) {
}
public void GenerateMembers(TextGenerator writer) {
writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
writer.WriteLine("}");
// TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
writer.WriteLine("public int {0}Count {{", CapitalizedName);
writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
writer.WriteLine("}");
writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, CapitalizedName);
writer.WriteLine(" return {0}_[index];", Name);
writer.WriteLine("}");
}
public void GenerateBuilderMembers(TextGenerator writer) {
// Note: We can return the original list here, because we make it unmodifiable when we build
writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return result.{0}_; }}", Name);
writer.WriteLine("}");
writer.WriteLine("public int {0}Count {{", CapitalizedName);
writer.WriteLine(" get {{ return result.{0}Count; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, CapitalizedName);
writer.WriteLine(" return result.Get{0}(index);", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_[index] = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Add{0}({1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", CapitalizedName, TypeName);
writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Clear{0}() {{", CapitalizedName);
writer.WriteLine(" result.{0}_.Clear();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
}
public void GenerateMergingCode(TextGenerator writer) {
writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
writer.WriteLine("}");
}
public void GenerateBuildingCode(TextGenerator writer) {
writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
}
public void GenerateParsingCode(TextGenerator writer) {
// TODO(jonskeet): Make a more efficient way of doing this
writer.WriteLine("int rawValue = input.ReadEnum();");
writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
writer.WriteLine(" unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
writer.WriteLine("} else {");
writer.WriteLine(" Add{0}(({1}) rawValue);", CapitalizedName, TypeName);
writer.WriteLine("}");
}
public void GenerateSerializationCode(TextGenerator writer) {
writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, CapitalizedName);
writer.WriteLine(" output.WriteEnum({0}, (int) element);", Number);
writer.WriteLine("}");
}
public void GenerateSerializedSizeCode(TextGenerator writer) {
writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, CapitalizedName);
writer.WriteLine(" size += pb::CodedOutputStream.ComputeEnumSize({0}, (int) element);", Number);
writer.WriteLine("}");
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class RepeatedMessageFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
internal RepeatedMessageFieldGenerator(FieldDescriptor descriptor)
: base(descriptor) {
}
public void GenerateMembers(TextGenerator writer) {
writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return {0}_; }}", Name);
writer.WriteLine("}");
// TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
writer.WriteLine("public int {0}Count {{", CapitalizedName);
writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
writer.WriteLine("}");
writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, CapitalizedName);
writer.WriteLine(" return {0}_[index];", Name);
writer.WriteLine("}");
}
public void GenerateBuilderMembers(TextGenerator writer) {
// Note: We can return the original list here, because we make it unmodifiable when we build
writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return result.{0}_; }}", Name);
writer.WriteLine("}");
writer.WriteLine("public int {0}Count {{", CapitalizedName);
writer.WriteLine(" get {{ return result.{0}Count; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, CapitalizedName);
writer.WriteLine(" return result.Get{0}(index);", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_[index] = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
// Extra overload for builder (just on messages)
writer.WriteLine("public Builder Set{0}(int index, {1}.Builder builderForValue) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_[index] = builderForValue.Build();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Add{0}({1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
// Extra overload for builder (just on messages)
writer.WriteLine("public Builder Add{0}({1}.Builder builderForValue) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_.Add(builderForValue.Build());", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", CapitalizedName, TypeName);
writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Clear{0}() {{", CapitalizedName);
writer.WriteLine(" result.{0}_.Clear();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
}
public void GenerateMergingCode(TextGenerator writer) {
writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
writer.WriteLine("}");
}
public void GenerateBuildingCode(TextGenerator writer) {
writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
}
public void GenerateParsingCode(TextGenerator writer) {
writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
if (Descriptor.FieldType == FieldType.Group) {
writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
} else {
writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
}
writer.WriteLine("Add{0}(subBuilder.BuildPartial());", CapitalizedName);
}
public void GenerateSerializationCode(TextGenerator writer) {
writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, CapitalizedName);
writer.WriteLine(" output.Write{0}({1}, element);", MessageOrGroup, Number);
writer.WriteLine("}");
}
public void GenerateSerializedSizeCode(TextGenerator writer) {
writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, CapitalizedName);
writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, element);", MessageOrGroup, Number);
writer.WriteLine("}");
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class RepeatedPrimitiveFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
internal RepeatedPrimitiveFieldGenerator(FieldDescriptor descriptor)
: base(descriptor) {
}
public void GenerateMembers(TextGenerator writer) {
writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
writer.WriteLine("}");
// TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
writer.WriteLine("public int {0}Count {{", CapitalizedName);
writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
writer.WriteLine("}");
writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, CapitalizedName);
writer.WriteLine(" return {0}_[index];", Name);
writer.WriteLine("}");
}
public void GenerateBuilderMembers(TextGenerator writer) {
// Note: We can return the original list here, because we make it unmodifiable when we build
writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, CapitalizedName);
writer.WriteLine(" get {{ return result.{0}_; }}", Name);
writer.WriteLine("}");
writer.WriteLine("public int {0}Count {{", CapitalizedName);
writer.WriteLine(" get {{ return result.{0}Count; }}", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, CapitalizedName);
writer.WriteLine(" return result.Get{0}(index);", CapitalizedName);
writer.WriteLine("}");
writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_[index] = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Add{0}({1} value) {{", CapitalizedName, TypeName);
writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", CapitalizedName, TypeName);
writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("public Builder Clear{0}() {{", CapitalizedName);
writer.WriteLine(" result.{0}_.Clear();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
}
public void GenerateMergingCode(TextGenerator writer) {
writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
writer.WriteLine("}");
}
public void GenerateBuildingCode(TextGenerator writer) {
writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
}
public void GenerateParsingCode(TextGenerator writer) {
writer.WriteLine("Add{0}(input.Read{1}());", CapitalizedName, CapitalizedTypeName);
}
public void GenerateSerializationCode(TextGenerator writer) {
writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, CapitalizedName);
writer.WriteLine(" output.Write{0}({1}, element);", CapitalizedTypeName, Number);
writer.WriteLine("}");
}
public void GenerateSerializedSizeCode(TextGenerator writer) {
writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, CapitalizedName);
writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, element);", CapitalizedTypeName, Number);
writer.WriteLine("}");
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal class ServiceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator {
private enum RequestOrResponse {
Request,
Response
}
internal ServiceGenerator(ServiceDescriptor descriptor)
: base(descriptor) {
}
public void Generate(TextGenerator writer) {
writer.WriteLine("{0} abstract class {1} : pb::IService {{", ClassAccessLevel, Descriptor.Name);
writer.Indent();
foreach (MethodDescriptor method in Descriptor.Methods) {
writer.WriteLine("{0} abstract void {1}(", ClassAccessLevel, Helpers.UnderscoresToPascalCase(method.Name));
writer.WriteLine(" pb::IRpcController controller,");
writer.WriteLine(" {0} request,", DescriptorUtil.GetClassName(method.InputType));
writer.WriteLine(" global::System.Action<{0}> done);", DescriptorUtil.GetClassName(method.OutputType));
}
// Generate Descriptor and DescriptorForType.
writer.WriteLine();
writer.WriteLine("{0} static pbd::ServiceDescriptor Descriptor {{", ClassAccessLevel);
writer.WriteLine(" get {{ return {0}.Descriptor.Services[{1}]; }}",
DescriptorUtil.GetUmbrellaClassName(Descriptor.File), Descriptor.Index);
writer.WriteLine("}");
writer.WriteLine("{0} pbd::ServiceDescriptor DescriptorForType {{", ClassAccessLevel);
writer.WriteLine(" get { return Descriptor; }");
writer.WriteLine("}");
GenerateCallMethod(writer);
GenerateGetPrototype(RequestOrResponse.Request, writer);
GenerateGetPrototype(RequestOrResponse.Response, writer);
GenerateStub(writer);
writer.Outdent();
writer.WriteLine("}");
}
private void GenerateCallMethod(TextGenerator writer) {
writer.WriteLine();
writer.WriteLine("public void CallMethod(", ClassAccessLevel);
writer.WriteLine(" pbd::MethodDescriptor method,");
writer.WriteLine(" pb::IRpcController controller,");
writer.WriteLine(" pb::IMessage request,");
writer.WriteLine(" global::System.Action<pb::IMessage> done) {");
writer.Indent();
writer.WriteLine("if (method.Service != Descriptor) {");
writer.WriteLine(" throw new global::System.ArgumentException(");
writer.WriteLine(" \"Service.CallMethod() given method descriptor for wrong service type.\");");
writer.WriteLine("}");
writer.WriteLine("switch(method.Index) {");
writer.Indent();
foreach (MethodDescriptor method in Descriptor.Methods) {
writer.WriteLine("case {0}:", method.Index);
writer.WriteLine(" this.{0}(controller, ({1}) request,",
Helpers.UnderscoresToPascalCase(method.Name), DescriptorUtil.GetClassName(method.InputType));
writer.WriteLine(" pb::RpcUtil.SpecializeCallback<{0}>(", DescriptorUtil.GetClassName(method.OutputType));
writer.WriteLine(" done));");
writer.WriteLine(" return;");
}
writer.WriteLine("default:");
writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
writer.Outdent();
writer.WriteLine("}");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
private void GenerateGetPrototype(RequestOrResponse which, TextGenerator writer) {
writer.WriteLine("public pb::IMessage Get{0}Prototype(pbd::MethodDescriptor method) {{", which);
writer.Indent();
writer.WriteLine("if (method.Service != Descriptor) {");
writer.WriteLine(" throw new global::System.ArgumentException(");
writer.WriteLine(" \"Service.Get{0}Prototype() given method descriptor for wrong service type.\");", which);
writer.WriteLine("}");
writer.WriteLine("switch(method.Index) {");
writer.Indent();
foreach (MethodDescriptor method in Descriptor.Methods) {
writer.WriteLine("case {0}:", method.Index);
writer.WriteLine(" return {0}.DefaultInstance;",
DescriptorUtil.GetClassName(which == RequestOrResponse.Request ? method.InputType : method.OutputType));
}
writer.WriteLine("default:");
writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
writer.Outdent();
writer.WriteLine("}");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
private void GenerateStub(TextGenerator writer) {
writer.WriteLine("public static Stub CreateStub(pb::IRpcChannel channel) {");
writer.WriteLine(" return new Stub(channel);");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, DescriptorUtil.GetClassName(Descriptor));
writer.Indent();
writer.WriteLine("internal Stub(pb::IRpcChannel channel) {");
writer.WriteLine(" this.channel = channel;");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("private readonly pb::IRpcChannel channel;");
writer.WriteLine();
writer.WriteLine("public pb::IRpcChannel Channel {");
writer.WriteLine(" get { return channel; }");
writer.WriteLine("}");
foreach (MethodDescriptor method in Descriptor.Methods) {
writer.WriteLine();
writer.WriteLine("public override void {0}(", Helpers.UnderscoresToPascalCase(method.Name));
writer.WriteLine(" pb::IRpcController controller,");
writer.WriteLine(" {0} request,", DescriptorUtil.GetClassName(method.InputType));
writer.WriteLine(" global::System.Action<{0}> done) {{", DescriptorUtil.GetClassName(method.OutputType));
writer.Indent();
writer.WriteLine("channel.CallMethod(Descriptor.Methods[{0}],", method.Index);
writer.WriteLine(" controller, request, {0}.DefaultInstance,", DescriptorUtil.GetClassName(method.OutputType));
writer.WriteLine(" pb::RpcUtil.GeneralizeCallback<{0}, {0}.Builder>(done, {0}.DefaultInstance));",
DescriptorUtil.GetClassName(method.OutputType));
writer.Outdent();
writer.WriteLine("}");
}
writer.Outdent();
writer.WriteLine("}");
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Generator to hold a TextGenerator, generate namespace aliases etc.
/// Each source file created uses one of these, and it can be used to create
/// multiple classes within the same file.
/// </summary>
internal class SourceFileGenerator {
private readonly TextGenerator output;
private SourceFileGenerator(TextWriter writer) {
output = new TextGenerator(writer);
}
/// <summary>
/// Creates a ClassFileGenerator for the given writer, which will be closed
/// when the instance is disposed. The specified namespace is created, if it's non-null.
/// </summary>
internal static SourceFileGenerator ForWriter(TextWriter writer) {
return new SourceFileGenerator(writer);
}
}
}
using System.Collections.Generic;
using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal abstract class SourceGeneratorBase<T> where T : IDescriptor {
private readonly T descriptor;
protected SourceGeneratorBase(T descriptor) {
this.descriptor = descriptor;
}
protected T Descriptor {
get { return descriptor; }
}
protected string ClassAccessLevel {
get {
// Default to public
return !descriptor.File.Options.HasExtension(CSharpOptions.CSharpPublicClasses)
|| descriptor.File.Options.GetExtension(CSharpOptions.CSharpPublicClasses) ? "public" : "internal";
}
}
public bool MultipleFiles {
get { return descriptor.File.Options.GetExtension(CSharpOptions.CSharpMultipleFiles); }
}
protected static void WriteChildren<TChild>(TextGenerator writer, string region, IEnumerable<TChild> children)
where TChild : IDescriptor {
// Copy the set of children; makes access easier
List<TChild> copy = new List<TChild>(children);
if (copy.Count == 0) {
return;
}
if (region != null) {
writer.WriteLine("#region {0}", region);
}
foreach (TChild child in children) {
SourceGenerators.CreateGenerator(child).Generate(writer);
}
if (region != null) {
writer.WriteLine("#endregion");
writer.WriteLine();
}
}
}
}
using System;
using System.Collections.Generic;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
internal static class SourceGenerators {
private static readonly Dictionary<Type, Func<IDescriptor, ISourceGenerator>> GeneratorFactories = new Dictionary<Type, Func<IDescriptor, ISourceGenerator>> {
{ typeof(FileDescriptor), descriptor => new UmbrellaClassGenerator((FileDescriptor) descriptor) },
{ typeof(EnumDescriptor), descriptor => new EnumGenerator((EnumDescriptor) descriptor) },
{ typeof(ServiceDescriptor), descriptor => new ServiceGenerator((ServiceDescriptor) descriptor) },
{ typeof(MessageDescriptor), descriptor => new MessageGenerator((MessageDescriptor) descriptor) },
// For other fields, we have IFieldSourceGenerators.
{ typeof(FieldDescriptor), descriptor => new ExtensionGenerator((FieldDescriptor) descriptor) }
};
public static IFieldSourceGenerator CreateFieldGenerator(FieldDescriptor field) {
switch (field.MappedType) {
case MappedType.Message :
return field.IsRepeated
? (IFieldSourceGenerator) new RepeatedMessageFieldGenerator(field)
: new MessageFieldGenerator(field);
case MappedType.Enum:
return field.IsRepeated
? (IFieldSourceGenerator)new RepeatedEnumFieldGenerator(field)
: new EnumFieldGenerator(field);
default:
return field.IsRepeated
? (IFieldSourceGenerator)new RepeatedPrimitiveFieldGenerator(field)
: new PrimitiveFieldGenerator(field);
}
}
public static ISourceGenerator CreateGenerator<T>(T descriptor) where T : IDescriptor {
Func<IDescriptor, ISourceGenerator> factory;
if (!GeneratorFactories.TryGetValue(typeof(T), out factory)) {
throw new ArgumentException("No generator registered for " + typeof(T).Name);
}
return factory(descriptor);
}
}
}
using System;
using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
/// <summary>
/// Generator for the class describing the .proto file in general,
/// containing things like the message descriptor.
/// </summary>
internal sealed class UmbrellaClassGenerator : SourceGeneratorBase<FileDescriptor>, ISourceGenerator {
internal UmbrellaClassGenerator(FileDescriptor descriptor)
: base(descriptor) {
}
public void Generate(TextGenerator writer) {
WriteIntroduction(writer);
WriteDescriptor(writer);
WriteChildren(writer, "Extensions", Descriptor.Extensions);
writer.WriteLine("#region Static variables");
foreach (MessageDescriptor message in Descriptor.MessageTypes) {
new MessageGenerator(message).GenerateStaticVariables(writer);
}
writer.WriteLine("#endregion");
// The class declaration either gets closed before or after the children are written.
if (!DescriptorUtil.NestClasses(Descriptor)) {
writer.Outdent();
writer.WriteLine("}");
}
WriteChildren(writer, "Enums", Descriptor.EnumTypes);
WriteChildren(writer, "Messages", Descriptor.MessageTypes);
WriteChildren(writer, "Services", Descriptor.Services);
if (DescriptorUtil.NestClasses(Descriptor)) {
writer.Outdent();
writer.WriteLine("}");
}
if (DescriptorUtil.GetNamespace(Descriptor) != "") {
writer.Outdent();
writer.WriteLine("}");
}
}
private void WriteIntroduction(TextGenerator writer) {
writer.WriteLine("// Generated by the protocol buffer compiler. DO NOT EDIT!");
writer.WriteLine();
Helpers.WriteNamespaces(writer);
if (DescriptorUtil.GetNamespace(Descriptor) != "") {
writer.WriteLine("namespace {0} {{", DescriptorUtil.GetNamespace(Descriptor));
writer.Indent();
writer.WriteLine();
}
writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel, DescriptorUtil.GetUmbrellaClassName(Descriptor));
writer.WriteLine();
writer.Indent();
}
private void WriteDescriptor(TextGenerator writer) {
writer.WriteLine("#region Descriptor");
writer.WriteLine("public static pbd::FileDescriptor Descriptor {");
writer.WriteLine(" get { return descriptor; }");
writer.WriteLine("}");
writer.WriteLine("private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(");
writer.WriteLine(" global::System.Convert.FromBase64String(");
writer.Indent();
writer.Indent();
// TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
byte[] bytes = Descriptor.Proto.ToByteArray();
string base64 = Convert.ToBase64String(bytes);
while (base64.Length > 60) {
writer.WriteLine("\"{0}\" + ", base64.Substring(0, 60));
base64 = base64.Substring(60);
}
writer.WriteLine("\"{0}\"),", base64);
writer.WriteLine("new pbd::FileDescriptor[] {");
foreach (FileDescriptor dependency in Descriptor.Dependencies) {
// TODO(jonskeet): The normal code won't work for the bootstrapping descriptor, because we don't get unknown fields :(
if (dependency.Package == "google.protobuf" && dependency.Name.EndsWith("descriptor.proto")) {
writer.WriteLine(" global::" + typeof(DescriptorProtoFile).FullName + ".Descriptor, ");
continue;
}
writer.WriteLine(" {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
}
writer.WriteLine("});");
writer.Outdent();
writer.Outdent();
writer.WriteLine("#endregion");
writer.WriteLine();
}
}
}
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>
This diff is collapsed.
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Text;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
[TestFixture]
public class ByteStringTest {
[Test]
public void EmptyByteStringHasZeroSize() {
Assert.AreEqual(0, ByteString.Empty.Length);
}
[Test]
public void CopyFromStringWithExplicitEncoding() {
ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
Assert.AreEqual(4, bs.Length);
Assert.AreEqual(65, bs[0]);
Assert.AreEqual(0, bs[1]);
Assert.AreEqual(66, bs[2]);
Assert.AreEqual(0, bs[3]);
}
[Test]
public void IsEmptyWhenEmpty() {
Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
}
[Test]
public void IsEmptyWhenNotEmpty() {
Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
}
[Test]
public void CopyFromByteArrayCopiesContents() {
byte[] data = new byte[1];
data[0] = 10;
ByteString bs = ByteString.CopyFrom(data);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void ToByteArrayCopiesContents() {
ByteString bs = ByteString.CopyFromUtf8("Hello");
byte[] data = bs.ToByteArray();
Assert.AreEqual('H', data[0]);
Assert.AreEqual('H', bs[0]);
data[0] = 0;
Assert.AreEqual(0, data[0]);
Assert.AreEqual('H', bs[0]);
}
[Test]
public void CopyFromUtf8UsesUtf8() {
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(0xe2, bs[0]);
Assert.AreEqual(0x82, bs[1]);
Assert.AreEqual(0xac, bs[2]);
}
[Test]
public void CopyFromPortion() {
byte[] data = new byte[]{0, 1, 2, 3, 4, 5, 6};
ByteString bs = ByteString.CopyFrom(data, 2, 3);
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(2, bs[0]);
Assert.AreEqual(3, bs[1]);
}
[Test]
public void ToStringUtf8() {
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual("\u20ac", bs.ToStringUtf8());
}
[Test]
public void ToStringWithExplicitEncoding() {
ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment