First cut at new layout

pull/288/head
Jon Skeet 17 years ago
parent f0589506c9
commit 6803686bc0
  1. 33
      .gitignore
  2. 126
      ProtocolBuffers.build
  3. BIN
      lib/Rhino.Mocks.dll
  4. 4849
      lib/Rhino.Mocks.xml
  5. 15
      lib/nunit-license.txt
  6. BIN
      lib/nunit.framework.dll
  7. 36
      lib/protoc-license.txt
  8. BIN
      lib/protoc.exe
  9. 25
      lib/rhino-license.txt
  10. 16
      protos/google/protobuf/csharp_options.proto
  11. 392
      protos/google/protobuf/descriptor.proto
  12. 473
      protos/google/protobuf/unittest.proto
  13. 277
      protos/google/protobuf/unittest_custom_options.proto
  14. 57
      protos/google/protobuf/unittest_embed_optimize_for.proto
  15. 68
      protos/google/protobuf/unittest_import.proto
  16. 79
      protos/google/protobuf/unittest_mset.proto
  17. 67
      protos/google/protobuf/unittest_optimize_for.proto
  18. 1
      readme.txt
  19. 95
      src/ProtoGen.Test/DependencyResolutionTest.cs
  20. 69
      src/ProtoGen.Test/DescriptorUtilTest.cs
  21. 10
      src/ProtoGen.Test/GeneratorTest.cs
  22. 33
      src/ProtoGen.Test/HelpersTest.cs
  23. 36
      src/ProtoGen.Test/Properties/AssemblyInfo.cs
  24. BIN
      src/ProtoGen.Test/Properties/Google.ProtocolBuffers.ProtoGen.Test.snk
  25. 74
      src/ProtoGen.Test/ProtoGen.Test.csproj
  26. 17
      src/ProtoGen/DependencyResolutionException.cs
  27. 108
      src/ProtoGen/DescriptorUtil.cs
  28. 75
      src/ProtoGen/EnumFieldGenerator.cs
  29. 19
      src/ProtoGen/EnumGenerator.cs
  30. 37
      src/ProtoGen/ExtensionGenerator.cs
  31. 130
      src/ProtoGen/FieldGeneratorBase.cs
  32. 138
      src/ProtoGen/Generator.cs
  33. 69
      src/ProtoGen/GeneratorOptions.cs
  34. 78
      src/ProtoGen/Helpers.cs
  35. 11
      src/ProtoGen/IFieldSourceGenerator.cs
  36. 5
      src/ProtoGen/ISourceGenerator.cs
  37. 36
      src/ProtoGen/InvalidOptionsException.cs
  38. 92
      src/ProtoGen/MessageFieldGenerator.cs
  39. 453
      src/ProtoGen/MessageGenerator.cs
  40. 70
      src/ProtoGen/PrimitiveFieldGenerator.cs
  41. 47
      src/ProtoGen/Program.cs
  42. 42
      src/ProtoGen/Properties/AssemblyInfo.cs
  43. BIN
      src/ProtoGen/Properties/Google.ProtocolBuffers.ProtoGen.snk
  44. 85
      src/ProtoGen/ProtoGen.csproj
  45. 90
      src/ProtoGen/RepeatedEnumFieldGenerator.cs
  46. 100
      src/ProtoGen/RepeatedMessageFieldGenerator.cs
  47. 84
      src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
  48. 138
      src/ProtoGen/ServiceGenerator.cs
  49. 29
      src/ProtoGen/SourceFileGenerator.cs
  50. 50
      src/ProtoGen/SourceGeneratorBase.cs
  51. 42
      src/ProtoGen/SourceGenerators.cs
  52. 96
      src/ProtoGen/UmbrellaClassGenerator.cs
  53. 3
      src/ProtoGen/app.config
  54. 364
      src/ProtocolBuffers.Test/AbstractMessageTest.cs
  55. 98
      src/ProtocolBuffers.Test/ByteStringTest.cs
  56. 376
      src/ProtocolBuffers.Test/CodedInputStreamTest.cs
  57. 239
      src/ProtocolBuffers.Test/CodedOutputStreamTest.cs
  58. 64
      src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs
  59. 274
      src/ProtocolBuffers.Test/DescriptorsTest.cs
  60. 114
      src/ProtocolBuffers.Test/DynamicMessageTest.cs
  61. 291
      src/ProtocolBuffers.Test/GeneratedMessageTest.cs
  62. 23
      src/ProtocolBuffers.Test/MessageStreamIteratorTest.cs
  63. 36
      src/ProtocolBuffers.Test/MessageStreamWriterTest.cs
  64. 299
      src/ProtocolBuffers.Test/MessageTest.cs
  65. 36
      src/ProtocolBuffers.Test/Properties/AssemblyInfo.cs
  66. BIN
      src/ProtocolBuffers.Test/Properties/Google.ProtocolBuffers.Test.snk
  67. 88
      src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  68. 798
      src/ProtocolBuffers.Test/ReflectionTester.cs
  69. 178
      src/ProtocolBuffers.Test/ServiceTest.cs
  70. 2251
      src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs
  71. 324
      src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
  72. 243
      src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
  73. 1284
      src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
  74. 467
      src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs
  75. 11835
      src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
  76. 1370
      src/ProtocolBuffers.Test/TestUtil.cs
  77. 487
      src/ProtocolBuffers.Test/TextFormatTest.cs
  78. 314
      src/ProtocolBuffers.Test/UnknownFieldSetTest.cs
  79. 228
      src/ProtocolBuffers.Test/WireFormatTest.cs
  80. 38
      src/ProtocolBuffers.sln
  81. 222
      src/ProtocolBuffers/AbstractBuilder.cs
  82. 181
      src/ProtocolBuffers/AbstractMessage.cs
  83. 187
      src/ProtocolBuffers/ByteString.cs
  84. 843
      src/ProtocolBuffers/CodedInputStream.cs
  85. 765
      src/ProtocolBuffers/CodedOutputStream.cs
  86. 108
      src/ProtocolBuffers/Collections/Dictionaries.cs
  87. 56
      src/ProtocolBuffers/Collections/Lists.cs
  88. 95
      src/ProtocolBuffers/Collections/PopsicleList.cs
  89. 112
      src/ProtocolBuffers/Collections/ReadOnlyDictionary.cs
  90. 32
      src/ProtocolBuffers/Delegates.cs
  91. 49
      src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
  92. 6131
      src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  93. 36
      src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs
  94. 43
      src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs
  95. 83
      src/ProtocolBuffers/Descriptors/DescriptorBase.cs
  96. 281
      src/ProtocolBuffers/Descriptors/DescriptorPool.cs
  97. 43
      src/ProtocolBuffers/Descriptors/DescriptorUtil.cs
  98. 70
      src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs
  99. 76
      src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
  100. 43
      src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
  101. Some files were not shown because too many files have changed in this diff Show More

33
.gitignore vendored

@ -1,25 +1,14 @@
# Untracked files
csharp/ProtocolBuffers/bin/
csharp/ProtocolBuffers/obj/
csharp/ProtocolBuffers.Test/bin/
csharp/ProtocolBuffers.Test/obj/
csharp/ProtoGen/bin/
csharp/ProtoGen/obj/
csharp/ProtoGen.Test/bin/
csharp/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/
src/ProtocolBuffers/bin/
src/ProtocolBuffers/obj/
src/ProtocolBuffers.Test/bin/
src/ProtocolBuffers.Test/obj/
src/ProtoGen/bin/
src/ProtoGen/obj/
src/ProtoGen.Test/bin/
src/ProtoGen.Test/obj/
tmp/
vsprojects/*
vsprojects/protobuf.sln
benchmark.txt
*.user
*.suo
_ReSharper.*

@ -0,0 +1,126 @@
<?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>

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -0,0 +1,15 @@
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.

Binary file not shown.

@ -0,0 +1,36 @@
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.

Binary file not shown.

@ -0,0 +1,25 @@
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.

@ -0,0 +1,16 @@
// 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;
}

@ -0,0 +1,392 @@
// 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.
//
// The messages in this file describe the definitions found in .proto files.
// A valid .proto file can be translated directly to a FileDescriptorProto
// without any other information (e.g. without reading its imports).
package google.protobuf;
option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos";
// descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping.
option optimize_for = SPEED;
// The protocol compiler can output a FileDescriptorSet containing the .proto
// files it parses.
message FileDescriptorSet {
repeated FileDescriptorProto file = 1;
}
// Describes a complete .proto file.
message FileDescriptorProto {
optional string name = 1; // file name, relative to root of source tree
optional string package = 2; // e.g. "foo", "foo.bar", etc.
// Names of files imported by this file.
repeated string dependency = 3;
// All top-level definitions in this file.
repeated DescriptorProto message_type = 4;
repeated EnumDescriptorProto enum_type = 5;
repeated ServiceDescriptorProto service = 6;
repeated FieldDescriptorProto extension = 7;
optional FileOptions options = 8;
}
// Describes a message type.
message DescriptorProto {
optional string name = 1;
repeated FieldDescriptorProto field = 2;
repeated FieldDescriptorProto extension = 6;
repeated DescriptorProto nested_type = 3;
repeated EnumDescriptorProto enum_type = 4;
message ExtensionRange {
optional int32 start = 1;
optional int32 end = 2;
}
repeated ExtensionRange extension_range = 5;
optional MessageOptions options = 7;
}
// Describes a field within a message.
message FieldDescriptorProto {
enum Type {
// 0 is reserved for errors.
// Order is weird for historical reasons.
TYPE_DOUBLE = 1;
TYPE_FLOAT = 2;
TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers
// take 10 bytes. Use TYPE_SINT64 if negative
// values are likely.
TYPE_UINT64 = 4;
TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers
// take 10 bytes. Use TYPE_SINT32 if negative
// values are likely.
TYPE_FIXED64 = 6;
TYPE_FIXED32 = 7;
TYPE_BOOL = 8;
TYPE_STRING = 9;
TYPE_GROUP = 10; // Tag-delimited aggregate.
TYPE_MESSAGE = 11; // Length-delimited aggregate.
// New in version 2.
TYPE_BYTES = 12;
TYPE_UINT32 = 13;
TYPE_ENUM = 14;
TYPE_SFIXED32 = 15;
TYPE_SFIXED64 = 16;
TYPE_SINT32 = 17; // Uses ZigZag encoding.
TYPE_SINT64 = 18; // Uses ZigZag encoding.
};
enum Label {
// 0 is reserved for errors
LABEL_OPTIONAL = 1;
LABEL_REQUIRED = 2;
LABEL_REPEATED = 3;
// TODO(sanjay): Should we add LABEL_MAP?
};
optional string name = 1;
optional int32 number = 3;
optional Label label = 4;
// If type_name is set, this need not be set. If both this and type_name
// are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
optional Type type = 5;
// For message and enum types, this is the name of the type. If the name
// starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
// rules are used to find the type (i.e. first the nested types within this
// message are searched, then within the parent, on up to the root
// namespace).
optional string type_name = 6;
// For extensions, this is the name of the type being extended. It is
// resolved in the same manner as type_name.
optional string extendee = 2;
// For numeric types, contains the original text representation of the value.
// For booleans, "true" or "false".
// For strings, contains the default text contents (not escaped in any way).
// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
// TODO(kenton): Base-64 encode?
optional string default_value = 7;
optional FieldOptions options = 8;
}
// Describes an enum type.
message EnumDescriptorProto {
optional string name = 1;
repeated EnumValueDescriptorProto value = 2;
optional EnumOptions options = 3;
}
// Describes a value within an enum.
message EnumValueDescriptorProto {
optional string name = 1;
optional int32 number = 2;
optional EnumValueOptions options = 3;
}
// Describes a service.
message ServiceDescriptorProto {
optional string name = 1;
repeated MethodDescriptorProto method = 2;
optional ServiceOptions options = 3;
}
// Describes a method of a service.
message MethodDescriptorProto {
optional string name = 1;
// Input and output type names. These are resolved in the same way as
// FieldDescriptorProto.type_name, but must refer to a message type.
optional string input_type = 2;
optional string output_type = 3;
optional MethodOptions options = 4;
}
// ===================================================================
// Options
// Each of the definitions above may have "options" attached. These are
// just annotations which may cause code to be generated slightly differently
// or may contain hints for code that manipulates protocol messages.
//
// Clients may define custom options as extensions of the *Options messages.
// These extensions may not yet be known at parsing time, so the parser cannot
// store the values in them. Instead it stores them in a field in the *Options
// message called uninterpreted_option. This field must have the same name
// across all *Options messages. We then use this field to populate the
// extensions when we build a descriptor, at which point all protos have been
// parsed and so all extensions are known.
//
// Extension numbers for custom options may be chosen as follows:
// * For options which will only be used within a single application or
// organization, or for experimental options, use field numbers 50000
// through 99999. It is up to you to ensure that you do not use the
// same number for multiple options.
// * For options which will be published and used publicly by multiple
// independent entities, e-mail kenton@google.com to reserve extension
// numbers. Simply tell me how many you need and I'll send you back a
// set of numbers to use -- there's no need to explain how you intend to
// use them. If this turns out to be popular, a web service will be set up
// to automatically assign option numbers.
message FileOptions {
// Sets the Java package where classes generated from this .proto will be
// placed. By default, the proto package is used, but this is often
// inappropriate because proto packages do not normally start with backwards
// domain names.
optional string java_package = 1;
// If set, all the classes from the .proto file are wrapped in a single
// outer class with the given name. This applies to both Proto1
// (equivalent to the old "--one_java_file" option) and Proto2 (where
// a .proto always translates to a single class, but you may want to
// explicitly choose the class name).
optional string java_outer_classname = 8;
// If set true, then the Java code generator will generate a separate .java
// file for each top-level message, enum, and service defined in the .proto
// file. Thus, these types will *not* be nested inside the outer class
// named by java_outer_classname. However, the outer class will still be
// generated to contain the file's getDescriptor() method as well as any
// top-level extensions defined in the file.
optional bool java_multiple_files = 10 [default=false];
// Generated classes can be optimized for speed or code size.
enum OptimizeMode {
SPEED = 1; // Generate complete code for parsing, serialization, etc.
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
}
optional OptimizeMode optimize_for = 9 [default=CODE_SIZE];
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message MessageOptions {
// Set true to use the old proto1 MessageSet wire format for extensions.
// This is provided for backwards-compatibility with the MessageSet wire
// format. You should not use this for any other reason: It's less
// efficient, has fewer features, and is more complicated.
//
// The message must be defined exactly as follows:
// message Foo {
// option message_set_wire_format = true;
// extensions 4 to max;
// }
// Note that the message cannot have any defined fields; MessageSets only
// have extensions.
//
// All extensions of your type must be singular messages; e.g. they cannot
// be int32s, enums, or repeated messages.
//
// Because this is an option, the above two restrictions are not enforced by
// the protocol compiler.
optional bool message_set_wire_format = 1 [default=false];
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message FieldOptions {
// The ctype option instructs the C++ code generator to use a different
// representation of the field than it normally would. See the specific
// options below. This option is not yet implemented in the open source
// release -- sorry, we'll try to include it in a future version!
optional CType ctype = 1;
enum CType {
CORD = 1;
STRING_PIECE = 2;
}
// EXPERIMENTAL. DO NOT USE.
// For "map" fields, the name of the field in the enclosed type that
// is the key for this map. For example, suppose we have:
// message Item {
// required string name = 1;
// required string value = 2;
// }
// message Config {
// repeated Item items = 1 [experimental_map_key="name"];
// }
// In this situation, the map key for Item will be set to "name".
// TODO: Fully-implement this, then remove the "experimental_" prefix.
optional string experimental_map_key = 9;
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message EnumOptions {
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message EnumValueOptions {
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message ServiceOptions {
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
// framework. We apologize for hoarding these numbers to ourselves, but
// we were already using them long before we decided to release Protocol
// Buffers.
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message MethodOptions {
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
// framework. We apologize for hoarding these numbers to ourselves, but
// we were already using them long before we decided to release Protocol
// Buffers.
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
// A message representing a option the parser does not recognize. This only
// appears in options protos created by the compiler::Parser class.
// DescriptorPool resolves these when building Descriptor objects. Therefore,
// options protos in descriptor objects (e.g. returned by Descriptor::options(),
// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
// in them.
message UninterpretedOption {
// The name of the uninterpreted option. Each string represents a segment in
// a dot-separated name. is_extension is true iff a segment represents an
// extension (denoted with parentheses in options specs in .proto files).
// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
// "foo.(bar.baz).qux".
message NamePart {
required string name_part = 1;
required bool is_extension = 2;
}
repeated NamePart name = 2;
// The value of the uninterpreted option, in whatever type the tokenizer
// identified it as during parsing. Exactly one of these should be set.
optional string identifier_value = 3;
optional uint64 positive_int_value = 4;
optional int64 negative_int_value = 5;
optional double double_value = 6;
optional bytes string_value = 7;
}

@ -0,0 +1,473 @@
// 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) = "UnitTestProtoFile";
// 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 we will use for unit testing.
import "google/protobuf/unittest_import.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.
// In test_util.h we do "using namespace unittest = protobuf_unittest".
package protobuf_unittest;
// Protos optimized for SPEED use a strict superset of the generated code
// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
// tests for speed unless explicitly testing code size optimization.
option optimize_for = SPEED;
option java_outer_classname = "UnittestProto";
// This proto includes every type of field in both singular and repeated
// forms.
message TestAllTypes {
message NestedMessage {
// The field name "b" fails to compile in proto1 because it conflicts with
// a local variable named "b" in one of the generated methods. Doh.
// This file needs to compile in proto1 to test backwards-compatibility.
optional int32 bb = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
// Singular
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional group OptionalGroup = 16 {
optional int32 a = 17;
}
optional NestedMessage optional_nested_message = 18;
optional ForeignMessage optional_foreign_message = 19;
optional protobuf_unittest_import.ImportMessage optional_import_message = 20;
optional NestedEnum optional_nested_enum = 21;
optional ForeignEnum optional_foreign_enum = 22;
optional protobuf_unittest_import.ImportEnum optional_import_enum = 23;
optional string optional_string_piece = 24 [ctype=STRING_PIECE];
optional string optional_cord = 25 [ctype=CORD];
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated group RepeatedGroup = 46 {
optional int32 a = 47;
}
repeated NestedMessage repeated_nested_message = 48;
repeated ForeignMessage repeated_foreign_message = 49;
repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
repeated NestedEnum repeated_nested_enum = 51;
repeated ForeignEnum repeated_foreign_enum = 52;
repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional int64 default_int64 = 62 [default = 42 ];
optional uint32 default_uint32 = 63 [default = 43 ];
optional uint64 default_uint64 = 64 [default = 44 ];
optional sint32 default_sint32 = 65 [default = -45 ];
optional sint64 default_sint64 = 66 [default = 46 ];
optional fixed32 default_fixed32 = 67 [default = 47 ];
optional fixed64 default_fixed64 = 68 [default = 48 ];
optional sfixed32 default_sfixed32 = 69 [default = 49 ];
optional sfixed64 default_sfixed64 = 70 [default = -50 ];
optional float default_float = 71 [default = 51.5 ];
optional double default_double = 72 [default = 52e3 ];
optional bool default_bool = 73 [default = true ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional NestedEnum default_nested_enum = 81 [default = BAR ];
optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
optional protobuf_unittest_import.ImportEnum
default_import_enum = 83 [default = IMPORT_BAR];
optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
optional string default_cord = 85 [ctype=CORD,default="123"];
}
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
optional int32 c = 1;
}
enum ForeignEnum {
FOREIGN_FOO = 4;
FOREIGN_BAR = 5;
FOREIGN_BAZ = 6;
}
message TestAllExtensions {
extensions 1 to max;
}
extend TestAllExtensions {
// Singular
optional int32 optional_int32_extension = 1;
optional int64 optional_int64_extension = 2;
optional uint32 optional_uint32_extension = 3;
optional uint64 optional_uint64_extension = 4;
optional sint32 optional_sint32_extension = 5;
optional sint64 optional_sint64_extension = 6;
optional fixed32 optional_fixed32_extension = 7;
optional fixed64 optional_fixed64_extension = 8;
optional sfixed32 optional_sfixed32_extension = 9;
optional sfixed64 optional_sfixed64_extension = 10;
optional float optional_float_extension = 11;
optional double optional_double_extension = 12;
optional bool optional_bool_extension = 13;
optional string optional_string_extension = 14;
optional bytes optional_bytes_extension = 15;
optional group OptionalGroup_extension = 16 {
optional int32 a = 17;
}
optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
optional ForeignMessage optional_foreign_message_extension = 19;
optional protobuf_unittest_import.ImportMessage
optional_import_message_extension = 20;
optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
optional ForeignEnum optional_foreign_enum_extension = 22;
optional protobuf_unittest_import.ImportEnum
optional_import_enum_extension = 23;
optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
optional string optional_cord_extension = 25 [ctype=CORD];
// Repeated
repeated int32 repeated_int32_extension = 31;
repeated int64 repeated_int64_extension = 32;
repeated uint32 repeated_uint32_extension = 33;
repeated uint64 repeated_uint64_extension = 34;
repeated sint32 repeated_sint32_extension = 35;
repeated sint64 repeated_sint64_extension = 36;
repeated fixed32 repeated_fixed32_extension = 37;
repeated fixed64 repeated_fixed64_extension = 38;
repeated sfixed32 repeated_sfixed32_extension = 39;
repeated sfixed64 repeated_sfixed64_extension = 40;
repeated float repeated_float_extension = 41;
repeated double repeated_double_extension = 42;
repeated bool repeated_bool_extension = 43;
repeated string repeated_string_extension = 44;
repeated bytes repeated_bytes_extension = 45;
repeated group RepeatedGroup_extension = 46 {
optional int32 a = 47;
}
repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
repeated ForeignMessage repeated_foreign_message_extension = 49;
repeated protobuf_unittest_import.ImportMessage
repeated_import_message_extension = 50;
repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
repeated ForeignEnum repeated_foreign_enum_extension = 52;
repeated protobuf_unittest_import.ImportEnum
repeated_import_enum_extension = 53;
repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
repeated string repeated_cord_extension = 55 [ctype=CORD];
// Singular with defaults
optional int32 default_int32_extension = 61 [default = 41 ];
optional int64 default_int64_extension = 62 [default = 42 ];
optional uint32 default_uint32_extension = 63 [default = 43 ];
optional uint64 default_uint64_extension = 64 [default = 44 ];
optional sint32 default_sint32_extension = 65 [default = -45 ];
optional sint64 default_sint64_extension = 66 [default = 46 ];
optional fixed32 default_fixed32_extension = 67 [default = 47 ];
optional fixed64 default_fixed64_extension = 68 [default = 48 ];
optional sfixed32 default_sfixed32_extension = 69 [default = 49 ];
optional sfixed64 default_sfixed64_extension = 70 [default = -50 ];
optional float default_float_extension = 71 [default = 51.5 ];
optional double default_double_extension = 72 [default = 52e3 ];
optional bool default_bool_extension = 73 [default = true ];
optional string default_string_extension = 74 [default = "hello"];
optional bytes default_bytes_extension = 75 [default = "world"];
optional TestAllTypes.NestedEnum
default_nested_enum_extension = 81 [default = BAR];
optional ForeignEnum
default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
optional protobuf_unittest_import.ImportEnum
default_import_enum_extension = 83 [default = IMPORT_BAR];
optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
default="abc"];
optional string default_cord_extension = 85 [ctype=CORD, default="123"];
}
// We have separate messages for testing required fields because it's
// annoying to have to fill in required fields in TestProto in order to
// do anything with it. Note that we don't need to test every type of
// required filed because the code output is basically identical to
// optional fields for all types.
message TestRequired {
required int32 a = 1;
optional int32 dummy2 = 2;
required int32 b = 3;
extend TestAllExtensions {
optional TestRequired single = 1000;
repeated TestRequired multi = 1001;
}
// Pad the field count to 32 so that we can test that IsInitialized()
// properly checks multiple elements of has_bits_.
optional int32 dummy4 = 4;
optional int32 dummy5 = 5;
optional int32 dummy6 = 6;
optional int32 dummy7 = 7;
optional int32 dummy8 = 8;
optional int32 dummy9 = 9;
optional int32 dummy10 = 10;
optional int32 dummy11 = 11;
optional int32 dummy12 = 12;
optional int32 dummy13 = 13;
optional int32 dummy14 = 14;
optional int32 dummy15 = 15;
optional int32 dummy16 = 16;
optional int32 dummy17 = 17;
optional int32 dummy18 = 18;
optional int32 dummy19 = 19;
optional int32 dummy20 = 20;
optional int32 dummy21 = 21;
optional int32 dummy22 = 22;
optional int32 dummy23 = 23;
optional int32 dummy24 = 24;
optional int32 dummy25 = 25;
optional int32 dummy26 = 26;
optional int32 dummy27 = 27;
optional int32 dummy28 = 28;
optional int32 dummy29 = 29;
optional int32 dummy30 = 30;
optional int32 dummy31 = 31;
optional int32 dummy32 = 32;
required int32 c = 33;
}
message TestRequiredForeign {
optional TestRequired optional_message = 1;
repeated TestRequired repeated_message = 2;
optional int32 dummy = 3;
}
// Test that we can use NestedMessage from outside TestAllTypes.
message TestForeignNested {
optional TestAllTypes.NestedMessage foreign_nested = 1;
}
// TestEmptyMessage is used to test unknown field support.
message TestEmptyMessage {
}
// Like above, but declare all field numbers as potential extensions. No
// actual extensions should ever be defined for this type.
message TestEmptyMessageWithExtensions {
extensions 1 to max;
}
// Test that really large tag numbers don't break anything.
message TestReallyLargeTagNumber {
// The largest possible tag number is 2^28 - 1, since the wire format uses
// three bits to communicate wire type.
optional int32 a = 1;
optional int32 bb = 268435455;
}
message TestRecursiveMessage {
optional TestRecursiveMessage a = 1;
optional int32 i = 2;
}
// Test that mutual recursion works.
message TestMutualRecursionA {
optional TestMutualRecursionB bb = 1;
}
message TestMutualRecursionB {
optional TestMutualRecursionA a = 1;
optional int32 optional_int32 = 2;
}
// Test that groups have disjoint field numbers from their siblings and
// parents. This is NOT possible in proto1; only proto2. When outputting
// proto1, the dup fields should be dropped.
message TestDupFieldNumber {
optional int32 a = 1;
optional group Foo = 2 { optional int32 a = 1; }
optional group Bar = 3 { optional int32 a = 1; }
}
// Needed for a Python test.
message TestNestedMessageHasBits {
message NestedMessage {
repeated int32 nestedmessage_repeated_int32 = 1;
repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
}
optional NestedMessage optional_nested_message = 1;
}
// Test an enum that has multiple values with the same number.
enum TestEnumWithDupValue {
FOO1 = 1;
BAR1 = 2;
BAZ = 3;
FOO2 = 1;
BAR2 = 2;
}
// Test an enum with large, unordered values.
enum TestSparseEnum {
SPARSE_A = 123;
SPARSE_B = 62374;
SPARSE_C = 12589234;
SPARSE_D = -15;
SPARSE_E = -53452;
SPARSE_F = 0;
SPARSE_G = 2;
}
// Test message with CamelCase field names. This violates Protocol Buffer
// standard style.
message TestCamelCaseFieldNames {
optional int32 PrimitiveField = 1;
optional string StringField = 2;
optional ForeignEnum EnumField = 3;
optional ForeignMessage MessageField = 4;
optional string StringPieceField = 5 [ctype=STRING_PIECE];
optional string CordField = 6 [ctype=CORD];
repeated int32 RepeatedPrimitiveField = 7;
repeated string RepeatedStringField = 8;
repeated ForeignEnum RepeatedEnumField = 9;
repeated ForeignMessage RepeatedMessageField = 10;
repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
repeated string RepeatedCordField = 12 [ctype=CORD];
}
// We list fields out of order, to ensure that we're using field number and not
// field index to determine serialization order.
message TestFieldOrderings {
optional string my_string = 11;
extensions 2 to 10;
optional int64 my_int = 1;
extensions 12 to 100;
optional float my_float = 101;
}
extend TestFieldOrderings {
optional string my_extension_string = 50;
optional int32 my_extension_int = 5;
}
message TestExtremeDefaultValues {
optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
optional int32 small_int32 = 4 [default = -0x7FFFFFFF];
optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF];
// The default value here is UTF-8 for "\u1234". (We could also just type
// the UTF-8 text directly into this text file rather than escape it, but
// lots of people use editors that would be confused by this.)
optional string utf8_string = 6 [default = "\341\210\264"];
}
// Test that RPC services work.
message FooRequest {}
message FooResponse {}
service TestService {
rpc Foo(FooRequest) returns (FooResponse);
rpc Bar(BarRequest) returns (BarResponse);
}
message BarRequest {}
message BarResponse {}

@ -0,0 +1,277 @@
// 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;
}

@ -0,0 +1,57 @@
// 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;
}

@ -0,0 +1,68 @@
// 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;
}

@ -0,0 +1,79 @@
// 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;
}
}

@ -0,0 +1,67 @@
// 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;
}

@ -0,0 +1 @@
Welcome! This is, of course, a placeholder file.

@ -0,0 +1,95 @@
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
}
}
}
}

@ -0,0 +1,69 @@
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));
}
}
}

@ -0,0 +1,10 @@
using Google.ProtocolBuffers.DescriptorProtos;
using NUnit.Framework;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
[TestFixture]
public class GeneratorTest {
}
}

@ -0,0 +1,33 @@
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);
}
}
}

@ -0,0 +1,36 @@
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")]

@ -0,0 +1,74 @@
<?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>

@ -0,0 +1,17 @@
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)) {
}
}
}

@ -0,0 +1,108 @@
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);
}
}
}
}

@ -0,0 +1,75 @@
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("}");
}
}
}

@ -0,0 +1,19 @@
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();
}
}
}

@ -0,0 +1,37 @@
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);
}
}
}
}

@ -0,0 +1,130 @@
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();
}
}
}
}

@ -0,0 +1,138 @@
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);
}
}
}

@ -0,0 +1,69 @@
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);
}
}
}
}

@ -0,0 +1,78 @@
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;
}
}
}

@ -0,0 +1,11 @@
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);
}
}

@ -0,0 +1,5 @@
namespace Google.ProtocolBuffers.ProtoGen {
internal interface ISourceGenerator {
void Generate(TextGenerator writer);
}
}

@ -0,0 +1,36 @@
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();
}
}
}

@ -0,0 +1,92 @@
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("}");
}
}
}

@ -0,0 +1,453 @@
using System.Collections;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.DescriptorProtos;
using System.Collections.Generic;
using ExtensionRange = Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange;
namespace Google.ProtocolBuffers.ProtoGen {
internal class MessageGenerator : SourceGeneratorBase<MessageDescriptor>, ISourceGenerator {
internal MessageGenerator(MessageDescriptor descriptor) : base(descriptor) {
}
private string ClassName {
get { return Descriptor.Name; }
}
private string FullClassName {
get { return DescriptorUtil.GetClassName(Descriptor); }
}
/// <summary>
/// Get an identifier that uniquely identifies this type within the file.
/// This is used to declare static variables related to this type at the
/// outermost file scope.
/// </summary>
static string GetUniqueFileScopeIdentifier(IDescriptor descriptor) {
return "static_" + descriptor.FullName.Replace(".", "_");
}
internal void GenerateStaticVariables(TextGenerator writer) {
// Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is
// used in the construction of descriptors, we have a tricky bootstrapping
// problem. To help control static initialization order, we make sure all
// descriptors and other static data that depends on them are members of
// the proto-descriptor class. This way, they will be initialized in
// a deterministic order.
string identifier = GetUniqueFileScopeIdentifier(Descriptor);
// The descriptor for this type.
string access = Descriptor.File.Options.GetExtension(CSharpOptions.CSharpNestClasses) ? "private" : "internal";
writer.WriteLine("{0} static readonly pbd::MessageDescriptor internal__{1}__Descriptor", access, identifier);
if (Descriptor.ContainingType == null) {
writer.WriteLine(" = Descriptor.MessageTypes[{0}];", Descriptor.Index);
} else {
writer.WriteLine(" = internal__{0}__Descriptor.NestedTypes[{1}];", GetUniqueFileScopeIdentifier(Descriptor.ContainingType), Descriptor.Index);
}
writer.WriteLine("{0} static pb::FieldAccess.FieldAccessorTable<{1}, {1}.Builder> internal__{2}__FieldAccessorTable",
access, FullClassName, identifier);
writer.WriteLine(" = new pb::FieldAccess.FieldAccessorTable<{0}, {0}.Builder>(internal__{1}__Descriptor,",
FullClassName, identifier);
writer.Print(" new string[] { ");
foreach (FieldDescriptor field in Descriptor.Fields) {
writer.Write("\"{0}\", ", Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(field)));
}
writer.WriteLine("});");
// Generate static members for all nested types.
foreach (MessageDescriptor nestedMessage in Descriptor.NestedTypes) {
new MessageGenerator(nestedMessage).GenerateStaticVariables(writer);
}
}
public void Generate(TextGenerator writer) {
writer.WriteLine("{0} sealed partial class {1} : pb::{2}Message<{1}, {1}.Builder> {{",
ClassAccessLevel, ClassName, Descriptor.Proto.ExtensionRangeCount > 0 ? "Extendable" : "Generated");
writer.Indent();
// Must call BuildPartial() to make sure all lists are made read-only
writer.WriteLine("private static readonly {0} defaultInstance = new Builder().BuildPartial();", ClassName);
writer.WriteLine("public static {0} DefaultInstance {{", ClassName);
writer.WriteLine(" get { return defaultInstance; }");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
writer.WriteLine(" get { return defaultInstance; }");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("protected override {0} ThisMessage {{", ClassName);
writer.WriteLine(" get { return this; }");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public static pbd::MessageDescriptor Descriptor {");
writer.WriteLine(" get {{ return {0}.internal__{1}__Descriptor; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor.File),
GetUniqueFileScopeIdentifier(Descriptor));
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("protected override pb::FieldAccess.FieldAccessorTable<{0}, {0}.Builder> InternalFieldAccessors {{", ClassName);
writer.WriteLine(" get {{ return {0}.internal__{1}__FieldAccessorTable; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor.File),
GetUniqueFileScopeIdentifier(Descriptor));
writer.WriteLine("}");
writer.WriteLine();
// Extensions don't need to go in an extra nested type
WriteChildren(writer, null, Descriptor.Extensions);
if (Descriptor.EnumTypes.Count + Descriptor.NestedTypes.Count > 0) {
writer.WriteLine("#region Nested types");
writer.WriteLine("public static class Types {");
writer.Indent();
WriteChildren(writer, null, Descriptor.EnumTypes);
WriteChildren(writer, null, Descriptor.NestedTypes);
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine("#endregion");
writer.WriteLine();
}
foreach(FieldDescriptor fieldDescriptor in Descriptor.Fields) {
// Rats: we lose the debug comment here :(
SourceGenerators.CreateFieldGenerator(fieldDescriptor).GenerateMembers(writer);
writer.WriteLine();
}
if (Descriptor.File.Options.OptimizeFor == FileOptions.Types.OptimizeMode.SPEED) {
GenerateIsInitialized(writer);
GenerateMessageSerializationMethods(writer);
}
GenerateParseFromMethods(writer);
GenerateBuilder(writer);
}
private void GenerateMessageSerializationMethods(TextGenerator writer) {
List<FieldDescriptor> sortedFields = new List<FieldDescriptor>(Descriptor.Fields);
sortedFields.Sort((f1, f2) => f1.FieldNumber.CompareTo(f2.FieldNumber));
List<ExtensionRange> sortedExtensions = new List<ExtensionRange>(Descriptor.Proto.ExtensionRangeList);
sortedExtensions.Sort((r1, r2) => (r1.Start.CompareTo(r2.Start)));
writer.WriteLine("public override void WriteTo(pb::CodedOutputStream output) {");
writer.Indent();
if (Descriptor.Proto.ExtensionRangeList.Count > 0) {
writer.WriteLine("pb::ExtendableMessage<{0}, {0}.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);",
ClassName);
}
// Merge the fields and the extension ranges, both sorted by field number.
for (int i = 0, j = 0; i < Descriptor.Fields.Count || j < sortedExtensions.Count; ) {
if (i == Descriptor.Fields.Count) {
GenerateSerializeOneExtensionRange(writer, sortedExtensions[j++]);
} else if (j == sortedExtensions.Count) {
GenerateSerializeOneField(writer, sortedFields[i++]);
} else if (sortedFields[i].FieldNumber < sortedExtensions[j].Start) {
GenerateSerializeOneField(writer, sortedFields[i++]);
} else {
GenerateSerializeOneExtensionRange(writer, sortedExtensions[j++]);
}
}
if (Descriptor.Proto.Options.MessageSetWireFormat) {
writer.WriteLine("UnknownFields.WriteAsMessageSetTo(output);");
} else {
writer.WriteLine("UnknownFields.WriteTo(output);");
}
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("private int memoizedSerializedSize = -1;");
writer.WriteLine("public override int SerializedSize {");
writer.Indent();
writer.WriteLine("get {");
writer.Indent();
writer.WriteLine("int size = memoizedSerializedSize;");
writer.WriteLine("if (size != -1) return size;");
writer.WriteLine();
writer.WriteLine("size = 0;");
foreach (FieldDescriptor field in Descriptor.Fields) {
SourceGenerators.CreateFieldGenerator(field).GenerateSerializedSizeCode(writer);
}
if (Descriptor.Proto.ExtensionRangeCount > 0) {
writer.WriteLine("size += ExtensionsSerializedSize;");
}
if (Descriptor.Options.MessageSetWireFormat) {
writer.WriteLine("size += UnknownFields.SerializedSizeAsMessageSet;");
} else {
writer.WriteLine("size += UnknownFields.SerializedSize;");
}
writer.WriteLine("memoizedSerializedSize = size;");
writer.WriteLine("return size;");
writer.Outdent();
writer.WriteLine("}");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
private static void GenerateSerializeOneField(TextGenerator writer, FieldDescriptor fieldDescriptor) {
SourceGenerators.CreateFieldGenerator(fieldDescriptor).GenerateSerializationCode(writer);
}
private static void GenerateSerializeOneExtensionRange(TextGenerator writer, ExtensionRange extensionRange) {
writer.WriteLine("extensionWriter.WriteUntil({0}, output);", extensionRange.End);
}
private void GenerateParseFromMethods(TextGenerator writer) {
// Note: These are separate from GenerateMessageSerializationMethods()
// because they need to be generated even for messages that are optimized
// for code size.
writer.WriteLine("public static {0} ParseFrom(pb::ByteString data) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(byte[] data) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(global::System.IO.Stream input) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(pb::CodedInputStream input) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();");
writer.WriteLine("}");
}
/// <summary>
/// Returns whether or not the specified message type has any required fields.
/// If it doesn't, calls to check for initialization can be optimised.
/// TODO(jonskeet): Move this into MessageDescriptor?
/// </summary>
private static bool HasRequiredFields(MessageDescriptor descriptor, Dictionary<MessageDescriptor,object> alreadySeen) {
if (alreadySeen.ContainsKey(descriptor)) {
// The type is already in cache. This means that either:
// a. The type has no required fields.
// b. We are in the midst of checking if the type has required fields,
// somewhere up the stack. In this case, we know that if the type
// has any required fields, they'll be found when we return to it,
// and the whole call to HasRequiredFields() will return true.
// Therefore, we don't have to check if this type has required fields
// here.
return false;
}
alreadySeen[descriptor] = descriptor; // Value is irrelevant
// If the type has extensions, an extension with message type could contain
// required fields, so we have to be conservative and assume such an
// extension exists.
if (descriptor.Extensions.Count > 0) {
return true;
}
foreach (FieldDescriptor field in descriptor.Fields) {
if (field.IsRequired) {
return true;
}
// Message or group
if (field.MappedType == MappedType.Message) {
if (HasRequiredFields(field.MessageType, alreadySeen)) {
return true;
}
}
}
return false;
}
private void GenerateBuilder(TextGenerator writer) {
writer.WriteLine("public static Builder CreateBuilder() { return new Builder(); }");
writer.WriteLine("public override Builder CreateBuilderForType() { return new Builder(); }");
writer.WriteLine("public static Builder CreateBuilder({0} prototype) {{", ClassName);
writer.WriteLine(" return (Builder) new Builder().MergeFrom(prototype);");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("{0} sealed partial class Builder : pb::{2}Builder<{1}, Builder> {{",
ClassAccessLevel, ClassName, Descriptor.Proto.ExtensionRangeCount > 0 ? "Extendable" : "Generated");
writer.Indent();
writer.WriteLine("protected override Builder ThisBuilder {");
writer.WriteLine(" get { return this; }");
writer.WriteLine("}");
GenerateCommonBuilderMethods(writer);
if (Descriptor.File.Options.OptimizeFor == FileOptions.Types.OptimizeMode.SPEED) {
GenerateBuilderParsingMethods(writer);
}
foreach (FieldDescriptor field in Descriptor.Fields) {
writer.WriteLine();
// No field comment :(
SourceGenerators.CreateFieldGenerator(field).GenerateBuilderMembers(writer);
}
writer.Outdent();
writer.WriteLine("}");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
private void GenerateCommonBuilderMethods(TextGenerator writer) {
writer.WriteLine("{0} Builder() {{}}", ClassAccessLevel);
writer.WriteLine();
writer.WriteLine("{0} result = new {0}();", ClassName);
writer.WriteLine();
writer.WriteLine("protected override {0} MessageBeingBuilt {{", ClassName);
writer.WriteLine(" get { return result; }");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override Builder Clear() {");
writer.WriteLine(" result = new {0}();", ClassName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override Builder Clone() {");
writer.WriteLine(" return new Builder().MergeFrom(result);");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override pbd::MessageDescriptor DescriptorForType {");
writer.WriteLine(" get {{ return {0}.Descriptor; }}", ClassName);
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
writer.WriteLine(" get {{ return {0}.DefaultInstance; }}", ClassName);
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override {0} BuildPartial() {{", ClassName);
writer.Indent();
foreach (FieldDescriptor field in Descriptor.Fields) {
SourceGenerators.CreateFieldGenerator(field).GenerateBuildingCode(writer);
}
writer.WriteLine("{0} returnMe = result;", ClassName);
writer.WriteLine("result = null;");
writer.WriteLine("return returnMe;");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
if (Descriptor.File.Options.OptimizeFor == FileOptions.Types.OptimizeMode.SPEED) {
writer.WriteLine("public override Builder MergeFrom(pb::IMessage other) {");
writer.WriteLine(" if (other is {0}) {{", ClassName);
writer.WriteLine(" return MergeFrom(({0}) other);", ClassName);
writer.WriteLine(" } else {");
writer.WriteLine(" base.MergeFrom(other);");
writer.WriteLine(" return this;");
writer.WriteLine(" }");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override Builder MergeFrom({0} other) {{", ClassName);
// Optimization: If other is the default instance, we know none of its
// fields are set so we can skip the merge.
writer.Indent();
writer.WriteLine("if (other == {0}.DefaultInstance) return this;", ClassName);
foreach (FieldDescriptor field in Descriptor.Fields) {
SourceGenerators.CreateFieldGenerator(field).GenerateMergingCode(writer);
}
writer.WriteLine("this.MergeUnknownFields(other.UnknownFields);");
writer.WriteLine("return this;");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
}
private void GenerateBuilderParsingMethods(TextGenerator writer) {
List<FieldDescriptor> sortedFields = new List<FieldDescriptor>(Descriptor.Fields);
sortedFields.Sort((f1, f2) => f1.FieldNumber.CompareTo(f2.FieldNumber));
writer.WriteLine("public override Builder MergeFrom(pb::CodedInputStream input) {");
writer.WriteLine(" return MergeFrom(input, pb::ExtensionRegistry.Empty);");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {");
writer.Indent();
writer.WriteLine("pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
writer.WriteLine("while (true) {");
writer.Indent();
writer.WriteLine("uint tag = input.ReadTag();");
writer.WriteLine("switch (tag) {");
writer.Indent();
writer.WriteLine("case 0: {"); // 0 signals EOF / limit reached
writer.WriteLine(" this.UnknownFields = unknownFields.Build();");
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine("default: {");
writer.WriteLine(" if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) {");
writer.WriteLine(" this.UnknownFields = unknownFields.Build();");
writer.WriteLine(" return this;"); // it's an endgroup tag
writer.WriteLine(" }");
writer.WriteLine(" break;");
writer.WriteLine("}");
foreach (FieldDescriptor field in sortedFields) {
uint tag = WireFormat.MakeTag(field.FieldNumber, WireFormat.GetWireType(field.FieldType));
writer.WriteLine("case {0}: {{", tag);
writer.Indent();
SourceGenerators.CreateFieldGenerator(field).GenerateParsingCode(writer);
writer.WriteLine("break;");
writer.Outdent();
writer.WriteLine("}");
}
writer.Outdent();
writer.WriteLine("}");
writer.Outdent();
writer.WriteLine("}");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
private void GenerateIsInitialized(TextGenerator writer) {
writer.WriteLine("public override bool IsInitialized {");
writer.Indent();
writer.WriteLine("get {");
writer.Indent();
// Check that all required fields in this message are set.
// TODO(kenton): We can optimize this when we switch to putting all the
// "has" fields into a single bitfield.
foreach (FieldDescriptor field in Descriptor.Fields) {
if (field.IsRequired) {
writer.WriteLine("if (!has{0}) return false;", Helpers.UnderscoresToPascalCase(field.Name));
}
}
// Now check that all embedded messages are initialized.
foreach (FieldDescriptor field in Descriptor.Fields) {
if (field.FieldType != FieldType.Message ||
!HasRequiredFields(field.MessageType, new Dictionary<MessageDescriptor, object>())) {
continue;
}
string propertyName = Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(field));
if (field.IsRepeated) {
writer.WriteLine("foreach ({0} element in {1}List) {{", DescriptorUtil.GetClassName(field.MessageType), propertyName);
writer.WriteLine(" if (!element.IsInitialized) return false;");
writer.WriteLine("}");
} else if (field.IsOptional) {
writer.WriteLine("if (Has{0}) {{", propertyName);
writer.WriteLine(" if (!{0}.IsInitialized) return false;", propertyName);
writer.WriteLine("}");
} else {
writer.WriteLine("if (!{0}.IsInitialized) return false;", propertyName);
}
}
if (Descriptor.Proto.ExtensionRangeCount > 0) {
writer.WriteLine("if (!ExtensionsAreInitialized) return false;");
}
writer.WriteLine("return true;");
writer.Outdent();
writer.WriteLine("}");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
}
}
}

@ -0,0 +1,70 @@
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("}");
}
}
}

@ -0,0 +1,47 @@
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;
}
}
}

@ -0,0 +1,42 @@
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")]

@ -0,0 +1,85 @@
<?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>

@ -0,0 +1,90 @@
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("}");
}
}
}

@ -0,0 +1,100 @@
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("}");
}
}
}

@ -0,0 +1,84 @@
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("}");
}
}
}

@ -0,0 +1,138 @@
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("}");
}
}
}

@ -0,0 +1,29 @@
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);
}
}
}

@ -0,0 +1,50 @@
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();
}
}
}
}

@ -0,0 +1,42 @@
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);
}
}
}

@ -0,0 +1,96 @@
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();
}
}
}

@ -0,0 +1,3 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

@ -0,0 +1,364 @@
// 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;
using System.Collections.Generic;
using Google.ProtocolBuffers.Descriptors;
using NUnit.Framework;
using Google.ProtocolBuffers.TestProtos;
namespace Google.ProtocolBuffers {
[TestFixture]
public class AbstractMessageTest {
[Test]
public void Clear() {
AbstractMessageWrapper message = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(TestUtil.GetAllSet())).Clear().Build();
TestUtil.AssertClear((TestAllTypes) message.WrappedMessage);
}
[Test]
public void Copy() {
AbstractMessageWrapper message = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()).MergeFrom(TestUtil.GetAllSet()).Build();
TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage);
}
[Test]
public void SerializedSize() {
TestAllTypes message = TestUtil.GetAllSet();
IMessage abstractMessage = new AbstractMessageWrapper(TestUtil.GetAllSet());
Assert.AreEqual(message.SerializedSize, abstractMessage.SerializedSize);
}
[Test]
public void Serialization() {
IMessage abstractMessage = new AbstractMessageWrapper(TestUtil.GetAllSet());
TestUtil.AssertAllFieldsSet(TestAllTypes.ParseFrom(abstractMessage.ToByteString()));
Assert.AreEqual(TestUtil.GetAllSet().ToByteString(), abstractMessage.ToByteString());
}
[Test]
public void Parsing() {
IBuilder builder = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder());
AbstractMessageWrapper message = (AbstractMessageWrapper) builder.WeakMergeFrom(TestUtil.GetAllSet().ToByteString()).WeakBuild();
TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage);
}
[Test]
public void OptimizedForSize() {
// We're mostly only Checking that this class was compiled successfully.
TestOptimizedForSize message = TestOptimizedForSize.CreateBuilder().SetI(1).Build();
message = TestOptimizedForSize.ParseFrom(message.ToByteString());
Assert.AreEqual(2, message.SerializedSize);
}
// -----------------------------------------------------------------
// Tests for isInitialized().
private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance;
private static readonly TestRequired TestRequiredInitialized = TestRequired.CreateBuilder().SetA(1).SetB(2).SetC(3).Build();
[Test]
public void IsInitialized() {
TestRequired.Builder builder = TestRequired.CreateBuilder();
AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder);
Assert.IsFalse(abstractBuilder.IsInitialized);
builder.A = 1;
Assert.IsFalse(abstractBuilder.IsInitialized);
builder.B = 1;
Assert.IsFalse(abstractBuilder.IsInitialized);
builder.C = 1;
Assert.IsTrue(abstractBuilder.IsInitialized);
}
[Test]
public void ForeignIsInitialized() {
TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder();
AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder);
Assert.IsTrue(abstractBuilder.IsInitialized);
builder.SetOptionalMessage(TestRequiredUninitialized);
Assert.IsFalse(abstractBuilder.IsInitialized);
builder.SetOptionalMessage(TestRequiredInitialized);
Assert.IsTrue(abstractBuilder.IsInitialized);
builder.AddRepeatedMessage(TestRequiredUninitialized);
Assert.IsFalse(abstractBuilder.IsInitialized);
builder.SetRepeatedMessage(0, TestRequiredInitialized);
Assert.IsTrue(abstractBuilder.IsInitialized);
}
// -----------------------------------------------------------------
// Tests for mergeFrom
static readonly TestAllTypes MergeSource = TestAllTypes.CreateBuilder()
.SetOptionalInt32(1)
.SetOptionalString("foo")
.SetOptionalForeignMessage(ForeignMessage.DefaultInstance)
.AddRepeatedString("bar")
.Build();
static readonly TestAllTypes MergeDest = TestAllTypes.CreateBuilder()
.SetOptionalInt64(2)
.SetOptionalString("baz")
.SetOptionalForeignMessage(ForeignMessage.CreateBuilder().SetC(3).Build())
.AddRepeatedString("qux")
.Build();
const string MergeResultText = "optional_int32: 1\n" +
"optional_int64: 2\n" +
"optional_string: \"foo\"\n" +
"optional_foreign_message {\n" +
" c: 3\n" +
"}\n" +
"repeated_string: \"qux\"\n" +
"repeated_string: \"bar\"\n";
[Test]
public void MergeFrom() {
AbstractMessageWrapper result = (AbstractMessageWrapper)
new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(MergeDest))
.MergeFrom(MergeSource)
.Build();
Assert.AreEqual(MergeResultText, result.ToString());
}
// -----------------------------------------------------------------
// Tests for equals and hashCode
[Test]
public void EqualsAndHashCode() {
TestAllTypes a = TestUtil.GetAllSet();
TestAllTypes b = TestAllTypes.CreateBuilder().Build();
TestAllTypes c = TestAllTypes.CreateBuilder(b).AddRepeatedString("x").Build();
TestAllTypes d = TestAllTypes.CreateBuilder(c).AddRepeatedString("y").Build();
TestAllExtensions e = TestUtil.GetAllExtensionsSet();
TestAllExtensions f = TestAllExtensions.CreateBuilder(e)
.AddExtension(UnitTestProtoFile.RepeatedInt32Extension, 999).Build();
CheckEqualsIsConsistent(a);
CheckEqualsIsConsistent(b);
CheckEqualsIsConsistent(c);
CheckEqualsIsConsistent(d);
CheckEqualsIsConsistent(e);
CheckEqualsIsConsistent(f);
CheckNotEqual(a, b);
CheckNotEqual(a, c);
CheckNotEqual(a, d);
CheckNotEqual(a, e);
CheckNotEqual(a, f);
CheckNotEqual(b, c);
CheckNotEqual(b, d);
CheckNotEqual(b, e);
CheckNotEqual(b, f);
CheckNotEqual(c, d);
CheckNotEqual(c, e);
CheckNotEqual(c, f);
CheckNotEqual(d, e);
CheckNotEqual(d, f);
CheckNotEqual(e, f);
}
/// <summary>
/// Asserts that the given protos are equal and have the same hash code.
/// </summary>
private static void CheckEqualsIsConsistent(IMessage message) {
// Object should be equal to itself.
Assert.AreEqual(message, message);
// Object should be equal to a dynamic copy of itself.
DynamicMessage dynamic = DynamicMessage.CreateBuilder(message).Build();
Assert.AreEqual(message, dynamic);
Assert.AreEqual(dynamic, message);
Assert.AreEqual(dynamic.GetHashCode(), message.GetHashCode());
}
/// <summary>
/// Asserts that the given protos are not equal and have different hash codes.
/// </summary>
/// <remarks>
/// It's valid for non-equal objects to have the same hash code, so
/// this test is stricter than it needs to be. However, this should happen
/// relatively rarely. (If this test fails, it's probably still due to a bug.)
/// </remarks>
private static void CheckNotEqual(IMessage m1, IMessage m2) {
String equalsError = string.Format("{0} should not be equal to {1}", m1, m2);
Assert.IsFalse(m1.Equals(m2), equalsError);
Assert.IsFalse(m2.Equals(m1), equalsError);
Assert.IsFalse(m1.GetHashCode() == m2.GetHashCode(),
string.Format("{0} should have a different hash code from {1}", m1, m2));
}
/// <summary>
/// Extends AbstractMessage and wraps some other message object. The methods
/// of the Message interface which aren't explicitly implemented by
/// AbstractMessage are forwarded to the wrapped object. This allows us to
/// test that AbstractMessage's implementations work even if the wrapped
/// object does not use them.
/// </summary>
private class AbstractMessageWrapper : AbstractMessage<AbstractMessageWrapper, AbstractMessageWrapper.Builder> {
private readonly IMessage wrappedMessage;
public IMessage WrappedMessage {
get { return wrappedMessage; }
}
public AbstractMessageWrapper(IMessage wrappedMessage) {
this.wrappedMessage = wrappedMessage;
}
public override MessageDescriptor DescriptorForType {
get { return wrappedMessage.DescriptorForType; }
}
public override AbstractMessageWrapper DefaultInstanceForType {
get { return new AbstractMessageWrapper(wrappedMessage.WeakDefaultInstanceForType); }
}
public override IDictionary<FieldDescriptor, object> AllFields {
get { return wrappedMessage.AllFields; }
}
public override bool HasField(FieldDescriptor field) {
return wrappedMessage.HasField(field);
}
public override object this[FieldDescriptor field] {
get { return wrappedMessage[field]; }
}
public override object this[FieldDescriptor field, int index] {
get { return wrappedMessage[field, index]; }
}
public override int GetRepeatedFieldCount(FieldDescriptor field) {
return wrappedMessage.GetRepeatedFieldCount(field);
}
public override UnknownFieldSet UnknownFields {
get { return wrappedMessage.UnknownFields; }
}
public override Builder CreateBuilderForType() {
return new Builder(wrappedMessage.WeakCreateBuilderForType());
}
internal class Builder : AbstractBuilder<AbstractMessageWrapper, Builder> {
private readonly IBuilder wrappedBuilder;
protected override Builder ThisBuilder {
get { return this; }
}
internal Builder(IBuilder wrappedBuilder) {
this.wrappedBuilder = wrappedBuilder;
}
public override Builder MergeFrom(AbstractMessageWrapper other) {
wrappedBuilder.WeakMergeFrom(other.wrappedMessage);
return this;
}
public override bool IsInitialized {
get { return wrappedBuilder.IsInitialized; }
}
public override IDictionary<FieldDescriptor, object> AllFields {
get { return wrappedBuilder.AllFields; }
}
public override object this[FieldDescriptor field] {
get { return wrappedBuilder[field]; }
set { wrappedBuilder[field] = value; }
}
public override MessageDescriptor DescriptorForType {
get { return wrappedBuilder.DescriptorForType; }
}
public override int GetRepeatedFieldCount(FieldDescriptor field) {
return wrappedBuilder.GetRepeatedFieldCount(field);
}
public override object this[FieldDescriptor field, int index] {
get { return wrappedBuilder[field, index]; }
set { wrappedBuilder[field, index] = value; }
}
public override bool HasField(FieldDescriptor field) {
return wrappedBuilder.HasField(field);
}
public override UnknownFieldSet UnknownFields {
get { return wrappedBuilder.UnknownFields; }
set { wrappedBuilder.UnknownFields = value; }
}
public override AbstractMessageWrapper Build() {
return new AbstractMessageWrapper(wrappedBuilder.WeakBuild());
}
public override AbstractMessageWrapper BuildPartial() {
return new AbstractMessageWrapper(wrappedBuilder.WeakBuildPartial());
}
public override Builder Clone() {
return new Builder(wrappedBuilder.WeakClone());
}
public override AbstractMessageWrapper DefaultInstanceForType {
get { return new AbstractMessageWrapper(wrappedBuilder.WeakDefaultInstanceForType); }
}
public override Builder ClearField(FieldDescriptor field) {
wrappedBuilder.WeakClearField(field);
return this;
}
public override Builder AddRepeatedField(FieldDescriptor field, object value) {
wrappedBuilder.WeakAddRepeatedField(field, value);
return this;
}
public override IBuilder CreateBuilderForField(FieldDescriptor field) {
wrappedBuilder.CreateBuilderForField(field);
return this;
}
public override Builder MergeFrom(IMessage other) {
wrappedBuilder.WeakMergeFrom(other);
return this;
}
public override Builder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
wrappedBuilder.WeakMergeFrom(input, extensionRegistry);
return this;
}
}
}
}
}

@ -0,0 +1,98 @@
// 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));
}
}
}

@ -0,0 +1,376 @@
// 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;
using System.IO;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
using System.Diagnostics;
namespace Google.ProtocolBuffers {
[TestFixture]
public class CodedInputStreamTest {
/// <summary>
/// Helper to construct a byte array from a bunch of bytes. The inputs are
/// actually ints so that I can use hex notation and not get stupid errors
/// about precision.
/// </summary>
private static byte[] Bytes(params int[] bytesAsInts) {
byte[] bytes = new byte[bytesAsInts.Length];
for (int i = 0; i < bytesAsInts.Length; i++) {
bytes[i] = (byte)bytesAsInts[i];
}
return bytes;
}
/// <summary>
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
/// </summary>
private static void AssertReadVarint(byte[] data, ulong value) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
Assert.AreEqual((uint)value, input.ReadRawVarint32());
input = CodedInputStream.CreateInstance(data);
Assert.AreEqual(value, input.ReadRawVarint64());
// Try different block sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) {
input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
Assert.AreEqual((uint)value, input.ReadRawVarint32());
input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
Assert.AreEqual(value, input.ReadRawVarint64());
}
}
/// <summary>
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
/// expects them to fail with an InvalidProtocolBufferException whose
/// description matches the given one.
/// </summary>
private void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
try {
input.ReadRawVarint32();
Assert.Fail("Should have thrown an exception.");
} catch (InvalidProtocolBufferException e) {
Assert.AreEqual(expected.Message, e.Message);
}
input = CodedInputStream.CreateInstance(data);
try {
input.ReadRawVarint64();
Assert.Fail("Should have thrown an exception.");
} catch (InvalidProtocolBufferException e) {
Assert.AreEqual(expected.Message, e.Message);
}
}
[Test]
public void ReadVarint() {
AssertReadVarint(Bytes(0x00), 0);
AssertReadVarint(Bytes(0x01), 1);
AssertReadVarint(Bytes(0x7f), 127);
// 14882
AssertReadVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
// 2961488830
AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x0bL << 28));
// 64-bit
// 7256456126
AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x1bL << 28));
// 41256202580718336
AssertReadVarint(Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
(0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
// 11964378330978735131
AssertReadVarint(Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
(0x3bUL << 28) | (0x56UL << 35) | (0x00UL << 42) |
(0x05UL << 49) | (0x26UL << 56) | (0x01UL << 63));
// Failures
AssertReadVarintFailure(
InvalidProtocolBufferException.MalformedVarint(),
Bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x00));
AssertReadVarintFailure(
InvalidProtocolBufferException.TruncatedMessage(),
Bytes(0x80));
}
/// <summary>
/// Parses the given bytes using ReadRawLittleEndian32() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertReadLittleEndian32(byte[] data, uint value) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
Assert.AreEqual(value, input.ReadRawLittleEndian32());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
input = CodedInputStream.CreateInstance(
new SmallBlockInputStream(data, blockSize));
Assert.AreEqual(value, input.ReadRawLittleEndian32());
}
}
/// <summary>
/// Parses the given bytes using ReadRawLittleEndian64() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertReadLittleEndian64(byte[] data, ulong value) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
Assert.AreEqual(value, input.ReadRawLittleEndian64());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
input = CodedInputStream.CreateInstance(
new SmallBlockInputStream(data, blockSize));
Assert.AreEqual(value, input.ReadRawLittleEndian64());
}
}
[Test]
public void ReadLittleEndian() {
AssertReadLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
AssertReadLittleEndian64(Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
0x123456789abcdef0L);
AssertReadLittleEndian64(
Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678UL);
}
[Test]
public void DecodeZigZag32() {
Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0));
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));
Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2));
Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));
Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));
Assert.AreEqual(unchecked((int)0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));
Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));
Assert.AreEqual(unchecked((int)0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));
}
[Test]
public void DecodeZigZag64() {
Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0));
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));
Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2));
Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));
Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));
Assert.AreEqual(unchecked((long)0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));
Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));
Assert.AreEqual(unchecked((long)0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));
Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
Assert.AreEqual(unchecked((long)0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
}
[Test]
public void ReadWholeMessage() {
TestAllTypes message = TestUtil.GetAllSet();
byte[] rawBytes = message.ToByteArray();
Assert.AreEqual(rawBytes.Length, message.SerializedSize);
TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
TestUtil.AssertAllFieldsSet(message2);
// Try different block sizes.
for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
message2 = TestAllTypes.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
TestUtil.AssertAllFieldsSet(message2);
}
}
[Test]
public void SkipWholeMessage() {
TestAllTypes message = TestUtil.GetAllSet();
byte[] rawBytes = message.ToByteArray();
// Create two parallel inputs. Parse one as unknown fields while using
// skipField() to skip each field on the other. Expect the same tags.
CodedInputStream input1 = CodedInputStream.CreateInstance(rawBytes);
CodedInputStream input2 = CodedInputStream.CreateInstance(rawBytes);
UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder();
while (true) {
uint tag = input1.ReadTag();
Assert.AreEqual(tag, input2.ReadTag());
if (tag == 0) {
break;
}
unknownFields.MergeFieldFrom(tag, input1);
input2.SkipField(tag);
}
}
public void ReadHugeBlob() {
// Allocate and initialize a 1MB blob.
byte[] blob = new byte[1 << 20];
for (int i = 0; i < blob.Length; i++) {
blob[i] = (byte)i;
}
// Make a message containing it.
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TestUtil.SetAllFields(builder);
builder.SetOptionalBytes(ByteString.CopyFrom(blob));
TestAllTypes message = builder.Build();
// Serialize and parse it. Make sure to parse from an InputStream, not
// directly from a ByteString, so that CodedInputStream uses buffered
// reading.
TestAllTypes message2 = TestAllTypes.ParseFrom(message.ToByteString().CreateCodedInput());
Assert.AreEqual(message.OptionalBytes, message2.OptionalBytes);
// Make sure all the other fields were parsed correctly.
TestAllTypes message3 = TestAllTypes.CreateBuilder(message2)
.SetOptionalBytes(TestUtil.GetAllSet().OptionalBytes)
.Build();
TestUtil.AssertAllFieldsSet(message3);
}
[Test]
public void ReadMaliciouslyLargeBlob() {
MemoryStream ms = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
output.WriteRawVarint32(tag);
output.WriteRawVarint32(0x7FFFFFFF);
output.WriteRawBytes(new byte[32]); // Pad with a few random bytes.
output.Flush();
ms.Position = 0;
CodedInputStream input = CodedInputStream.CreateInstance(ms);
Assert.AreEqual(tag, input.ReadTag());
try {
input.ReadBytes();
Assert.Fail("Should have thrown an exception!");
} catch (InvalidProtocolBufferException) {
// success.
}
}
private static TestRecursiveMessage MakeRecursiveMessage(int depth) {
if (depth == 0) {
return TestRecursiveMessage.CreateBuilder().SetI(5).Build();
} else {
return TestRecursiveMessage.CreateBuilder()
.SetA(MakeRecursiveMessage(depth - 1)).Build();
}
}
private static void AssertMessageDepth(TestRecursiveMessage message, int depth) {
if (depth == 0) {
Assert.IsFalse(message.HasA);
Assert.AreEqual(5, message.I);
} else {
Assert.IsTrue(message.HasA);
AssertMessageDepth(message.A, depth - 1);
}
}
[Test]
public void MaliciousRecursion() {
ByteString data64 = MakeRecursiveMessage(64).ToByteString();
ByteString data65 = MakeRecursiveMessage(65).ToByteString();
AssertMessageDepth(TestRecursiveMessage.ParseFrom(data64), 64);
try {
TestRecursiveMessage.ParseFrom(data65);
Assert.Fail("Should have thrown an exception!");
} catch (InvalidProtocolBufferException) {
// success.
}
CodedInputStream input = data64.CreateCodedInput();
input.SetRecursionLimit(8);
try {
TestRecursiveMessage.ParseFrom(input);
Assert.Fail("Should have thrown an exception!");
} catch (InvalidProtocolBufferException) {
// success.
}
}
[Test]
public void SizeLimit() {
// Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't
// apply to the latter case.
MemoryStream ms = new MemoryStream(TestUtil.GetAllSet().ToByteString().ToByteArray());
CodedInputStream input = CodedInputStream.CreateInstance(ms);
input.SetSizeLimit(16);
try {
TestAllTypes.ParseFrom(input);
Assert.Fail("Should have thrown an exception!");
} catch (InvalidProtocolBufferException) {
// success.
}
}
/// <summary>
/// Tests that if we read an string that contains invalid UTF-8, no exception
/// is thrown. Instead, the invalid bytes are replaced with the Unicode
/// "replacement character" U+FFFD.
/// </summary>
[Test]
public void ReadInvalidUtf8() {
MemoryStream ms = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
output.WriteRawVarint32(tag);
output.WriteRawVarint32(1);
output.WriteRawBytes(new byte[] { 0x80 });
output.Flush();
ms.Position = 0;
CodedInputStream input = CodedInputStream.CreateInstance(ms);
Assert.AreEqual(tag, input.ReadTag());
string text = input.ReadString();
Assert.AreEqual('\ufffd', text[0]);
}
/// <summary>
/// A stream which limits the number of bytes it reads at a time.
/// We use this to make sure that CodedInputStream doesn't screw up when
/// reading in small blocks.
/// </summary>
private sealed class SmallBlockInputStream : MemoryStream {
private readonly int blockSize;
public SmallBlockInputStream(byte[] data, int blockSize)
: base(data) {
this.blockSize = blockSize;
}
public override int Read(byte[] buffer, int offset, int count) {
return base.Read(buffer, offset, Math.Min(count, blockSize));
}
}
}
}

@ -0,0 +1,239 @@
// 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.IO;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
[TestFixture]
public class CodedOutputStreamTest {
/// <summary>
/// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
/// checks that the result matches the given bytes
/// </summary>
private static void AssertWriteVarint(byte[] data, ulong value) {
// Only do 32-bit write if the value fits in 32 bits.
if ((value >> 32) == 0) {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Also try computing size.
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
}
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Also try computing size.
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
}
// Try different buffer sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) {
// Only do 32-bit write if the value fits in 32 bits.
if ((value >> 32) == 0) {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output =
CodedOutputStream.CreateInstance(rawOutput, bufferSize);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
}
/// <summary>
/// Tests WriteRawVarint32() and WriteRawVarint64()
/// </summary>
[Test]
public void WriteVarint() {
AssertWriteVarint(new byte[] {0x00}, 0);
AssertWriteVarint(new byte[] {0x01}, 1);
AssertWriteVarint(new byte[] {0x7f}, 127);
// 14882
AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7));
// 2961488830
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b},
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x0bL << 28));
// 64-bit
// 7256456126
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b},
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x1bL << 28));
// 41256202580718336
AssertWriteVarint(
new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49},
(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
(0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
// 11964378330978735131
AssertWriteVarint(
new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01},
unchecked((ulong)
((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
(0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
(0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
}
/// <summary>
/// Parses the given bytes using WriteRawLittleEndian32() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertWriteLittleEndian32(byte[] data, uint value) {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Try different buffer sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) {
rawOutput = new MemoryStream();
output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
/// <summary>
/// Parses the given bytes using WriteRawLittleEndian64() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertWriteLittleEndian64(byte[] data, ulong value) {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
rawOutput = new MemoryStream();
output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
/// <summary>
/// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
/// </summary>
[Test]
public void WriteLittleEndian() {
AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678);
AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0);
AssertWriteLittleEndian64(
new byte[]{0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12},
0x123456789abcdef0L);
AssertWriteLittleEndian64(
new byte[]{0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a},
0x9abcdef012345678UL);
}
[Test]
public void WriteWholeMessage() {
TestAllTypes message = TestUtil.GetAllSet();
byte[] rawBytes = message.ToByteArray();
TestUtil.AssertEqualBytes(TestUtil.GoldenMessage.ToByteArray(), rawBytes);
// Try different block sizes.
for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output =
CodedOutputStream.CreateInstance(rawOutput, blockSize);
message.WriteTo(output);
output.Flush();
TestUtil.AssertEqualBytes(rawBytes, rawOutput.ToArray());
}
}
[Test]
public void EncodeZigZag32() {
Assert.AreEqual(0, CodedOutputStream.EncodeZigZag32( 0));
Assert.AreEqual(1, CodedOutputStream.EncodeZigZag32(-1));
Assert.AreEqual(2, CodedOutputStream.EncodeZigZag32( 1));
Assert.AreEqual(3, CodedOutputStream.EncodeZigZag32(-2));
Assert.AreEqual(0x7FFFFFFE, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));
Assert.AreEqual(0x7FFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int)0xC0000000)));
Assert.AreEqual(0xFFFFFFFE, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));
Assert.AreEqual(0xFFFFFFFF, CodedOutputStream.EncodeZigZag32(unchecked((int)0x80000000)));
}
[Test]
public void EncodeZigZag64() {
Assert.AreEqual(0, CodedOutputStream.EncodeZigZag64( 0));
Assert.AreEqual(1, CodedOutputStream.EncodeZigZag64(-1));
Assert.AreEqual(2, CodedOutputStream.EncodeZigZag64( 1));
Assert.AreEqual(3, CodedOutputStream.EncodeZigZag64(-2));
Assert.AreEqual(0x000000007FFFFFFEL,
CodedOutputStream.EncodeZigZag64(unchecked((long)0x000000003FFFFFFFUL)));
Assert.AreEqual(0x000000007FFFFFFFL,
CodedOutputStream.EncodeZigZag64(unchecked((long)0xFFFFFFFFC0000000UL)));
Assert.AreEqual(0x00000000FFFFFFFEL,
CodedOutputStream.EncodeZigZag64(unchecked((long)0x000000007FFFFFFFUL)));
Assert.AreEqual(0x00000000FFFFFFFFL,
CodedOutputStream.EncodeZigZag64(unchecked((long)0xFFFFFFFF80000000UL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
CodedOutputStream.EncodeZigZag64(unchecked((long)0x7FFFFFFFFFFFFFFFUL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
CodedOutputStream.EncodeZigZag64(unchecked((long)0x8000000000000000UL)));
}
[Test]
public void RoundTripZigZag32() {
// Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
// were chosen semi-randomly via keyboard bashing.
Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));
Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));
Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));
Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));
}
[Test]
public void RoundTripZigZag64() {
Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));
Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));
Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));
Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));
Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));
Assert.AreEqual(856912304801416L, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));
Assert.AreEqual(-75123905439571256L, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
}
}
}

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
namespace Google.ProtocolBuffers.Collections {
[TestFixture]
public class PopsicleListTest {
[Test]
public void MutatingOperationsOnFrozenList() {
PopsicleList<string> list = new PopsicleList<string>();
list.MakeReadOnly();
AssertNotSupported(() => list.Add(""));
AssertNotSupported(() => list.Clear());
AssertNotSupported(() => list.Insert(0, ""));
AssertNotSupported(() => list.Remove(""));
AssertNotSupported(() => list.RemoveAt(0));
}
[Test]
public void NonMutatingOperationsOnFrozenList() {
PopsicleList<string> list = new PopsicleList<string>();
list.MakeReadOnly();
Assert.IsFalse(list.Contains(""));
Assert.AreEqual(0, list.Count);
list.CopyTo(new string[5], 0);
list.GetEnumerator();
Assert.AreEqual(-1, list.IndexOf(""));
Assert.IsTrue(list.IsReadOnly);
}
[Test]
public void MutatingOperationsOnFluidList() {
PopsicleList<string> list = new PopsicleList<string>();
list.Add("");
list.Clear();
list.Insert(0, "");
list.Remove("");
list.Add("x"); // Just to make the next call valid
list.RemoveAt(0);
}
[Test]
public void NonMutatingOperationsOnFluidList() {
PopsicleList<string> list = new PopsicleList<string>();
Assert.IsFalse(list.Contains(""));
Assert.AreEqual(0, list.Count);
list.CopyTo(new string[5], 0);
list.GetEnumerator();
Assert.AreEqual(-1, list.IndexOf(""));
Assert.IsFalse(list.IsReadOnly);
}
private static void AssertNotSupported(Action action) {
try {
action();
Assert.Fail("Expected NotSupportedException");
} catch (NotSupportedException) {
// Expected
}
}
}
}

@ -0,0 +1,274 @@
// 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;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
namespace Google.ProtocolBuffers {
/// <summary>
/// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the
/// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...)
/// </summary>
[TestFixture]
public class DescriptorsTest {
[Test]
public void FileDescriptor() {
FileDescriptor file = UnitTestProtoFile.Descriptor;
Assert.AreEqual("google/protobuf/unittest.proto", file.Name);
Assert.AreEqual("protobuf_unittest", file.Package);
Assert.AreEqual("UnittestProto", file.Options.JavaOuterClassname);
Assert.AreEqual("google/protobuf/unittest.proto", file.Proto.Name);
// TODO(jonskeet): Either change to expect 3 dependencies, or don't emit them.
// Assert.AreEqual(1, file.Dependencies.Count);
Assert.AreEqual(UnitTestImportProtoFile.Descriptor, file.Dependencies[2]);
MessageDescriptor messageType = TestAllTypes.Descriptor;
Assert.AreEqual(messageType, file.MessageTypes[0]);
Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
Assert.IsNull(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
Assert.IsNull(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes"));
for (int i = 0; i < file.MessageTypes.Count; i++) {
Assert.AreEqual(i, file.MessageTypes[i].Index);
}
Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum"));
Assert.IsNull(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
Assert.IsNull(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum"));
Assert.AreEqual(1, UnitTestImportProtoFile.Descriptor.EnumTypes.Count);
Assert.AreEqual("ImportEnum", UnitTestImportProtoFile.Descriptor.EnumTypes[0].Name);
for (int i = 0; i < file.EnumTypes.Count; i++) {
Assert.AreEqual(i, file.EnumTypes[i].Index);
}
ServiceDescriptor service = TestService.Descriptor;
Assert.AreEqual(service, file.Services[0]);
Assert.AreEqual(service, file.FindTypeByName<ServiceDescriptor>("TestService"));
Assert.IsNull(file.FindTypeByName<ServiceDescriptor>("NoSuchType"));
Assert.IsNull(file.FindTypeByName<ServiceDescriptor>("protobuf_unittest.TestService"));
Assert.AreEqual(0, UnitTestImportProtoFile.Descriptor.Services.Count);
for (int i = 0; i < file.Services.Count; i++) {
Assert.AreEqual(i, file.Services[i].Index);
}
FieldDescriptor extension = UnitTestProtoFile.OptionalInt32Extension.Descriptor;
Assert.AreEqual(extension, file.Extensions[0]);
Assert.AreEqual(extension, file.FindTypeByName<FieldDescriptor>("optional_int32_extension"));
Assert.IsNull(file.FindTypeByName<FieldDescriptor>("no_such_ext"));
Assert.IsNull(file.FindTypeByName<FieldDescriptor>("protobuf_unittest.optional_int32_extension"));
Assert.AreEqual(0, UnitTestImportProtoFile.Descriptor.Extensions.Count);
for (int i = 0; i < file.Extensions.Count; i++) {
Assert.AreEqual(i, file.Extensions[i].Index);
}
}
[Test]
public void MessageDescriptor() {
MessageDescriptor messageType = TestAllTypes.Descriptor;
MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor;
Assert.AreEqual("TestAllTypes", messageType.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName);
Assert.AreEqual(UnitTestProtoFile.Descriptor, messageType.File);
Assert.IsNull(messageType.ContainingType);
Assert.AreEqual(DescriptorProtos.MessageOptions.DefaultInstance, messageType.Options);
Assert.AreEqual("TestAllTypes", messageType.Proto.Name);
Assert.AreEqual("NestedMessage", nestedType.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName);
Assert.AreEqual(UnitTestProtoFile.Descriptor, nestedType.File);
Assert.AreEqual(messageType, nestedType.ContainingType);
FieldDescriptor field = messageType.Fields[0];
Assert.AreEqual("optional_int32", field.Name);
Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("optional_int32"));
Assert.IsNull(messageType.FindDescriptor<FieldDescriptor>("no_such_field"));
Assert.AreEqual(field, messageType.FindFieldByNumber(1));
Assert.IsNull(messageType.FindFieldByNumber(571283));
for (int i = 0; i < messageType.Fields.Count; i++) {
Assert.AreEqual(i, messageType.Fields[i].Index);
}
Assert.AreEqual(nestedType, messageType.NestedTypes[0]);
Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage"));
Assert.IsNull(messageType.FindDescriptor<MessageDescriptor>("NoSuchType"));
for (int i = 0; i < messageType.NestedTypes.Count; i++) {
Assert.AreEqual(i, messageType.NestedTypes[i].Index);
}
Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum"));
Assert.IsNull(messageType.FindDescriptor<EnumDescriptor>("NoSuchType"));
for (int i = 0; i < messageType.EnumTypes.Count; i++) {
Assert.AreEqual(i, messageType.EnumTypes[i].Index);
}
}
[Test]
public void FieldDescriptor() {
MessageDescriptor messageType = TestAllTypes.Descriptor;
FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("optional_int32");
FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("optional_nested_enum");
FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("optional_foreign_message");
FieldDescriptor cordField = messageType.FindDescriptor<FieldDescriptor>("optional_cord");
FieldDescriptor extension = UnitTestProtoFile.OptionalInt32Extension.Descriptor;
FieldDescriptor nestedExtension = TestRequired.Single.Descriptor;
Assert.AreEqual("optional_int32", primitiveField.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes.optional_int32",
primitiveField.FullName);
Assert.AreEqual(1, primitiveField.FieldNumber);
Assert.AreEqual(messageType, primitiveField.ContainingType);
Assert.AreEqual(UnitTestProtoFile.Descriptor, primitiveField.File);
Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
Assert.AreEqual(MappedType.Int32, primitiveField.MappedType);
Assert.AreEqual(DescriptorProtos.FieldOptions.DefaultInstance, primitiveField.Options);
Assert.IsFalse(primitiveField.IsExtension);
Assert.AreEqual("optional_int32", primitiveField.Proto.Name);
Assert.AreEqual("optional_nested_enum", enumField.Name);
Assert.AreEqual(FieldType.Enum, enumField.FieldType);
Assert.AreEqual(MappedType.Enum, enumField.MappedType);
// Assert.AreEqual(TestAllTypes.Types.NestedEnum.Descriptor, enumField.EnumType);
Assert.AreEqual("optional_foreign_message", messageField.Name);
Assert.AreEqual(FieldType.Message, messageField.FieldType);
Assert.AreEqual(MappedType.Message, messageField.MappedType);
Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType);
Assert.AreEqual("optional_cord", cordField.Name);
Assert.AreEqual(FieldType.String, cordField.FieldType);
Assert.AreEqual(MappedType.String, cordField.MappedType);
Assert.AreEqual(DescriptorProtos.FieldOptions.Types.CType.CORD, cordField.Options.Ctype);
Assert.AreEqual("optional_int32_extension", extension.Name);
Assert.AreEqual("protobuf_unittest.optional_int32_extension", extension.FullName);
Assert.AreEqual(1, extension.FieldNumber);
Assert.AreEqual(TestAllExtensions.Descriptor, extension.ContainingType);
Assert.AreEqual(UnitTestProtoFile.Descriptor, extension.File);
Assert.AreEqual(FieldType.Int32, extension.FieldType);
Assert.AreEqual(MappedType.Int32, extension.MappedType);
Assert.AreEqual(DescriptorProtos.FieldOptions.DefaultInstance,
extension.Options);
Assert.IsTrue(extension.IsExtension);
Assert.AreEqual(null, extension.ExtensionScope);
Assert.AreEqual("optional_int32_extension", extension.Proto.Name);
Assert.AreEqual("single", nestedExtension.Name);
Assert.AreEqual("protobuf_unittest.TestRequired.single",
nestedExtension.FullName);
Assert.AreEqual(TestRequired.Descriptor,
nestedExtension.ExtensionScope);
}
[Test]
public void FieldDescriptorLabel() {
FieldDescriptor requiredField =
TestRequired.Descriptor.FindDescriptor<FieldDescriptor>("a");
FieldDescriptor optionalField =
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("optional_int32");
FieldDescriptor repeatedField =
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32");
Assert.IsTrue(requiredField.IsRequired);
Assert.IsFalse(requiredField.IsRepeated);
Assert.IsFalse(optionalField.IsRequired);
Assert.IsFalse(optionalField.IsRepeated);
Assert.IsFalse(repeatedField.IsRequired);
Assert.IsTrue(repeatedField.IsRepeated);
}
[Test]
public void FieldDescriptorDefault() {
MessageDescriptor d = TestAllTypes.Descriptor;
Assert.IsFalse(d.FindDescriptor<FieldDescriptor>("optional_int32").HasDefaultValue);
Assert.AreEqual(0, d.FindDescriptor<FieldDescriptor>("optional_int32").DefaultValue);
Assert.IsTrue(d.FindDescriptor<FieldDescriptor>("default_int32").HasDefaultValue);
Assert.AreEqual(41, d.FindDescriptor<FieldDescriptor>("default_int32").DefaultValue);
d = TestExtremeDefaultValues.Descriptor;
Assert.AreEqual(ByteString.CopyFrom("\u0000\u0001\u0007\b\f\n\r\t\u000b\\\'\"\u00fe", Encoding.GetEncoding(28591)),
d.FindDescriptor<FieldDescriptor>("escaped_bytes").DefaultValue);
Assert.AreEqual(uint.MaxValue, d.FindDescriptor<FieldDescriptor>("large_uint32").DefaultValue);
Assert.AreEqual(ulong.MaxValue, d.FindDescriptor<FieldDescriptor>("large_uint64").DefaultValue);
}
[Test]
public void EnumDescriptor() {
// Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor
EnumDescriptor enumType = UnitTestProtoFile.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum");
EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum");
Assert.AreEqual("ForeignEnum", enumType.Name);
Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName);
Assert.AreEqual(UnitTestProtoFile.Descriptor, enumType.File);
Assert.IsNull(enumType.ContainingType);
Assert.AreEqual(DescriptorProtos.EnumOptions.DefaultInstance,
enumType.Options);
Assert.AreEqual("NestedEnum", nestedType.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum",
nestedType.FullName);
Assert.AreEqual(UnitTestProtoFile.Descriptor, nestedType.File);
Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType);
EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO");
Assert.AreEqual(value, enumType.Values[0]);
Assert.AreEqual("FOREIGN_FOO", value.Name);
Assert.AreEqual(4, value.Number);
Assert.AreEqual((int) ForeignEnum.FOREIGN_FOO, value.Number);
Assert.AreEqual(value, enumType.FindValueByNumber(4));
Assert.IsNull(enumType.FindValueByName("NO_SUCH_VALUE"));
for (int i = 0; i < enumType.Values.Count; i++) {
Assert.AreEqual(i, enumType.Values[i].Index);
}
}
[Test]
public void ServiceDescriptor() {
ServiceDescriptor service = TestService.Descriptor;
Assert.AreEqual("TestService", service.Name);
Assert.AreEqual("protobuf_unittest.TestService", service.FullName);
Assert.AreEqual(UnitTestProtoFile.Descriptor, service.File);
Assert.AreEqual(2, service.Methods.Count);
MethodDescriptor fooMethod = service.Methods[0];
Assert.AreEqual("Foo", fooMethod.Name);
Assert.AreEqual(FooRequest.Descriptor, fooMethod.InputType);
Assert.AreEqual(FooResponse.Descriptor, fooMethod.OutputType);
Assert.AreEqual(fooMethod, service.FindMethodByName("Foo"));
MethodDescriptor barMethod = service.Methods[1];
Assert.AreEqual("Bar", barMethod.Name);
Assert.AreEqual(BarRequest.Descriptor, barMethod.InputType);
Assert.AreEqual(BarResponse.Descriptor, barMethod.OutputType);
Assert.AreEqual(barMethod, service.FindMethodByName("Bar"));
Assert.IsNull(service.FindMethodByName("NoSuchMethod"));
for (int i = 0; i < service.Methods.Count; i++) {
Assert.AreEqual(i, service.Methods[i].Index);
}
}
}
}

@ -0,0 +1,114 @@
using Google.ProtocolBuffers.TestProtos;
// 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 NUnit.Framework;
namespace Google.ProtocolBuffers {
[TestFixture]
public class DynamicMessageTest {
private ReflectionTester reflectionTester;
private ReflectionTester extensionsReflectionTester;
[SetUp]
public void SetUp() {
reflectionTester = ReflectionTester.CreateTestAllTypesInstance();
extensionsReflectionTester = ReflectionTester.CreateTestAllExtensionsInstance();
}
[Test]
public void DynamicMessageAccessors() {
IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(builder);
IMessage message = builder.WeakBuild();
reflectionTester.AssertAllFieldsSetViaReflection(message);
}
[Test]
public void DynamicMessageExtensionAccessors() {
// We don't need to extensively test DynamicMessage's handling of
// extensions because, frankly, it doesn't do anything special with them.
// It treats them just like any other fields.
IBuilder builder = DynamicMessage.CreateBuilder(TestAllExtensions.Descriptor);
extensionsReflectionTester.SetAllFieldsViaReflection(builder);
IMessage message = builder.WeakBuild();
extensionsReflectionTester.AssertAllFieldsSetViaReflection(message);
}
[Test]
public void DynamicMessageRepeatedSetters() {
IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(builder);
reflectionTester.ModifyRepeatedFieldsViaReflection(builder);
IMessage message = builder.WeakBuild();
reflectionTester.AssertRepeatedFieldsModifiedViaReflection(message);
}
[Test]
public void DynamicMessageDefaults() {
reflectionTester.AssertClearViaReflection(DynamicMessage.GetDefaultInstance(TestAllTypes.Descriptor));
reflectionTester.AssertClearViaReflection(DynamicMessage.CreateBuilder(TestAllTypes.Descriptor).Build());
}
[Test]
public void DynamicMessageSerializedSize() {
TestAllTypes message = TestUtil.GetAllSet();
IBuilder dynamicBuilder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(dynamicBuilder);
IMessage dynamicMessage = dynamicBuilder.WeakBuild();
Assert.AreEqual(message.SerializedSize, dynamicMessage.SerializedSize);
}
[Test]
public void DynamicMessageSerialization() {
IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(builder);
IMessage message = builder.WeakBuild();
ByteString rawBytes = message.ToByteString();
TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
TestUtil.AssertAllFieldsSet(message2);
// In fact, the serialized forms should be exactly the same, byte-for-byte.
Assert.AreEqual(TestUtil.GetAllSet().ToByteString(), rawBytes);
}
[Test]
public void DynamicMessageParsing() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TestUtil.SetAllFields(builder);
TestAllTypes message = builder.Build();
ByteString rawBytes = message.ToByteString();
IMessage message2 = DynamicMessage.ParseFrom(TestAllTypes.Descriptor, rawBytes);
reflectionTester.AssertAllFieldsSetViaReflection(message2);
}
[Test]
public void DynamicMessageCopy() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TestUtil.SetAllFields(builder);
TestAllTypes message = builder.Build();
DynamicMessage copy = DynamicMessage.CreateBuilder(message).Build();
reflectionTester.AssertAllFieldsSetViaReflection(copy);
}
}
}

@ -0,0 +1,291 @@
// 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;
using System.Collections.Generic;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
[TestFixture]
public class GeneratedMessageTest {
ReflectionTester reflectionTester;
ReflectionTester extensionsReflectionTester;
[SetUp]
public void SetUp() {
reflectionTester = ReflectionTester.CreateTestAllTypesInstance();
extensionsReflectionTester = ReflectionTester.CreateTestAllExtensionsInstance();
}
[Test]
public void RepeatedAddPrimitiveBeforeBuild() {
TestAllTypes message = new TestAllTypes.Builder { RepeatedInt32List = { 1, 2, 3 } }.Build();
TestUtil.AssertEqual(new int[]{1, 2, 3}, message.RepeatedInt32List);
}
[Test]
public void AddPrimitiveFailsAfterBuild() {
TestAllTypes.Builder builder = new TestAllTypes.Builder();
IList<int> list = builder.RepeatedInt32List;
list.Add(1); // Fine
builder.Build();
try {
list.Add(2);
Assert.Fail("List should be frozen");
} catch (NotSupportedException) {
// Expected
}
}
[Test]
public void RepeatedAddMessageBeforeBuild() {
TestAllTypes message = new TestAllTypes.Builder {
RepeatedNestedMessageList = { new TestAllTypes.Types.NestedMessage.Builder { Bb = 10 }.Build() } }.Build();
Assert.AreEqual(1, message.RepeatedNestedMessageCount);
Assert.AreEqual(10, message.RepeatedNestedMessageList[0].Bb);
}
[Test]
public void AddMessageFailsAfterBuild() {
TestAllTypes.Builder builder = new TestAllTypes.Builder();
IList<TestAllTypes.Types.NestedMessage> list = builder.RepeatedNestedMessageList;
builder.Build();
try {
list.Add(new TestAllTypes.Types.NestedMessage.Builder { Bb = 10 }.Build());
Assert.Fail("List should be frozen");
} catch (NotSupportedException) {
// Expected
}
}
[Test]
public void DefaultInstance() {
Assert.AreSame(TestAllTypes.DefaultInstance, TestAllTypes.DefaultInstance.DefaultInstanceForType);
Assert.AreSame(TestAllTypes.DefaultInstance, TestAllTypes.CreateBuilder().DefaultInstanceForType);
}
[Test]
public void Accessors() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TestUtil.SetAllFields(builder);
TestAllTypes message = builder.Build();
TestUtil.AssertAllFieldsSet(message);
}
[Test]
public void RepeatedSetters() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TestUtil.SetAllFields(builder);
TestUtil.ModifyRepeatedFields(builder);
TestAllTypes message = builder.Build();
TestUtil.AssertRepeatedFieldsModified(message);
}
[Test]
public void RepeatedAppend() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
builder.AddRangeRepeatedInt32(new int[]{1, 2, 3, 4});
builder.AddRangeRepeatedForeignEnum((new ForeignEnum[] { ForeignEnum.FOREIGN_BAZ }));
ForeignMessage foreignMessage = ForeignMessage.CreateBuilder().SetC(12).Build();
builder.AddRangeRepeatedForeignMessage(new ForeignMessage[] {foreignMessage});
TestAllTypes message = builder.Build();
TestUtil.AssertEqual(message.RepeatedInt32List, new int[]{1, 2, 3, 4});
TestUtil.AssertEqual(message.RepeatedForeignEnumList, new ForeignEnum[] {ForeignEnum.FOREIGN_BAZ});
Assert.AreEqual(1, message.RepeatedForeignMessageCount);
Assert.AreEqual(12, message.GetRepeatedForeignMessage(0).C);
}
[Test]
public void SettingForeignMessageUsingBuilder() {
TestAllTypes message = TestAllTypes.CreateBuilder()
// Pass builder for foreign message instance.
.SetOptionalForeignMessage(ForeignMessage.CreateBuilder().SetC(123))
.Build();
TestAllTypes expectedMessage = TestAllTypes.CreateBuilder()
// Create expected version passing foreign message instance explicitly.
.SetOptionalForeignMessage(ForeignMessage.CreateBuilder().SetC(123).Build())
.Build();
Assert.AreEqual(expectedMessage, message);
}
[Test]
public void SettingRepeatedForeignMessageUsingBuilder() {
TestAllTypes message = TestAllTypes.CreateBuilder()
// Pass builder for foreign message instance.
.AddRepeatedForeignMessage(ForeignMessage.CreateBuilder().SetC(456))
.Build();
TestAllTypes expectedMessage = TestAllTypes.CreateBuilder()
// Create expected version passing foreign message instance explicitly.
.AddRepeatedForeignMessage(ForeignMessage.CreateBuilder().SetC(456).Build())
.Build();
Assert.AreEqual(expectedMessage, message);
}
[Test]
public void Defaults() {
TestUtil.AssertClear(TestAllTypes.DefaultInstance);
TestUtil.AssertClear(TestAllTypes.CreateBuilder().Build());
Assert.AreEqual("\u1234", TestExtremeDefaultValues.DefaultInstance.Utf8String);
}
[Test]
public void ReflectionGetters() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TestUtil.SetAllFields(builder);
TestAllTypes message = builder.Build();
reflectionTester.AssertAllFieldsSetViaReflection(message);
}
[Test]
public void ReflectionSetters() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
reflectionTester.SetAllFieldsViaReflection(builder);
TestAllTypes message = builder.Build();
TestUtil.AssertAllFieldsSet(message);
}
[Test]
public void ReflectionRepeatedSetters() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
reflectionTester.SetAllFieldsViaReflection(builder);
reflectionTester.ModifyRepeatedFieldsViaReflection(builder);
TestAllTypes message = builder.Build();
TestUtil.AssertRepeatedFieldsModified(message);
}
[Test]
public void ReflectionDefaults() {
reflectionTester.AssertClearViaReflection(TestAllTypes.DefaultInstance);
reflectionTester.AssertClearViaReflection(TestAllTypes.CreateBuilder().Build());
}
// =================================================================
// Extensions.
[Test]
public void ExtensionAccessors() {
TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
TestUtil.SetAllExtensions(builder);
TestAllExtensions message = builder.Build();
TestUtil.AssertAllExtensionsSet(message);
}
[Test]
public void ExtensionRepeatedSetters() {
TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
TestUtil.SetAllExtensions(builder);
TestUtil.ModifyRepeatedExtensions(builder);
TestAllExtensions message = builder.Build();
TestUtil.AssertRepeatedExtensionsModified(message);
}
[Test]
public void ExtensionDefaults() {
TestUtil.AssertExtensionsClear(TestAllExtensions.DefaultInstance);
TestUtil.AssertExtensionsClear(TestAllExtensions.CreateBuilder().Build());
}
[Test]
public void ExtensionReflectionGetters() {
TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
TestUtil.SetAllExtensions(builder);
TestAllExtensions message = builder.Build();
extensionsReflectionTester.AssertAllFieldsSetViaReflection(message);
}
[Test]
public void ExtensionReflectionSetters() {
TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
extensionsReflectionTester.SetAllFieldsViaReflection(builder);
TestAllExtensions message = builder.Build();
TestUtil.AssertAllExtensionsSet(message);
}
[Test]
public void ExtensionReflectionRepeatedSetters() {
TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
extensionsReflectionTester.SetAllFieldsViaReflection(builder);
extensionsReflectionTester.ModifyRepeatedFieldsViaReflection(builder);
TestAllExtensions message = builder.Build();
TestUtil.AssertRepeatedExtensionsModified(message);
}
[Test]
public void ExtensionReflectionDefaults() {
extensionsReflectionTester.AssertClearViaReflection(TestAllExtensions.DefaultInstance);
extensionsReflectionTester.AssertClearViaReflection(TestAllExtensions.CreateBuilder().Build());
}
[Test]
public void ClearExtension() {
// ClearExtension() is not actually used in TestUtil, so try it manually.
Assert.IsFalse(TestAllExtensions.CreateBuilder()
.SetExtension(UnitTestProtoFile.OptionalInt32Extension, 1)
.ClearExtension(UnitTestProtoFile.OptionalInt32Extension)
.HasExtension(UnitTestProtoFile.OptionalInt32Extension));
Assert.AreEqual(0, TestAllExtensions.CreateBuilder()
.AddExtension(UnitTestProtoFile.RepeatedInt32Extension, 1)
.ClearExtension(UnitTestProtoFile.RepeatedInt32Extension)
.GetExtensionCount(UnitTestProtoFile.RepeatedInt32Extension));
}
/* Removed multiple files option for the moment
[Test]
public void MultipleFilesOption() {
// We mostly just want to check that things compile.
MessageWithNoOuter message = MessageWithNoOuter.CreateBuilder()
.SetNested(MessageWithNoOuter.Types.NestedMessage.CreateBuilder().SetI(1))
.AddForeign(TestAllTypes.CreateBuilder().SetOptionalInt32(1))
.SetNestedEnum(MessageWithNoOuter.Types.NestedEnum.BAZ)
.SetForeignEnum(EnumWithNoOuter.BAR)
.Build();
Assert.AreEqual(message, MessageWithNoOuter.ParseFrom(message.ToByteString()));
Assert.AreEqual(MultiFileProto.Descriptor, MessageWithNoOuter.Descriptor.File);
FieldDescriptor field = MessageWithNoOuter.Descriptor.FindDescriptor<FieldDescriptor>("foreign_enum");
Assert.AreEqual(MultiFileProto.Descriptor.FindTypeByName<EnumDescriptor>("EnumWithNoOuter")
.FindValueByNumber((int)EnumWithNoOuter.BAR), message[field]);
Assert.AreEqual(MultiFileProto.Descriptor, ServiceWithNoOuter.Descriptor.File);
Assert.IsFalse(TestAllExtensions.DefaultInstance.HasExtension(MultiFileProto.ExtensionWithOuter));
}*/
[Test]
public void OptionalFieldWithRequiredSubfieldsOptimizedForSize() {
TestOptionalOptimizedForSize message = TestOptionalOptimizedForSize.DefaultInstance;
Assert.IsTrue(message.IsInitialized);
message = TestOptionalOptimizedForSize.CreateBuilder().SetO(
TestRequiredOptimizedForSize.CreateBuilder().BuildPartial()
).BuildPartial();
Assert.IsFalse(message.IsInitialized);
message = TestOptionalOptimizedForSize.CreateBuilder().SetO(
TestRequiredOptimizedForSize.CreateBuilder().SetX(5).BuildPartial()
).BuildPartial();
Assert.IsTrue(message.IsInitialized);
}
}
}

@ -0,0 +1,23 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using NestedMessage = Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage;
namespace Google.ProtocolBuffers {
[TestFixture]
public class MessageStreamIteratorTest {
[Test]
public void ThreeMessagesInMemory() {
MemoryStream stream = new MemoryStream(MessageStreamWriterTest.ThreeMessageData);
IEnumerable<NestedMessage> iterator = MessageStreamIterator<NestedMessage>.FromStreamProvider(() => stream);
List<NestedMessage> messages = new List<NestedMessage>(iterator);
Assert.AreEqual(3, messages.Count);
Assert.AreEqual(5, messages[0].Bb);
Assert.AreEqual(1500, messages[1].Bb);
Assert.IsFalse(messages[2].HasBb);
}
}
}

@ -0,0 +1,36 @@
using System.IO;
using NUnit.Framework;
using NestedMessage = Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage;
namespace Google.ProtocolBuffers {
[TestFixture]
public class MessageStreamWriterTest {
internal static readonly byte[] ThreeMessageData = new byte[] {
(1 << 3) | 2, 2, // Field 1, 2 bytes long (first message)
(1 << 3) | 0, 5, // Field 1, value 5
(1 << 3) | 2, 3, // Field 1, 3 bytes long (second message)
(1 << 3) | 0, (1500 & 0x7f) | 0x80, 1500 >> 7, // Field 1, value 1500
(1 << 3) | 2, 0, // Field 1, no data (third message)
};
[Test]
public void ThreeMessages() {
NestedMessage message1 = new NestedMessage.Builder { Bb = 5 }.Build();
NestedMessage message2 = new NestedMessage.Builder { Bb = 1500 }.Build();
NestedMessage message3 = new NestedMessage.Builder().Build();
byte[] data;
using (MemoryStream stream = new MemoryStream()) {
MessageStreamWriter<NestedMessage> writer = new MessageStreamWriter<NestedMessage>(stream);
writer.Write(message1);
writer.Write(message2);
writer.Write(message3);
writer.Flush();
data = stream.ToArray();
}
TestUtil.AssertEqualBytes(ThreeMessageData, data);
}
}
}

@ -0,0 +1,299 @@
// 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 Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
/// <summary>
/// Miscellaneous tests for message operations that apply to both
/// generated and dynamic messages.
/// </summary>
[TestFixture]
public class MessageTest {
// =================================================================
// Message-merging tests.
private static readonly TestAllTypes MergeSource = new TestAllTypes.Builder {
OptionalInt32 = 1,
OptionalString = "foo",
OptionalForeignMessage = ForeignMessage.DefaultInstance,
}.AddRepeatedString("bar").Build();
private static readonly TestAllTypes MergeDest = new TestAllTypes.Builder {
OptionalInt64 = 2,
OptionalString = "baz",
OptionalForeignMessage = new ForeignMessage.Builder { C=3 }.Build(),
}.AddRepeatedString("qux").Build();
private const string MergeResultText =
"optional_int32: 1\n" +
"optional_int64: 2\n" +
"optional_string: \"foo\"\n" +
"optional_foreign_message {\n" +
" c: 3\n" +
"}\n" +
"repeated_string: \"qux\"\n" +
"repeated_string: \"bar\"\n";
[Test]
public void MergeFrom() {
TestAllTypes result = TestAllTypes.CreateBuilder(MergeDest).MergeFrom(MergeSource).Build();
Assert.AreEqual(MergeResultText, result.ToString());
}
/// <summary>
/// Test merging a DynamicMessage into a GeneratedMessage.
/// As long as they have the same descriptor, this should work, but it is an
/// entirely different code path.
/// </summary>
[Test]
public void MergeFromDynamic() {
TestAllTypes result = (TestAllTypes) TestAllTypes.CreateBuilder(MergeDest)
.MergeFrom(DynamicMessage.CreateBuilder(MergeSource).Build())
.Build();
Assert.AreEqual(MergeResultText, result.ToString());
}
/// <summary>
/// Test merging two DynamicMessages.
/// </summary>
[Test]
public void DynamicMergeFrom() {
DynamicMessage result = (DynamicMessage) DynamicMessage.CreateBuilder(MergeDest)
.MergeFrom((DynamicMessage) DynamicMessage.CreateBuilder(MergeSource).Build())
.Build();
Assert.AreEqual(MergeResultText, result.ToString());
}
// =================================================================
// Required-field-related tests.
private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance;
private static readonly TestRequired TestRequiredInitialized = new TestRequired.Builder {
A = 1, B = 2, C = 3
}.Build();
[Test]
public void Initialization() {
TestRequired.Builder builder = TestRequired.CreateBuilder();
Assert.IsFalse(builder.IsInitialized);
builder.A = 1;
Assert.IsFalse(builder.IsInitialized);
builder.B = 1;
Assert.IsFalse(builder.IsInitialized);
builder.C = 1;
Assert.IsTrue(builder.IsInitialized);
}
[Test]
public void RequiredForeign() {
TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder();
Assert.IsTrue(builder.IsInitialized);
builder.SetOptionalMessage(TestRequiredUninitialized);
Assert.IsFalse(builder.IsInitialized);
builder.SetOptionalMessage(TestRequiredInitialized);
Assert.IsTrue(builder.IsInitialized);
builder.AddRepeatedMessage(TestRequiredUninitialized);
Assert.IsFalse(builder.IsInitialized);
builder.SetRepeatedMessage(0, TestRequiredInitialized);
Assert.IsTrue(builder.IsInitialized);
}
[Test]
public void RequiredExtension() {
TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
Assert.IsTrue(builder.IsInitialized);
builder.SetExtension(TestRequired.Single, TestRequiredUninitialized);
Assert.IsFalse(builder.IsInitialized);
builder.SetExtension(TestRequired.Single, TestRequiredInitialized);
Assert.IsTrue(builder.IsInitialized);
builder.AddExtension(TestRequired.Multi, TestRequiredUninitialized);
Assert.IsFalse(builder.IsInitialized);
builder.SetExtension(TestRequired.Multi, 0, TestRequiredInitialized);
Assert.IsTrue(builder.IsInitialized);
}
[Test]
public void RequiredDynamic() {
MessageDescriptor descriptor = TestRequired.Descriptor;
DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor);
Assert.IsFalse(builder.IsInitialized);
builder[descriptor.FindDescriptor<FieldDescriptor>("a")] = 1;
Assert.IsFalse(builder.IsInitialized);
builder[descriptor.FindDescriptor<FieldDescriptor>("b")] = 1;
Assert.IsFalse(builder.IsInitialized);
builder[descriptor.FindDescriptor<FieldDescriptor>("c")] = 1;
Assert.IsTrue(builder.IsInitialized);
}
[Test]
public void RequiredDynamicForeign() {
MessageDescriptor descriptor = TestRequiredForeign.Descriptor;
DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor);
Assert.IsTrue(builder.IsInitialized);
builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredUninitialized;
Assert.IsFalse(builder.IsInitialized);
builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredInitialized;
Assert.IsTrue(builder.IsInitialized);
builder.AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), TestRequiredUninitialized);
Assert.IsFalse(builder.IsInitialized);
builder.SetRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), 0, TestRequiredInitialized);
Assert.IsTrue(builder.IsInitialized);
}
[Test]
public void UninitializedException() {
try {
TestRequired.CreateBuilder().Build();
Assert.Fail("Should have thrown an exception.");
} catch (UninitializedMessageException e) {
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
[Test]
public void BuildPartial() {
// We're mostly testing that no exception is thrown.
TestRequired message = TestRequired.CreateBuilder().BuildPartial();
Assert.IsFalse(message.IsInitialized);
}
[Test]
public void NestedUninitializedException() {
try {
TestRequiredForeign.CreateBuilder()
.SetOptionalMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.Build();
Assert.Fail("Should have thrown an exception.");
} catch (UninitializedMessageException e) {
Assert.AreEqual(
"Message missing required fields: " +
"optional_message.a, " +
"optional_message.b, " +
"optional_message.c, " +
"repeated_message[0].a, " +
"repeated_message[0].b, " +
"repeated_message[0].c, " +
"repeated_message[1].a, " +
"repeated_message[1].b, " +
"repeated_message[1].c",
e.Message);
}
}
[Test]
public void BuildNestedPartial() {
// We're mostly testing that no exception is thrown.
TestRequiredForeign message =
TestRequiredForeign.CreateBuilder()
.SetOptionalMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.BuildPartial();
Assert.IsFalse(message.IsInitialized);
}
[Test]
public void ParseUnititialized() {
try {
TestRequired.ParseFrom(ByteString.Empty);
Assert.Fail("Should have thrown an exception.");
} catch (InvalidProtocolBufferException e) {
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
[Test]
public void ParseNestedUnititialized() {
ByteString data =
TestRequiredForeign.CreateBuilder()
.SetOptionalMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.BuildPartial().ToByteString();
try {
TestRequiredForeign.ParseFrom(data);
Assert.Fail("Should have thrown an exception.");
} catch (InvalidProtocolBufferException e) {
Assert.AreEqual(
"Message missing required fields: " +
"optional_message.a, " +
"optional_message.b, " +
"optional_message.c, " +
"repeated_message[0].a, " +
"repeated_message[0].b, " +
"repeated_message[0].c, " +
"repeated_message[1].a, " +
"repeated_message[1].b, " +
"repeated_message[1].c",
e.Message);
}
}
[Test]
public void DynamicUninitializedException() {
try {
DynamicMessage.CreateBuilder(TestRequired.Descriptor).Build();
Assert.Fail("Should have thrown an exception.");
} catch (UninitializedMessageException e) {
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
[Test]
public void DynamicBuildPartial() {
// We're mostly testing that no exception is thrown.
DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial();
Assert.IsFalse(message.Initialized);
}
[Test]
public void DynamicParseUnititialized() {
try {
MessageDescriptor descriptor = TestRequired.Descriptor;
DynamicMessage.ParseFrom(descriptor, ByteString.Empty);
Assert.Fail("Should have thrown an exception.");
} catch (InvalidProtocolBufferException e) {
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
}
}

@ -0,0 +1,36 @@
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("ProtocolBuffers.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProtocolBuffers.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("54e627c3-daaa-4850-82cf-f25b7f097e78")]
// 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")]

@ -0,0 +1,88 @@
<?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>{DD01ED24-3750-4567-9A23-1DB676A15610}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Google.ProtocolBuffers</RootNamespace>
<AssemblyName>Google.ProtocolBuffers.Test</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.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="AbstractMessageTest.cs" />
<Compile Include="ByteStringTest.cs" />
<Compile Include="CodedInputStreamTest.cs" />
<Compile Include="CodedOutputStreamTest.cs" />
<Compile Include="Collections\PopsicleListTest.cs" />
<Compile Include="DescriptorsTest.cs" />
<Compile Include="DynamicMessageTest.cs" />
<Compile Include="GeneratedMessageTest.cs" />
<Compile Include="MessageStreamIteratorTest.cs" />
<Compile Include="MessageStreamWriterTest.cs" />
<Compile Include="MessageTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReflectionTester.cs" />
<Compile Include="ServiceTest.cs" />
<Compile Include="TestProtos\UnitTestEmbedOptimizeForProtoFile.cs" />
<Compile Include="TestProtos\UnitTestImportProtoFile.cs" />
<Compile Include="TestProtos\UnitTestMessageSetProtoFile.cs" />
<Compile Include="TestProtos\UnitTestOptimizeForProtoFile.cs" />
<Compile Include="TestProtos\UnitTestProtoFile.cs" />
<Compile Include="TestUtil.cs" />
<Compile Include="TextFormatTest.cs" />
<Compile Include="UnknownFieldSetTest.cs" />
<Compile Include="WireFormatTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">
<Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
<Name>ProtocolBuffers</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Properties\Google.ProtocolBuffers.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>

@ -0,0 +1,798 @@
// 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;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
/// <summary>
/// Performs the same things that the methods of TestUtil do, but
/// via the reflection interface. This is its own class because it needs
/// to know what descriptor to use.
/// </summary>
internal class ReflectionTester {
private readonly MessageDescriptor baseDescriptor;
private readonly ExtensionRegistry extensionRegistry;
private readonly FileDescriptor file;
private readonly FileDescriptor importFile;
private readonly MessageDescriptor optionalGroup;
private readonly MessageDescriptor repeatedGroup;
private readonly MessageDescriptor nestedMessage;
private readonly MessageDescriptor foreignMessage;
private readonly MessageDescriptor importMessage;
private readonly FieldDescriptor groupA;
private readonly FieldDescriptor repeatedGroupA;
private readonly FieldDescriptor nestedB;
private readonly FieldDescriptor foreignC;
private readonly FieldDescriptor importD;
private readonly EnumDescriptor nestedEnum;
private readonly EnumDescriptor foreignEnum;
private readonly EnumDescriptor importEnum;
private readonly EnumValueDescriptor nestedFoo;
private readonly EnumValueDescriptor nestedBar;
private readonly EnumValueDescriptor nestedBaz;
private readonly EnumValueDescriptor foreignFoo;
private readonly EnumValueDescriptor foreignBar;
private readonly EnumValueDescriptor foreignBaz;
private readonly EnumValueDescriptor importFoo;
private readonly EnumValueDescriptor importBar;
private readonly EnumValueDescriptor importBaz;
/// <summary>
/// Constructs an instance that will expect messages using the given
/// descriptor. Normally <paramref name="baseDescriptor"/> should be
/// a descriptor for TestAllTypes. However, if extensionRegistry is non-null,
/// then baseDescriptor should be for TestAllExtensions instead, and instead of
/// reading and writing normal fields, the tester will read and write extensions.
/// All of the TestAllExtensions extensions must be registered in the registry.
/// </summary>
private ReflectionTester(MessageDescriptor baseDescriptor,
ExtensionRegistry extensionRegistry) {
this.baseDescriptor = baseDescriptor;
this.extensionRegistry = extensionRegistry;
this.file = baseDescriptor.File;
// TODO(jonskeet): We've got 3 dependencies, not 1 - because of the C# options. Hmm.
// Assert.AreEqual(1, file.Dependencies.Count);
// TODO(jonskeet): Find dependency by name instead of number?
this.importFile = file.Dependencies[2];
MessageDescriptor testAllTypes;
if (extensionRegistry == null) {
testAllTypes = baseDescriptor;
} else {
testAllTypes = file.FindTypeByName<MessageDescriptor>("TestAllTypes");
Assert.IsNotNull(testAllTypes);
}
if (extensionRegistry == null) {
this.optionalGroup =
baseDescriptor.FindDescriptor<MessageDescriptor>("OptionalGroup");
this.repeatedGroup =
baseDescriptor.FindDescriptor<MessageDescriptor>("RepeatedGroup");
} else {
this.optionalGroup =
file.FindTypeByName<MessageDescriptor>("OptionalGroup_extension");
this.repeatedGroup =
file.FindTypeByName<MessageDescriptor>("RepeatedGroup_extension");
}
this.nestedMessage = testAllTypes.FindDescriptor<MessageDescriptor>("NestedMessage");
this.foreignMessage = file.FindTypeByName<MessageDescriptor>("ForeignMessage");
this.importMessage = importFile.FindTypeByName<MessageDescriptor>("ImportMessage");
this.nestedEnum = testAllTypes.FindDescriptor<EnumDescriptor>("NestedEnum");
this.foreignEnum = file.FindTypeByName<EnumDescriptor>("ForeignEnum");
this.importEnum = importFile.FindTypeByName<EnumDescriptor>("ImportEnum");
Assert.IsNotNull(optionalGroup );
Assert.IsNotNull(repeatedGroup );
Assert.IsNotNull(nestedMessage );
Assert.IsNotNull(foreignMessage);
Assert.IsNotNull(importMessage );
Assert.IsNotNull(nestedEnum );
Assert.IsNotNull(foreignEnum );
Assert.IsNotNull(importEnum );
this.nestedB = nestedMessage.FindDescriptor<FieldDescriptor>("bb");
this.foreignC = foreignMessage.FindDescriptor<FieldDescriptor>("c");
this.importD = importMessage .FindDescriptor<FieldDescriptor>("d");
this.nestedFoo = nestedEnum.FindValueByName("FOO");
this.nestedBar = nestedEnum.FindValueByName("BAR");
this.nestedBaz = nestedEnum.FindValueByName("BAZ");
this.foreignFoo = foreignEnum.FindValueByName("FOREIGN_FOO");
this.foreignBar = foreignEnum.FindValueByName("FOREIGN_BAR");
this.foreignBaz = foreignEnum.FindValueByName("FOREIGN_BAZ");
this.importFoo = importEnum.FindValueByName("IMPORT_FOO");
this.importBar = importEnum.FindValueByName("IMPORT_BAR");
this.importBaz = importEnum.FindValueByName("IMPORT_BAZ");
this.groupA = optionalGroup.FindDescriptor<FieldDescriptor>("a");
this.repeatedGroupA = repeatedGroup.FindDescriptor<FieldDescriptor>("a");
Assert.IsNotNull(groupA );
Assert.IsNotNull(repeatedGroupA);
Assert.IsNotNull(nestedB );
Assert.IsNotNull(foreignC );
Assert.IsNotNull(importD );
Assert.IsNotNull(nestedFoo );
Assert.IsNotNull(nestedBar );
Assert.IsNotNull(nestedBaz );
Assert.IsNotNull(foreignFoo );
Assert.IsNotNull(foreignBar );
Assert.IsNotNull(foreignBaz );
Assert.IsNotNull(importFoo );
Assert.IsNotNull(importBar );
Assert.IsNotNull(importBaz );
}
/// <summary>
/// Creates an instance for the TestAllTypes message, with no extension registry.
/// </summary>
public static ReflectionTester CreateTestAllTypesInstance() {
return new ReflectionTester(TestAllTypes.Descriptor, null);
}
/// <summary>
/// Creates an instance for the TestAllExtensions message, with an
/// extension registry from TestUtil.CreateExtensionRegistry.
/// </summary>
public static ReflectionTester CreateTestAllExtensionsInstance() {
return new ReflectionTester(TestAllExtensions.Descriptor, TestUtil.CreateExtensionRegistry());
}
/// <summary>
/// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
/// </summary>
private FieldDescriptor f(String name) {
FieldDescriptor result;
if (extensionRegistry == null) {
result = baseDescriptor.FindDescriptor<FieldDescriptor>(name);
} else {
result = file.FindTypeByName<FieldDescriptor>(name + "_extension");
}
Assert.IsNotNull(result);
return result;
}
/// <summary>
/// Calls parent.CreateBuilderForField() or uses the extension registry
/// to find an appropriate builder, depending on what type is being tested.
/// </summary>
private IBuilder CreateBuilderForField(IBuilder parent, FieldDescriptor field) {
if (extensionRegistry == null) {
return parent.CreateBuilderForField(field);
} else {
ExtensionInfo extension = extensionRegistry[field.ContainingType, field.FieldNumber];
Assert.IsNotNull(extension);
Assert.IsNotNull(extension.DefaultInstance);
return extension.DefaultInstance.WeakCreateBuilderForType();
}
}
/// <summary>
/// Sets every field of the message to the values expected by
/// AssertAllFieldsSet, using the reflection interface.
/// </summary>
/// <param name="message"></param>
internal void SetAllFieldsViaReflection(IBuilder message) {
message[f("optional_int32" )] = 101 ;
message[f("optional_int64" )] = 102L;
message[f("optional_uint32" )] = 103U ;
message[f("optional_uint64" )] = 104UL;
message[f("optional_sint32" )] = 105 ;
message[f("optional_sint64" )] = 106L;
message[f("optional_fixed32" )] = 107U ;
message[f("optional_fixed64" )] = 108UL;
message[f("optional_sfixed32")] = 109 ;
message[f("optional_sfixed64")] = 110L;
message[f("optional_float" )] = 111F;
message[f("optional_double" )] = 112D;
message[f("optional_bool" )] = true;
message[f("optional_string" )] = "115";
message[f("optional_bytes")] = TestUtil.ToBytes("116");
message[f("optionalgroup")] = CreateBuilderForField(message, f("optionalgroup")).SetField(groupA, 117).WeakBuild();
message[f("optional_nested_message")] = CreateBuilderForField(message, f("optional_nested_message")).SetField(nestedB, 118).WeakBuild();
message[f("optional_foreign_message")] = CreateBuilderForField(message, f("optional_foreign_message")).SetField(foreignC, 119).WeakBuild();
message[f("optional_import_message")] = CreateBuilderForField(message, f("optional_import_message")).SetField(importD, 120).WeakBuild();
message[f("optional_nested_enum" )] = nestedBaz;
message[f("optional_foreign_enum")] = foreignBaz;
message[f("optional_import_enum" )] = importBaz;
message[f("optional_string_piece" )] = "124";
message[f("optional_cord" )] = "125";
// -----------------------------------------------------------------
message.WeakAddRepeatedField(f("repeated_int32" ), 201 );
message.WeakAddRepeatedField(f("repeated_int64" ), 202L);
message.WeakAddRepeatedField(f("repeated_uint32" ), 203U );
message.WeakAddRepeatedField(f("repeated_uint64" ), 204UL);
message.WeakAddRepeatedField(f("repeated_sint32" ), 205 );
message.WeakAddRepeatedField(f("repeated_sint64" ), 206L);
message.WeakAddRepeatedField(f("repeated_fixed32" ), 207U );
message.WeakAddRepeatedField(f("repeated_fixed64" ), 208UL);
message.WeakAddRepeatedField(f("repeated_sfixed32"), 209 );
message.WeakAddRepeatedField(f("repeated_sfixed64"), 210L);
message.WeakAddRepeatedField(f("repeated_float" ), 211F);
message.WeakAddRepeatedField(f("repeated_double" ), 212D);
message.WeakAddRepeatedField(f("repeated_bool" ), true);
message.WeakAddRepeatedField(f("repeated_string" ), "215");
message.WeakAddRepeatedField(f("repeated_bytes" ), TestUtil.ToBytes("216"));
message.WeakAddRepeatedField(f("repeatedgroup"), CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 217).WeakBuild());
message.WeakAddRepeatedField(f("repeated_nested_message"), CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 218).WeakBuild());
message.WeakAddRepeatedField(f("repeated_foreign_message"), CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 219).WeakBuild());
message.WeakAddRepeatedField(f("repeated_import_message"), CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 220).WeakBuild());
message.WeakAddRepeatedField(f("repeated_nested_enum" ), nestedBar);
message.WeakAddRepeatedField(f("repeated_foreign_enum"), foreignBar);
message.WeakAddRepeatedField(f("repeated_import_enum" ), importBar);
message.WeakAddRepeatedField(f("repeated_string_piece" ), "224");
message.WeakAddRepeatedField(f("repeated_cord" ), "225");
// Add a second one of each field.
message.WeakAddRepeatedField(f("repeated_int32" ), 301 );
message.WeakAddRepeatedField(f("repeated_int64" ), 302L);
message.WeakAddRepeatedField(f("repeated_uint32" ), 303U );
message.WeakAddRepeatedField(f("repeated_uint64" ), 304UL);
message.WeakAddRepeatedField(f("repeated_sint32" ), 305 );
message.WeakAddRepeatedField(f("repeated_sint64" ), 306L);
message.WeakAddRepeatedField(f("repeated_fixed32" ), 307U );
message.WeakAddRepeatedField(f("repeated_fixed64" ), 308UL);
message.WeakAddRepeatedField(f("repeated_sfixed32"), 309 );
message.WeakAddRepeatedField(f("repeated_sfixed64"), 310L);
message.WeakAddRepeatedField(f("repeated_float" ), 311F);
message.WeakAddRepeatedField(f("repeated_double" ), 312D);
message.WeakAddRepeatedField(f("repeated_bool" ), false);
message.WeakAddRepeatedField(f("repeated_string" ), "315");
message.WeakAddRepeatedField(f("repeated_bytes" ), TestUtil.ToBytes("316"));
message.WeakAddRepeatedField(f("repeatedgroup"),
CreateBuilderForField(message, f("repeatedgroup"))
.SetField(repeatedGroupA, 317).WeakBuild());
message.WeakAddRepeatedField(f("repeated_nested_message"),
CreateBuilderForField(message, f("repeated_nested_message"))
.SetField(nestedB, 318).WeakBuild());
message.WeakAddRepeatedField(f("repeated_foreign_message"),
CreateBuilderForField(message, f("repeated_foreign_message"))
.SetField(foreignC, 319).WeakBuild());
message.WeakAddRepeatedField(f("repeated_import_message"),
CreateBuilderForField(message, f("repeated_import_message"))
.SetField(importD, 320).WeakBuild());
message.WeakAddRepeatedField(f("repeated_nested_enum" ), nestedBaz);
message.WeakAddRepeatedField(f("repeated_foreign_enum"), foreignBaz);
message.WeakAddRepeatedField(f("repeated_import_enum" ), importBaz);
message.WeakAddRepeatedField(f("repeated_string_piece" ), "324");
message.WeakAddRepeatedField(f("repeated_cord" ), "325");
// -----------------------------------------------------------------
message[f("default_int32" )] = 401 ;
message[f("default_int64" )] = 402L;
message[f("default_uint32" )] = 403U ;
message[f("default_uint64" )] = 404UL;
message[f("default_sint32" )] = 405 ;
message[f("default_sint64" )] = 406L;
message[f("default_fixed32" )] = 407U ;
message[f("default_fixed64" )] = 408UL;
message[f("default_sfixed32")] = 409 ;
message[f("default_sfixed64")] = 410L;
message[f("default_float" )] = 411F;
message[f("default_double" )] = 412D;
message[f("default_bool" )] = false;
message[f("default_string" )] = "415";
message[f("default_bytes" )] = TestUtil.ToBytes("416");
message[f("default_nested_enum" )] = nestedFoo;
message[f("default_foreign_enum")] = foreignFoo;
message[f("default_import_enum" )] = importFoo;
message[f("default_string_piece" )] = "424";
message[f("default_cord" )] = "425";
}
// -------------------------------------------------------------------
/// <summary>
/// Modify the repeated fields of the specified message to contain the
/// values expected by AssertRepeatedFieldsModified, using the IBuilder
/// reflection interface.
/// </summary>
internal void ModifyRepeatedFieldsViaReflection(IBuilder message) {
message[f("repeated_int32" ), 1] = 501 ;
message[f("repeated_int64" ), 1] = 502L;
message[f("repeated_uint32" ), 1] = 503U ;
message[f("repeated_uint64" ), 1] = 504UL;
message[f("repeated_sint32" ), 1] = 505 ;
message[f("repeated_sint64" ), 1] = 506L;
message[f("repeated_fixed32" ), 1] = 507U ;
message[f("repeated_fixed64" ), 1] = 508UL;
message[f("repeated_sfixed32"), 1] = 509 ;
message[f("repeated_sfixed64"), 1] = 510L;
message[f("repeated_float" ), 1] = 511F;
message[f("repeated_double" ), 1] = 512D;
message[f("repeated_bool" ), 1] = true;
message[f("repeated_string" ), 1] = "515";
message.SetRepeatedField(f("repeated_bytes" ), 1, TestUtil.ToBytes("516"));
message.SetRepeatedField(f("repeatedgroup"), 1, CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 517).WeakBuild());
message.SetRepeatedField(f("repeated_nested_message"), 1, CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 518).WeakBuild());
message.SetRepeatedField(f("repeated_foreign_message"), 1, CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 519).WeakBuild());
message.SetRepeatedField(f("repeated_import_message"), 1, CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 520).WeakBuild());
message[f("repeated_nested_enum" ), 1] = nestedFoo;
message[f("repeated_foreign_enum"), 1] = foreignFoo;
message[f("repeated_import_enum" ), 1] = importFoo;
message[f("repeated_string_piece"), 1] = "524";
message[f("repeated_cord"), 1] = "525";
}
// -------------------------------------------------------------------
/// <summary>
/// Asserts that all fields of the specified message are set to the values
/// assigned by SetAllFields, using the IMessage reflection interface.
/// </summary>
public void AssertAllFieldsSetViaReflection(IMessage message) {
Assert.IsTrue(message.HasField(f("optional_int32" )));
Assert.IsTrue(message.HasField(f("optional_int64" )));
Assert.IsTrue(message.HasField(f("optional_uint32" )));
Assert.IsTrue(message.HasField(f("optional_uint64" )));
Assert.IsTrue(message.HasField(f("optional_sint32" )));
Assert.IsTrue(message.HasField(f("optional_sint64" )));
Assert.IsTrue(message.HasField(f("optional_fixed32" )));
Assert.IsTrue(message.HasField(f("optional_fixed64" )));
Assert.IsTrue(message.HasField(f("optional_sfixed32")));
Assert.IsTrue(message.HasField(f("optional_sfixed64")));
Assert.IsTrue(message.HasField(f("optional_float" )));
Assert.IsTrue(message.HasField(f("optional_double" )));
Assert.IsTrue(message.HasField(f("optional_bool" )));
Assert.IsTrue(message.HasField(f("optional_string" )));
Assert.IsTrue(message.HasField(f("optional_bytes" )));
Assert.IsTrue(message.HasField(f("optionalgroup" )));
Assert.IsTrue(message.HasField(f("optional_nested_message" )));
Assert.IsTrue(message.HasField(f("optional_foreign_message")));
Assert.IsTrue(message.HasField(f("optional_import_message" )));
Assert.IsTrue(((IMessage)message[f("optionalgroup")]).HasField(groupA));
Assert.IsTrue(((IMessage)message[f("optional_nested_message")]).HasField(nestedB));
Assert.IsTrue(((IMessage)message[f("optional_foreign_message")]).HasField(foreignC));
Assert.IsTrue(((IMessage)message[f("optional_import_message")]).HasField(importD));
Assert.IsTrue(message.HasField(f("optional_nested_enum" )));
Assert.IsTrue(message.HasField(f("optional_foreign_enum")));
Assert.IsTrue(message.HasField(f("optional_import_enum" )));
Assert.IsTrue(message.HasField(f("optional_string_piece")));
Assert.IsTrue(message.HasField(f("optional_cord")));
Assert.AreEqual(101 , message[f("optional_int32" )]);
Assert.AreEqual(102L , message[f("optional_int64" )]);
Assert.AreEqual(103U , message[f("optional_uint32" )]);
Assert.AreEqual(104UL , message[f("optional_uint64" )]);
Assert.AreEqual(105 , message[f("optional_sint32" )]);
Assert.AreEqual(106L , message[f("optional_sint64" )]);
Assert.AreEqual(107U , message[f("optional_fixed32" )]);
Assert.AreEqual(108UL , message[f("optional_fixed64" )]);
Assert.AreEqual(109 , message[f("optional_sfixed32")]);
Assert.AreEqual(110L , message[f("optional_sfixed64")]);
Assert.AreEqual(111F , message[f("optional_float" )]);
Assert.AreEqual(112D , message[f("optional_double" )]);
Assert.AreEqual(true , message[f("optional_bool" )]);
Assert.AreEqual("115", message[f("optional_string" )]);
Assert.AreEqual(TestUtil.ToBytes("116"), message[f("optional_bytes")]);
Assert.AreEqual(117,((IMessage)message[f("optionalgroup")])[groupA]);
Assert.AreEqual(118,((IMessage)message[f("optional_nested_message")])[nestedB]);
Assert.AreEqual(119,((IMessage)message[f("optional_foreign_message")])[foreignC]);
Assert.AreEqual(120,((IMessage)message[f("optional_import_message")])[importD]);
Assert.AreEqual( nestedBaz, message[f("optional_nested_enum" )]);
Assert.AreEqual(foreignBaz, message[f("optional_foreign_enum")]);
Assert.AreEqual( importBaz, message[f("optional_import_enum" )]);
Assert.AreEqual("124", message[f("optional_string_piece")]);
Assert.AreEqual("125", message[f("optional_cord")]);
// -----------------------------------------------------------------
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed32")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed64")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_float" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_double" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bool" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bytes" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeatedgroup" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_message" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_message")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_message" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_enum" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_enum" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_enum" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string_piece")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_cord")));
Assert.AreEqual(201 , message[f("repeated_int32" ), 0]);
Assert.AreEqual(202L , message[f("repeated_int64" ), 0]);
Assert.AreEqual(203U , message[f("repeated_uint32" ), 0]);
Assert.AreEqual(204UL, message[f("repeated_uint64" ), 0]);
Assert.AreEqual(205 , message[f("repeated_sint32" ), 0]);
Assert.AreEqual(206L , message[f("repeated_sint64" ), 0]);
Assert.AreEqual(207U , message[f("repeated_fixed32" ), 0]);
Assert.AreEqual(208UL, message[f("repeated_fixed64" ), 0]);
Assert.AreEqual(209 , message[f("repeated_sfixed32"), 0]);
Assert.AreEqual(210L , message[f("repeated_sfixed64"), 0]);
Assert.AreEqual(211F , message[f("repeated_float" ), 0]);
Assert.AreEqual(212D , message[f("repeated_double" ), 0]);
Assert.AreEqual(true , message[f("repeated_bool" ), 0]);
Assert.AreEqual("215", message[f("repeated_string" ), 0]);
Assert.AreEqual(TestUtil.ToBytes("216"), message[f("repeated_bytes"), 0]);
Assert.AreEqual(217,((IMessage)message[f("repeatedgroup"), 0])[repeatedGroupA]);
Assert.AreEqual(218,((IMessage)message[f("repeated_nested_message"), 0])[nestedB]);
Assert.AreEqual(219,((IMessage)message[f("repeated_foreign_message"), 0])[foreignC]);
Assert.AreEqual(220,((IMessage)message[f("repeated_import_message"), 0])[importD]);
Assert.AreEqual( nestedBar, message[f("repeated_nested_enum" ),0]);
Assert.AreEqual(foreignBar, message[f("repeated_foreign_enum"),0]);
Assert.AreEqual( importBar, message[f("repeated_import_enum" ),0]);
Assert.AreEqual("224", message[f("repeated_string_piece"), 0]);
Assert.AreEqual("225", message[f("repeated_cord"), 0]);
Assert.AreEqual(301 , message[f("repeated_int32" ), 1]);
Assert.AreEqual(302L , message[f("repeated_int64" ), 1]);
Assert.AreEqual(303U , message[f("repeated_uint32" ), 1]);
Assert.AreEqual(304UL, message[f("repeated_uint64" ), 1]);
Assert.AreEqual(305 , message[f("repeated_sint32" ), 1]);
Assert.AreEqual(306L , message[f("repeated_sint64" ), 1]);
Assert.AreEqual(307U , message[f("repeated_fixed32" ), 1]);
Assert.AreEqual(308UL, message[f("repeated_fixed64" ), 1]);
Assert.AreEqual(309 , message[f("repeated_sfixed32"), 1]);
Assert.AreEqual(310L , message[f("repeated_sfixed64"), 1]);
Assert.AreEqual(311F , message[f("repeated_float" ), 1]);
Assert.AreEqual(312D , message[f("repeated_double" ), 1]);
Assert.AreEqual(false, message[f("repeated_bool" ), 1]);
Assert.AreEqual("315", message[f("repeated_string" ), 1]);
Assert.AreEqual(TestUtil.ToBytes("316"), message[f("repeated_bytes"), 1]);
Assert.AreEqual(317,((IMessage)message[f("repeatedgroup"), 1])[repeatedGroupA]);
Assert.AreEqual(318,((IMessage)message[f("repeated_nested_message"), 1])[nestedB]);
Assert.AreEqual(319,((IMessage)message[f("repeated_foreign_message"), 1])[foreignC]);
Assert.AreEqual(320,((IMessage)message[f("repeated_import_message"), 1])[importD]);
Assert.AreEqual( nestedBaz, message[f("repeated_nested_enum" ),1]);
Assert.AreEqual(foreignBaz, message[f("repeated_foreign_enum"),1]);
Assert.AreEqual( importBaz, message[f("repeated_import_enum" ),1]);
Assert.AreEqual("324", message[f("repeated_string_piece"), 1]);
Assert.AreEqual("325", message[f("repeated_cord"), 1]);
// -----------------------------------------------------------------
Assert.IsTrue(message.HasField(f("default_int32" )));
Assert.IsTrue(message.HasField(f("default_int64" )));
Assert.IsTrue(message.HasField(f("default_uint32" )));
Assert.IsTrue(message.HasField(f("default_uint64" )));
Assert.IsTrue(message.HasField(f("default_sint32" )));
Assert.IsTrue(message.HasField(f("default_sint64" )));
Assert.IsTrue(message.HasField(f("default_fixed32" )));
Assert.IsTrue(message.HasField(f("default_fixed64" )));
Assert.IsTrue(message.HasField(f("default_sfixed32")));
Assert.IsTrue(message.HasField(f("default_sfixed64")));
Assert.IsTrue(message.HasField(f("default_float" )));
Assert.IsTrue(message.HasField(f("default_double" )));
Assert.IsTrue(message.HasField(f("default_bool" )));
Assert.IsTrue(message.HasField(f("default_string" )));
Assert.IsTrue(message.HasField(f("default_bytes" )));
Assert.IsTrue(message.HasField(f("default_nested_enum" )));
Assert.IsTrue(message.HasField(f("default_foreign_enum")));
Assert.IsTrue(message.HasField(f("default_import_enum" )));
Assert.IsTrue(message.HasField(f("default_string_piece")));
Assert.IsTrue(message.HasField(f("default_cord")));
Assert.AreEqual(401 , message[f("default_int32" )]);
Assert.AreEqual(402L , message[f("default_int64" )]);
Assert.AreEqual(403U , message[f("default_uint32" )]);
Assert.AreEqual(404UL, message[f("default_uint64" )]);
Assert.AreEqual(405 , message[f("default_sint32" )]);
Assert.AreEqual(406L , message[f("default_sint64" )]);
Assert.AreEqual(407U , message[f("default_fixed32" )]);
Assert.AreEqual(408UL, message[f("default_fixed64" )]);
Assert.AreEqual(409 , message[f("default_sfixed32")]);
Assert.AreEqual(410L , message[f("default_sfixed64")]);
Assert.AreEqual(411F , message[f("default_float" )]);
Assert.AreEqual(412D , message[f("default_double" )]);
Assert.AreEqual(false, message[f("default_bool" )]);
Assert.AreEqual("415", message[f("default_string" )]);
Assert.AreEqual(TestUtil.ToBytes("416"), message[f("default_bytes")]);
Assert.AreEqual( nestedFoo, message[f("default_nested_enum" )]);
Assert.AreEqual(foreignFoo, message[f("default_foreign_enum")]);
Assert.AreEqual( importFoo, message[f("default_import_enum" )]);
Assert.AreEqual("424", message[f("default_string_piece")]);
Assert.AreEqual("425", message[f("default_cord")]);
}
/// <summary>
/// Assert that all fields of the message are cleared, and that
/// getting the fields returns their default values, using the reflection interface.
/// </summary>
public void AssertClearViaReflection(IMessage message) {
// has_blah() should initially be false for all optional fields.
Assert.IsFalse(message.HasField(f("optional_int32" )));
Assert.IsFalse(message.HasField(f("optional_int64" )));
Assert.IsFalse(message.HasField(f("optional_uint32" )));
Assert.IsFalse(message.HasField(f("optional_uint64" )));
Assert.IsFalse(message.HasField(f("optional_sint32" )));
Assert.IsFalse(message.HasField(f("optional_sint64" )));
Assert.IsFalse(message.HasField(f("optional_fixed32" )));
Assert.IsFalse(message.HasField(f("optional_fixed64" )));
Assert.IsFalse(message.HasField(f("optional_sfixed32")));
Assert.IsFalse(message.HasField(f("optional_sfixed64")));
Assert.IsFalse(message.HasField(f("optional_float" )));
Assert.IsFalse(message.HasField(f("optional_double" )));
Assert.IsFalse(message.HasField(f("optional_bool" )));
Assert.IsFalse(message.HasField(f("optional_string" )));
Assert.IsFalse(message.HasField(f("optional_bytes" )));
Assert.IsFalse(message.HasField(f("optionalgroup" )));
Assert.IsFalse(message.HasField(f("optional_nested_message" )));
Assert.IsFalse(message.HasField(f("optional_foreign_message")));
Assert.IsFalse(message.HasField(f("optional_import_message" )));
Assert.IsFalse(message.HasField(f("optional_nested_enum" )));
Assert.IsFalse(message.HasField(f("optional_foreign_enum")));
Assert.IsFalse(message.HasField(f("optional_import_enum" )));
Assert.IsFalse(message.HasField(f("optional_string_piece")));
Assert.IsFalse(message.HasField(f("optional_cord")));
// Optional fields without defaults are set to zero or something like it.
Assert.AreEqual(0 , message[f("optional_int32" )]);
Assert.AreEqual(0L , message[f("optional_int64" )]);
Assert.AreEqual(0U , message[f("optional_uint32" )]);
Assert.AreEqual(0UL , message[f("optional_uint64" )]);
Assert.AreEqual(0 , message[f("optional_sint32" )]);
Assert.AreEqual(0L , message[f("optional_sint64" )]);
Assert.AreEqual(0U , message[f("optional_fixed32" )]);
Assert.AreEqual(0UL , message[f("optional_fixed64" )]);
Assert.AreEqual(0 , message[f("optional_sfixed32")]);
Assert.AreEqual(0L , message[f("optional_sfixed64")]);
Assert.AreEqual(0F , message[f("optional_float" )]);
Assert.AreEqual(0D , message[f("optional_double" )]);
Assert.AreEqual(false, message[f("optional_bool" )]);
Assert.AreEqual("" , message[f("optional_string" )]);
Assert.AreEqual(ByteString.Empty, message[f("optional_bytes")]);
// Embedded messages should also be clear.
Assert.IsFalse(((IMessage)message[f("optionalgroup")]).HasField(groupA));
Assert.IsFalse(((IMessage)message[f("optional_nested_message")])
.HasField(nestedB));
Assert.IsFalse(((IMessage)message[f("optional_foreign_message")])
.HasField(foreignC));
Assert.IsFalse(((IMessage)message[f("optional_import_message")])
.HasField(importD));
Assert.AreEqual(0,((IMessage)message[f("optionalgroup")])[groupA]);
Assert.AreEqual(0,((IMessage)message[f("optional_nested_message")])[nestedB]);
Assert.AreEqual(0,((IMessage)message[f("optional_foreign_message")])[foreignC]);
Assert.AreEqual(0,((IMessage)message[f("optional_import_message")])[importD]);
// Enums without defaults are set to the first value in the enum.
Assert.AreEqual( nestedFoo, message[f("optional_nested_enum" )]);
Assert.AreEqual(foreignFoo, message[f("optional_foreign_enum")]);
Assert.AreEqual( importFoo, message[f("optional_import_enum" )]);
Assert.AreEqual("", message[f("optional_string_piece")]);
Assert.AreEqual("", message[f("optional_cord")]);
// Repeated fields are empty.
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_int32" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_int64" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_uint32" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_uint64" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sint32" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sint64" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_fixed32" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_fixed64" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sfixed32")));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sfixed64")));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_float" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_double" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_bool" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_string" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_bytes" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeatedgroup" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_nested_message" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_foreign_message")));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_import_message" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_nested_enum" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_foreign_enum" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_import_enum" )));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_string_piece")));
Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_cord")));
// has_blah() should also be false for all default fields.
Assert.IsFalse(message.HasField(f("default_int32" )));
Assert.IsFalse(message.HasField(f("default_int64" )));
Assert.IsFalse(message.HasField(f("default_uint32" )));
Assert.IsFalse(message.HasField(f("default_uint64" )));
Assert.IsFalse(message.HasField(f("default_sint32" )));
Assert.IsFalse(message.HasField(f("default_sint64" )));
Assert.IsFalse(message.HasField(f("default_fixed32" )));
Assert.IsFalse(message.HasField(f("default_fixed64" )));
Assert.IsFalse(message.HasField(f("default_sfixed32")));
Assert.IsFalse(message.HasField(f("default_sfixed64")));
Assert.IsFalse(message.HasField(f("default_float" )));
Assert.IsFalse(message.HasField(f("default_double" )));
Assert.IsFalse(message.HasField(f("default_bool" )));
Assert.IsFalse(message.HasField(f("default_string" )));
Assert.IsFalse(message.HasField(f("default_bytes" )));
Assert.IsFalse(message.HasField(f("default_nested_enum" )));
Assert.IsFalse(message.HasField(f("default_foreign_enum")));
Assert.IsFalse(message.HasField(f("default_import_enum" )));
Assert.IsFalse(message.HasField(f("default_string_piece" )));
Assert.IsFalse(message.HasField(f("default_cord" )));
// Fields with defaults have their default values (duh).
Assert.AreEqual( 41 , message[f("default_int32" )]);
Assert.AreEqual( 42L , message[f("default_int64" )]);
Assert.AreEqual( 43U , message[f("default_uint32" )]);
Assert.AreEqual( 44UL , message[f("default_uint64" )]);
Assert.AreEqual(-45 , message[f("default_sint32" )]);
Assert.AreEqual( 46L , message[f("default_sint64" )]);
Assert.AreEqual( 47U , message[f("default_fixed32" )]);
Assert.AreEqual( 48UL , message[f("default_fixed64" )]);
Assert.AreEqual( 49 , message[f("default_sfixed32")]);
Assert.AreEqual(-50L , message[f("default_sfixed64")]);
Assert.AreEqual( 51.5F , message[f("default_float" )]);
Assert.AreEqual( 52e3D , message[f("default_double" )]);
Assert.AreEqual(true , message[f("default_bool" )]);
Assert.AreEqual("hello", message[f("default_string" )]);
Assert.AreEqual(TestUtil.ToBytes("world"), message[f("default_bytes")]);
Assert.AreEqual( nestedBar, message[f("default_nested_enum" )]);
Assert.AreEqual(foreignBar, message[f("default_foreign_enum")]);
Assert.AreEqual( importBar, message[f("default_import_enum" )]);
Assert.AreEqual("abc", message[f("default_string_piece")]);
Assert.AreEqual("123", message[f("default_cord")]);
}
// ---------------------------------------------------------------
internal void AssertRepeatedFieldsModifiedViaReflection(IMessage message) {
// ModifyRepeatedFields only sets the second repeated element of each
// field. In addition to verifying this, we also verify that the first
// element and size were *not* modified.
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed32" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed64" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed32")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed64")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_float" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_double" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bool" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bytes" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeatedgroup" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_message" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_message")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_message" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_enum" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_enum" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_enum" )));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string_piece")));
Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_cord")));
Assert.AreEqual(201 , message[f("repeated_int32" ), 0]);
Assert.AreEqual(202L , message[f("repeated_int64" ), 0]);
Assert.AreEqual(203U , message[f("repeated_uint32" ), 0]);
Assert.AreEqual(204UL, message[f("repeated_uint64" ), 0]);
Assert.AreEqual(205 , message[f("repeated_sint32" ), 0]);
Assert.AreEqual(206L , message[f("repeated_sint64" ), 0]);
Assert.AreEqual(207U , message[f("repeated_fixed32" ), 0]);
Assert.AreEqual(208UL, message[f("repeated_fixed64" ), 0]);
Assert.AreEqual(209 , message[f("repeated_sfixed32"), 0]);
Assert.AreEqual(210L , message[f("repeated_sfixed64"), 0]);
Assert.AreEqual(211F , message[f("repeated_float" ), 0]);
Assert.AreEqual(212D , message[f("repeated_double" ), 0]);
Assert.AreEqual(true , message[f("repeated_bool" ), 0]);
Assert.AreEqual("215", message[f("repeated_string" ), 0]);
Assert.AreEqual(TestUtil.ToBytes("216"), message[f("repeated_bytes"), 0]);
Assert.AreEqual(217,((IMessage)message[f("repeatedgroup"), 0])[repeatedGroupA]);
Assert.AreEqual(218,((IMessage)message[f("repeated_nested_message"), 0])[nestedB]);
Assert.AreEqual(219,((IMessage)message[f("repeated_foreign_message"), 0])[foreignC]);
Assert.AreEqual(220,((IMessage)message[f("repeated_import_message"), 0])[importD]);
Assert.AreEqual( nestedBar, message[f("repeated_nested_enum" ),0]);
Assert.AreEqual(foreignBar, message[f("repeated_foreign_enum"),0]);
Assert.AreEqual( importBar, message[f("repeated_import_enum" ),0]);
Assert.AreEqual("224", message[f("repeated_string_piece"), 0]);
Assert.AreEqual("225", message[f("repeated_cord"), 0]);
Assert.AreEqual(501 , message[f("repeated_int32" ), 1]);
Assert.AreEqual(502L , message[f("repeated_int64" ), 1]);
Assert.AreEqual(503U , message[f("repeated_uint32" ), 1]);
Assert.AreEqual(504UL, message[f("repeated_uint64" ), 1]);
Assert.AreEqual(505 , message[f("repeated_sint32" ), 1]);
Assert.AreEqual(506L , message[f("repeated_sint64" ), 1]);
Assert.AreEqual(507U , message[f("repeated_fixed32" ), 1]);
Assert.AreEqual(508UL, message[f("repeated_fixed64" ), 1]);
Assert.AreEqual(509 , message[f("repeated_sfixed32"), 1]);
Assert.AreEqual(510L , message[f("repeated_sfixed64"), 1]);
Assert.AreEqual(511F , message[f("repeated_float" ), 1]);
Assert.AreEqual(512D , message[f("repeated_double" ), 1]);
Assert.AreEqual(true , message[f("repeated_bool" ), 1]);
Assert.AreEqual("515", message[f("repeated_string" ), 1]);
Assert.AreEqual(TestUtil.ToBytes("516"), message[f("repeated_bytes"), 1]);
Assert.AreEqual(517,((IMessage)message[f("repeatedgroup"), 1])[repeatedGroupA]);
Assert.AreEqual(518,((IMessage)message[f("repeated_nested_message"), 1])[nestedB]);
Assert.AreEqual(519,((IMessage)message[f("repeated_foreign_message"), 1])[foreignC]);
Assert.AreEqual(520,((IMessage)message[f("repeated_import_message"), 1])[importD]);
Assert.AreEqual( nestedFoo, message[f("repeated_nested_enum" ),1]);
Assert.AreEqual(foreignFoo, message[f("repeated_foreign_enum"),1]);
Assert.AreEqual( importFoo, message[f("repeated_import_enum" ),1]);
Assert.AreEqual("524", message[f("repeated_string_piece"), 1]);
Assert.AreEqual("525", message[f("repeated_cord"), 1]);
}
}
}

@ -0,0 +1,178 @@
// 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;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Constraints;
namespace Google.ProtocolBuffers {
/// <summary>
/// Tests for generated service classes.
/// TODO(jonskeet): Convert the mocking tests using Rhino.Mocks.
/// </summary>
[TestFixture]
public class ServiceTest {
delegate void Action<T1, T2>(T1 t1, T2 t2);
private static readonly MethodDescriptor FooDescriptor = TestService.Descriptor.Methods[0];
private static readonly MethodDescriptor BarDescriptor = TestService.Descriptor.Methods[1];
[Test]
public void GetRequestPrototype() {
TestService service = new TestServiceImpl();
Assert.AreSame(service.GetRequestPrototype(FooDescriptor), FooRequest.DefaultInstance);
Assert.AreSame(service.GetRequestPrototype(BarDescriptor), BarRequest.DefaultInstance);
}
[Test]
public void GetResponsePrototype() {
TestService service = new TestServiceImpl();
Assert.AreSame(service.GetResponsePrototype(FooDescriptor), FooResponse.DefaultInstance);
Assert.AreSame(service.GetResponsePrototype(BarDescriptor), BarResponse.DefaultInstance);
}
[Test]
public void CallMethodFoo() {
MockRepository mocks = new MockRepository();
FooRequest fooRequest = FooRequest.CreateBuilder().Build();
FooResponse fooResponse = FooResponse.CreateBuilder().Build();
IRpcController controller = mocks.StrictMock<IRpcController>();
bool fooCalled = false;
TestService service = new TestServiceImpl((request, responseAction) => {
Assert.AreSame(fooRequest, request);
fooCalled = true;
responseAction(fooResponse);
}, null, controller);
bool doneHandlerCalled = false;
Action<IMessage> doneHandler = (response => {
Assert.AreSame(fooResponse, response);
doneHandlerCalled = true;
});
using (mocks.Record()) {
// No mock interactions to record
}
service.CallMethod(FooDescriptor, controller, fooRequest, doneHandler);
Assert.IsTrue(doneHandlerCalled);
Assert.IsTrue(fooCalled);
mocks.VerifyAll();
}
delegate void CallFooDelegate(MethodDescriptor descriptor, IRpcController controller,
IMessage request, IMessage response, Action<IMessage> doneHandler);
/// <summary>
/// Tests the generated stub handling of Foo. By this stage we're reasonably confident
/// that the choice between Foo and Bar is arbitrary, hence the lack of a corresponding Bar
/// test.
/// </summary>
[Test]
public void GeneratedStubFooCall() {
FooRequest fooRequest = FooRequest.CreateBuilder().Build();
MockRepository mocks = new MockRepository();
IRpcChannel mockChannel = mocks.StrictMock<IRpcChannel>();
IRpcController mockController = mocks.StrictMock<IRpcController>();
TestService service = TestService.CreateStub(mockChannel);
Action<FooResponse> doneHandler = mocks.StrictMock<Action<FooResponse>>();
using (mocks.Record()) {
// Nasty way of mocking out "the channel calls the done handler".
Expect.Call(() => mockChannel.CallMethod(null, null, null, null, null))
.IgnoreArguments()
.Constraints(Is.Same(FooDescriptor), Is.Same(mockController), Is.Same(fooRequest),
Is.Same(FooResponse.DefaultInstance), Is.Anything())
.Do((CallFooDelegate) ((p1, p2, p3, response, done) => done(response)));
doneHandler.Invoke(FooResponse.DefaultInstance);
}
service.Foo(mockController, fooRequest, doneHandler);
mocks.VerifyAll();
}
[Test]
public void CallMethodBar() {
MockRepository mocks = new MockRepository();
BarRequest barRequest = BarRequest.CreateBuilder().Build();
BarResponse barResponse = BarResponse.CreateBuilder().Build();
IRpcController controller = mocks.StrictMock<IRpcController>();
bool barCalled = false;
TestService service = new TestServiceImpl(null, (request, responseAction) => {
Assert.AreSame(barRequest, request);
barCalled = true;
responseAction(barResponse);
}, controller);
bool doneHandlerCalled = false;
Action<IMessage> doneHandler = (response => {
Assert.AreSame(barResponse, response);
doneHandlerCalled = true;
});
using (mocks.Record()) {
// No mock interactions to record
}
service.CallMethod(BarDescriptor, controller, barRequest, doneHandler);
Assert.IsTrue(doneHandlerCalled);
Assert.IsTrue(barCalled);
mocks.VerifyAll();
}
class TestServiceImpl : TestService {
private readonly Action<FooRequest, Action<FooResponse>> fooHandler;
private readonly Action<BarRequest, Action<BarResponse>> barHandler;
private readonly IRpcController expectedController;
internal TestServiceImpl() {
}
internal TestServiceImpl(Action<FooRequest, Action<FooResponse>> fooHandler,
Action<BarRequest, Action<BarResponse>> barHandler,
IRpcController expectedController) {
this.fooHandler = fooHandler;
this.barHandler = barHandler;
this.expectedController = expectedController;
}
public override void Foo(IRpcController controller, FooRequest request, Action<FooResponse> done) {
Assert.AreSame(expectedController, controller);
fooHandler(request, done);
}
public override void Bar(IRpcController controller, BarRequest request, Action<BarResponse> done) {
Assert.AreSame(expectedController, controller);
barHandler(request, done);
}
}
}
}

@ -0,0 +1,324 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace Google.ProtocolBuffers.TestProtos {
public static partial class UnitTestEmbedOptimizeForProtoFile {
#region Descriptor
public static pbd::FileDescriptor Descriptor {
get { return descriptor; }
}
private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(
global::System.Convert.FromBase64String(
"CjFnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfZW1iZWRfb3B0aW1pemVfZm9y" +
"LnByb3RvEhFwcm90b2J1Zl91bml0dGVzdBokZ29vZ2xlL3Byb3RvYnVmL2Nz" +
"aGFycF9vcHRpb25zLnByb3RvGiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRv" +
"ci5wcm90bxorZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X29wdGltaXplX2Zv" +
"ci5wcm90byKhAQoZVGVzdEVtYmVkT3B0aW1pemVkRm9yU2l6ZRJBChBvcHRp" +
"b25hbF9tZXNzYWdlGAEgASgLMicucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9w" +
"dGltaXplZEZvclNpemUSQQoQcmVwZWF0ZWRfbWVzc2FnZRgCIAMoCzInLnBy" +
"b3RvYnVmX3VuaXR0ZXN0LlRlc3RPcHRpbWl6ZWRGb3JTaXplQkxIAYLiCSFH" +
"b29nbGUuUHJvdG9jb2xCdWZmZXJzLlRlc3RQcm90b3OK4gkhVW5pdFRlc3RF" +
"bWJlZE9wdGltaXplRm9yUHJvdG9GaWxl"),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
global::Google.ProtocolBuffers.TestProtos.UnitTestOptimizeForProtoFile.Descriptor,
});
#endregion
#region Static variables
internal static readonly pbd::MessageDescriptor internal__static_protobuf_unittest_TestEmbedOptimizedForSize__Descriptor
= Descriptor.MessageTypes[0];
internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize.Builder> internal__static_protobuf_unittest_TestEmbedOptimizedForSize__FieldAccessorTable
= new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize.Builder>(internal__static_protobuf_unittest_TestEmbedOptimizedForSize__Descriptor,
new string[] { "OptionalMessage", "RepeatedMessage", });
#endregion
}
#region Messages
public sealed partial class TestEmbedOptimizedForSize : pb::GeneratedMessage<TestEmbedOptimizedForSize, TestEmbedOptimizedForSize.Builder> {
private static readonly TestEmbedOptimizedForSize defaultInstance = new Builder().BuildPartial();
public static TestEmbedOptimizedForSize DefaultInstance {
get { return defaultInstance; }
}
public override TestEmbedOptimizedForSize DefaultInstanceForType {
get { return defaultInstance; }
}
protected override TestEmbedOptimizedForSize ThisMessage {
get { return this; }
}
public static pbd::MessageDescriptor Descriptor {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestEmbedOptimizeForProtoFile.internal__static_protobuf_unittest_TestEmbedOptimizedForSize__Descriptor; }
}
protected override pb::FieldAccess.FieldAccessorTable<TestEmbedOptimizedForSize, TestEmbedOptimizedForSize.Builder> InternalFieldAccessors {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestEmbedOptimizeForProtoFile.internal__static_protobuf_unittest_TestEmbedOptimizedForSize__FieldAccessorTable; }
}
private bool hasOptionalMessage;
private global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance;
public bool HasOptionalMessage {
get { return hasOptionalMessage; }
}
public global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize OptionalMessage {
get { return optionalMessage_; }
}
private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> repeatedMessage_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>();
public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> RepeatedMessageList {
get { return repeatedMessage_; }
}
public int RepeatedMessageCount {
get { return repeatedMessage_.Count; }
}
public global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize GetRepeatedMessage(int index) {
return repeatedMessage_[index];
}
public override bool IsInitialized {
get {
if (HasOptionalMessage) {
if (!OptionalMessage.IsInitialized) return false;
}
foreach (global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize element in RepeatedMessageList) {
if (!element.IsInitialized) return false;
}
return true;
}
}
public override void WriteTo(pb::CodedOutputStream output) {
if (HasOptionalMessage) {
output.WriteMessage(1, OptionalMessage);
}
foreach (global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize element in RepeatedMessageList) {
output.WriteMessage(2, element);
}
UnknownFields.WriteTo(output);
}
private int memoizedSerializedSize = -1;
public override int SerializedSize {
get {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (HasOptionalMessage) {
size += pb::CodedOutputStream.ComputeMessageSize(1, OptionalMessage);
}
foreach (global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize element in RepeatedMessageList) {
size += pb::CodedOutputStream.ComputeMessageSize(2, element);
}
size += UnknownFields.SerializedSize;
memoizedSerializedSize = size;
return size;
}
}
public static TestEmbedOptimizedForSize ParseFrom(pb::ByteString data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(global::System.IO.Stream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static Builder CreateBuilder() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(TestEmbedOptimizedForSize prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<TestEmbedOptimizedForSize, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
public Builder() {}
TestEmbedOptimizedForSize result = new TestEmbedOptimizedForSize();
protected override TestEmbedOptimizedForSize MessageBeingBuilt {
get { return result; }
}
public override Builder Clear() {
result = new TestEmbedOptimizedForSize();
return this;
}
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
public override pbd::MessageDescriptor DescriptorForType {
get { return TestEmbedOptimizedForSize.Descriptor; }
}
public override TestEmbedOptimizedForSize DefaultInstanceForType {
get { return TestEmbedOptimizedForSize.DefaultInstance; }
}
public override TestEmbedOptimizedForSize BuildPartial() {
result.repeatedMessage_.MakeReadOnly();
TestEmbedOptimizedForSize returnMe = result;
result = null;
return returnMe;
}
public override Builder MergeFrom(pb::IMessage other) {
if (other is TestEmbedOptimizedForSize) {
return MergeFrom((TestEmbedOptimizedForSize) other);
} else {
base.MergeFrom(other);
return this;
}
}
public override Builder MergeFrom(TestEmbedOptimizedForSize other) {
if (other == TestEmbedOptimizedForSize.DefaultInstance) return this;
if (other.HasOptionalMessage) {
MergeOptionalMessage(other.OptionalMessage);
}
if (other.repeatedMessage_.Count != 0) {
base.AddRange(other.repeatedMessage_, result.repeatedMessage_);
}
this.MergeUnknownFields(other.UnknownFields);
return this;
}
public override Builder MergeFrom(pb::CodedInputStream input) {
return MergeFrom(input, pb::ExtensionRegistry.Empty);
}
public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
while (true) {
uint tag = input.ReadTag();
switch (tag) {
case 0: {
this.UnknownFields = unknownFields.Build();
return this;
}
default: {
if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) {
this.UnknownFields = unknownFields.Build();
return this;
}
break;
}
case 10: {
global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.CreateBuilder();
if (HasOptionalMessage) {
subBuilder.MergeFrom(OptionalMessage);
}
input.ReadMessage(subBuilder, extensionRegistry);
OptionalMessage = subBuilder.BuildPartial();
break;
}
case 18: {
global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.CreateBuilder();
input.ReadMessage(subBuilder, extensionRegistry);
AddRepeatedMessage(subBuilder.BuildPartial());
break;
}
}
}
}
public bool HasOptionalMessage {
get { return result.HasOptionalMessage; }
}
public global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize OptionalMessage {
get { return result.OptionalMessage; }
set { SetOptionalMessage(value); }
}
public Builder SetOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
result.hasOptionalMessage = true;
result.optionalMessage_ = value;
return this;
}
public Builder SetOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
result.hasOptionalMessage = true;
result.optionalMessage_ = builderForValue.Build();
return this;
}
public Builder MergeOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
if (result.HasOptionalMessage &&
result.optionalMessage_ != global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance) {
result.optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.CreateBuilder(result.optionalMessage_).MergeFrom(value).BuildPartial();
} else {
result.optionalMessage_ = value;
}
result.hasOptionalMessage = true;
return this;
}
public Builder ClearOptionalMessage() {
result.hasOptionalMessage = false;
result.optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance;
return this;
}
public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> RepeatedMessageList {
get { return result.repeatedMessage_; }
}
public int RepeatedMessageCount {
get { return result.RepeatedMessageCount; }
}
public global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize GetRepeatedMessage(int index) {
return result.GetRepeatedMessage(index);
}
public Builder SetRepeatedMessage(int index, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
result.repeatedMessage_[index] = value;
return this;
}
public Builder SetRepeatedMessage(int index, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
result.repeatedMessage_[index] = builderForValue.Build();
return this;
}
public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
result.repeatedMessage_.Add(value);
return this;
}
public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
result.repeatedMessage_.Add(builderForValue.Build());
return this;
}
public Builder AddRangeRepeatedMessage(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> values) {
base.AddRange(values, result.repeatedMessage_);
return this;
}
public Builder ClearRepeatedMessage() {
result.repeatedMessage_.Clear();
return this;
}
}
}
#endregion
}

@ -0,0 +1,243 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace Google.ProtocolBuffers.TestProtos {
public static partial class UnitTestImportProtoFile {
#region Descriptor
public static pbd::FileDescriptor Descriptor {
get { return descriptor; }
}
private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(
global::System.Convert.FromBase64String(
"CiVnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0LnByb3RvEhhwcm90" +
"b2J1Zl91bml0dGVzdF9pbXBvcnQaJGdvb2dsZS9wcm90b2J1Zi9jc2hhcnBf" +
"b3B0aW9ucy5wcm90bxogZ29vZ2xlL3Byb3RvYnVmL2Rlc2NyaXB0b3IucHJv" +
"dG8iGgoNSW1wb3J0TWVzc2FnZRIJCgFkGAEgASgFKjwKCkltcG9ydEVudW0S" +
"DgoKSU1QT1JUX0ZPTxAHEg4KCklNUE9SVF9CQVIQCBIOCgpJTVBPUlRfQkFa" +
"EAlCXAoYY29tLmdvb2dsZS5wcm90b2J1Zi50ZXN0SAGC4gkhR29vZ2xlLlBy" +
"b3RvY29sQnVmZmVycy5UZXN0UHJvdG9ziuIJF1VuaXRUZXN0SW1wb3J0UHJv" +
"dG9GaWxl"),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
});
#endregion
#region Static variables
internal static readonly pbd::MessageDescriptor internal__static_protobuf_unittest_import_ImportMessage__Descriptor
= Descriptor.MessageTypes[0];
internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ImportMessage, global::Google.ProtocolBuffers.TestProtos.ImportMessage.Builder> internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable
= new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ImportMessage, global::Google.ProtocolBuffers.TestProtos.ImportMessage.Builder>(internal__static_protobuf_unittest_import_ImportMessage__Descriptor,
new string[] { "D", });
#endregion
}
#region Enums
public enum ImportEnum {
IMPORT_FOO = 7,
IMPORT_BAR = 8,
IMPORT_BAZ = 9,
}
#endregion
#region Messages
public sealed partial class ImportMessage : pb::GeneratedMessage<ImportMessage, ImportMessage.Builder> {
private static readonly ImportMessage defaultInstance = new Builder().BuildPartial();
public static ImportMessage DefaultInstance {
get { return defaultInstance; }
}
public override ImportMessage DefaultInstanceForType {
get { return defaultInstance; }
}
protected override ImportMessage ThisMessage {
get { return this; }
}
public static pbd::MessageDescriptor Descriptor {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestImportProtoFile.internal__static_protobuf_unittest_import_ImportMessage__Descriptor; }
}
protected override pb::FieldAccess.FieldAccessorTable<ImportMessage, ImportMessage.Builder> InternalFieldAccessors {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestImportProtoFile.internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable; }
}
private bool hasD;
private int d_ = 0;
public bool HasD {
get { return hasD; }
}
public int D {
get { return d_; }
}
public override bool IsInitialized {
get {
return true;
}
}
public override void WriteTo(pb::CodedOutputStream output) {
if (HasD) {
output.WriteInt32(1, D);
}
UnknownFields.WriteTo(output);
}
private int memoizedSerializedSize = -1;
public override int SerializedSize {
get {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (HasD) {
size += pb::CodedOutputStream.ComputeInt32Size(1, D);
}
size += UnknownFields.SerializedSize;
memoizedSerializedSize = size;
return size;
}
}
public static ImportMessage ParseFrom(pb::ByteString data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static ImportMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static ImportMessage ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static ImportMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static ImportMessage ParseFrom(global::System.IO.Stream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static ImportMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static ImportMessage ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static ImportMessage ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static Builder CreateBuilder() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(ImportMessage prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<ImportMessage, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
public Builder() {}
ImportMessage result = new ImportMessage();
protected override ImportMessage MessageBeingBuilt {
get { return result; }
}
public override Builder Clear() {
result = new ImportMessage();
return this;
}
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
public override pbd::MessageDescriptor DescriptorForType {
get { return ImportMessage.Descriptor; }
}
public override ImportMessage DefaultInstanceForType {
get { return ImportMessage.DefaultInstance; }
}
public override ImportMessage BuildPartial() {
ImportMessage returnMe = result;
result = null;
return returnMe;
}
public override Builder MergeFrom(pb::IMessage other) {
if (other is ImportMessage) {
return MergeFrom((ImportMessage) other);
} else {
base.MergeFrom(other);
return this;
}
}
public override Builder MergeFrom(ImportMessage other) {
if (other == ImportMessage.DefaultInstance) return this;
if (other.HasD) {
D = other.D;
}
this.MergeUnknownFields(other.UnknownFields);
return this;
}
public override Builder MergeFrom(pb::CodedInputStream input) {
return MergeFrom(input, pb::ExtensionRegistry.Empty);
}
public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
pb::UnknownFieldSet.Builder unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
while (true) {
uint tag = input.ReadTag();
switch (tag) {
case 0: {
this.UnknownFields = unknownFields.Build();
return this;
}
default: {
if (!ParseUnknownField(input, unknownFields, extensionRegistry, tag)) {
this.UnknownFields = unknownFields.Build();
return this;
}
break;
}
case 8: {
D = input.ReadInt32();
break;
}
}
}
}
public bool HasD {
get { return result.HasD; }
}
public int D {
get { return result.D; }
set { SetD(value); }
}
public Builder SetD(int value) {
result.hasD = true;
result.d_ = value;
return this;
}
public Builder ClearD() {
result.hasD = false;
result.d_ = 0;
return this;
}
}
}
#endregion
}

@ -0,0 +1,467 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace Google.ProtocolBuffers.TestProtos {
public static partial class UnitTestOptimizeForProtoFile {
#region Descriptor
public static pbd::FileDescriptor Descriptor {
get { return descriptor; }
}
private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(
global::System.Convert.FromBase64String(
"Citnb29nbGUvcHJvdG9idWYvdW5pdHRlc3Rfb3B0aW1pemVfZm9yLnByb3Rv" +
"EhFwcm90b2J1Zl91bml0dGVzdBokZ29vZ2xlL3Byb3RvYnVmL2NzaGFycF9v" +
"cHRpb25zLnByb3RvGiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90" +
"bxoeZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0LnByb3RvIp4BChRUZXN0T3B0" +
"aW1pemVkRm9yU2l6ZRIJCgFpGAEgASgFEi4KA21zZxgTIAEoCzIhLnByb3Rv" +
"YnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlKgkI6AcQgICAgAIyQAoOdGVz" +
"dF9leHRlbnNpb24SJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0T3B0aW1pemVk" +
"Rm9yU2l6ZRjSCSABKAUiKQocVGVzdFJlcXVpcmVkT3B0aW1pemVkRm9yU2l6" +
"ZRIJCgF4GAEgAigFIloKHFRlc3RPcHRpb25hbE9wdGltaXplZEZvclNpemUS" +
"OgoBbxgBIAEoCzIvLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZE9w" +
"dGltaXplZEZvclNpemVCR0gCguIJIUdvb2dsZS5Qcm90b2NvbEJ1ZmZlcnMu" +
"VGVzdFByb3Rvc4riCRxVbml0VGVzdE9wdGltaXplRm9yUHJvdG9GaWxl"),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
global::Google.ProtocolBuffers.TestProtos.UnitTestProtoFile.Descriptor,
});
#endregion
#region Static variables
internal static readonly pbd::MessageDescriptor internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor
= Descriptor.MessageTypes[0];
internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder> internal__static_protobuf_unittest_TestOptimizedForSize__FieldAccessorTable
= new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder>(internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor,
new string[] { "I", "Msg", });
internal static readonly pbd::MessageDescriptor internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor
= Descriptor.MessageTypes[1];
internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder> internal__static_protobuf_unittest_TestRequiredOptimizedForSize__FieldAccessorTable
= new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder>(internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor,
new string[] { "X", });
internal static readonly pbd::MessageDescriptor internal__static_protobuf_unittest_TestOptionalOptimizedForSize__Descriptor
= Descriptor.MessageTypes[2];
internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize.Builder> internal__static_protobuf_unittest_TestOptionalOptimizedForSize__FieldAccessorTable
= new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize.Builder>(internal__static_protobuf_unittest_TestOptionalOptimizedForSize__Descriptor,
new string[] { "O", });
#endregion
}
#region Messages
public sealed partial class TestOptimizedForSize : pb::ExtendableMessage<TestOptimizedForSize, TestOptimizedForSize.Builder> {
private static readonly TestOptimizedForSize defaultInstance = new Builder().BuildPartial();
public static TestOptimizedForSize DefaultInstance {
get { return defaultInstance; }
}
public override TestOptimizedForSize DefaultInstanceForType {
get { return defaultInstance; }
}
protected override TestOptimizedForSize ThisMessage {
get { return this; }
}
public static pbd::MessageDescriptor Descriptor {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestOptimizeForProtoFile.internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor; }
}
protected override pb::FieldAccess.FieldAccessorTable<TestOptimizedForSize, TestOptimizedForSize.Builder> InternalFieldAccessors {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestOptimizeForProtoFile.internal__static_protobuf_unittest_TestOptimizedForSize__FieldAccessorTable; }
}
public static readonly pb::GeneratedExtensionBase<int> TestExtension =
pb::GeneratedSingleExtension<int>.CreateInstance(Descriptor.Extensions[0]);
private bool hasI;
private int i_ = 0;
public bool HasI {
get { return hasI; }
}
public int I {
get { return i_; }
}
private bool hasMsg;
private global::Google.ProtocolBuffers.TestProtos.ForeignMessage msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance;
public bool HasMsg {
get { return hasMsg; }
}
public global::Google.ProtocolBuffers.TestProtos.ForeignMessage Msg {
get { return msg_; }
}
public static TestOptimizedForSize ParseFrom(pb::ByteString data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(global::System.IO.Stream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static Builder CreateBuilder() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(TestOptimizedForSize prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::ExtendableBuilder<TestOptimizedForSize, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
public Builder() {}
TestOptimizedForSize result = new TestOptimizedForSize();
protected override TestOptimizedForSize MessageBeingBuilt {
get { return result; }
}
public override Builder Clear() {
result = new TestOptimizedForSize();
return this;
}
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
public override pbd::MessageDescriptor DescriptorForType {
get { return TestOptimizedForSize.Descriptor; }
}
public override TestOptimizedForSize DefaultInstanceForType {
get { return TestOptimizedForSize.DefaultInstance; }
}
public override TestOptimizedForSize BuildPartial() {
TestOptimizedForSize returnMe = result;
result = null;
return returnMe;
}
public bool HasI {
get { return result.HasI; }
}
public int I {
get { return result.I; }
set { SetI(value); }
}
public Builder SetI(int value) {
result.hasI = true;
result.i_ = value;
return this;
}
public Builder ClearI() {
result.hasI = false;
result.i_ = 0;
return this;
}
public bool HasMsg {
get { return result.HasMsg; }
}
public global::Google.ProtocolBuffers.TestProtos.ForeignMessage Msg {
get { return result.Msg; }
set { SetMsg(value); }
}
public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
result.hasMsg = true;
result.msg_ = value;
return this;
}
public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage.Builder builderForValue) {
result.hasMsg = true;
result.msg_ = builderForValue.Build();
return this;
}
public Builder MergeMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
if (result.HasMsg &&
result.msg_ != global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance) {
result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.CreateBuilder(result.msg_).MergeFrom(value).BuildPartial();
} else {
result.msg_ = value;
}
result.hasMsg = true;
return this;
}
public Builder ClearMsg() {
result.hasMsg = false;
result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance;
return this;
}
}
}
public sealed partial class TestRequiredOptimizedForSize : pb::GeneratedMessage<TestRequiredOptimizedForSize, TestRequiredOptimizedForSize.Builder> {
private static readonly TestRequiredOptimizedForSize defaultInstance = new Builder().BuildPartial();
public static TestRequiredOptimizedForSize DefaultInstance {
get { return defaultInstance; }
}
public override TestRequiredOptimizedForSize DefaultInstanceForType {
get { return defaultInstance; }
}
protected override TestRequiredOptimizedForSize ThisMessage {
get { return this; }
}
public static pbd::MessageDescriptor Descriptor {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestOptimizeForProtoFile.internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor; }
}
protected override pb::FieldAccess.FieldAccessorTable<TestRequiredOptimizedForSize, TestRequiredOptimizedForSize.Builder> InternalFieldAccessors {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestOptimizeForProtoFile.internal__static_protobuf_unittest_TestRequiredOptimizedForSize__FieldAccessorTable; }
}
private bool hasX;
private int x_ = 0;
public bool HasX {
get { return hasX; }
}
public int X {
get { return x_; }
}
public static TestRequiredOptimizedForSize ParseFrom(pb::ByteString data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(global::System.IO.Stream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static Builder CreateBuilder() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(TestRequiredOptimizedForSize prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<TestRequiredOptimizedForSize, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
public Builder() {}
TestRequiredOptimizedForSize result = new TestRequiredOptimizedForSize();
protected override TestRequiredOptimizedForSize MessageBeingBuilt {
get { return result; }
}
public override Builder Clear() {
result = new TestRequiredOptimizedForSize();
return this;
}
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
public override pbd::MessageDescriptor DescriptorForType {
get { return TestRequiredOptimizedForSize.Descriptor; }
}
public override TestRequiredOptimizedForSize DefaultInstanceForType {
get { return TestRequiredOptimizedForSize.DefaultInstance; }
}
public override TestRequiredOptimizedForSize BuildPartial() {
TestRequiredOptimizedForSize returnMe = result;
result = null;
return returnMe;
}
public bool HasX {
get { return result.HasX; }
}
public int X {
get { return result.X; }
set { SetX(value); }
}
public Builder SetX(int value) {
result.hasX = true;
result.x_ = value;
return this;
}
public Builder ClearX() {
result.hasX = false;
result.x_ = 0;
return this;
}
}
}
public sealed partial class TestOptionalOptimizedForSize : pb::GeneratedMessage<TestOptionalOptimizedForSize, TestOptionalOptimizedForSize.Builder> {
private static readonly TestOptionalOptimizedForSize defaultInstance = new Builder().BuildPartial();
public static TestOptionalOptimizedForSize DefaultInstance {
get { return defaultInstance; }
}
public override TestOptionalOptimizedForSize DefaultInstanceForType {
get { return defaultInstance; }
}
protected override TestOptionalOptimizedForSize ThisMessage {
get { return this; }
}
public static pbd::MessageDescriptor Descriptor {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestOptimizeForProtoFile.internal__static_protobuf_unittest_TestOptionalOptimizedForSize__Descriptor; }
}
protected override pb::FieldAccess.FieldAccessorTable<TestOptionalOptimizedForSize, TestOptionalOptimizedForSize.Builder> InternalFieldAccessors {
get { return global::Google.ProtocolBuffers.TestProtos.UnitTestOptimizeForProtoFile.internal__static_protobuf_unittest_TestOptionalOptimizedForSize__FieldAccessorTable; }
}
private bool hasO;
private global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance;
public bool HasO {
get { return hasO; }
}
public global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize O {
get { return o_; }
}
public static TestOptionalOptimizedForSize ParseFrom(pb::ByteString data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(global::System.IO.Stream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static Builder CreateBuilder() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(TestOptionalOptimizedForSize prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<TestOptionalOptimizedForSize, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
public Builder() {}
TestOptionalOptimizedForSize result = new TestOptionalOptimizedForSize();
protected override TestOptionalOptimizedForSize MessageBeingBuilt {
get { return result; }
}
public override Builder Clear() {
result = new TestOptionalOptimizedForSize();
return this;
}
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
public override pbd::MessageDescriptor DescriptorForType {
get { return TestOptionalOptimizedForSize.Descriptor; }
}
public override TestOptionalOptimizedForSize DefaultInstanceForType {
get { return TestOptionalOptimizedForSize.DefaultInstance; }
}
public override TestOptionalOptimizedForSize BuildPartial() {
TestOptionalOptimizedForSize returnMe = result;
result = null;
return returnMe;
}
public bool HasO {
get { return result.HasO; }
}
public global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize O {
get { return result.O; }
set { SetO(value); }
}
public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
result.hasO = true;
result.o_ = value;
return this;
}
public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder builderForValue) {
result.hasO = true;
result.o_ = builderForValue.Build();
return this;
}
public Builder MergeO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
if (result.HasO &&
result.o_ != global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance) {
result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.CreateBuilder(result.o_).MergeFrom(value).BuildPartial();
} else {
result.o_ = value;
}
result.hasO = true;
return this;
}
public Builder ClearO() {
result.hasO = false;
result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance;
return this;
}
}
}
#endregion
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,487 @@
// 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;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
[TestFixture]
public class TextFormatTest {
private static readonly string AllFieldsSetText = TestUtil.ReadTextFromFile("text_format_unittest_data.txt");
private static readonly string AllExtensionsSetText = TestUtil.ReadTextFromFile("text_format_unittest_extensions_data.txt");
/// <summary>
/// Note that this is slightly different to the Java - 123.0 becomes 123, and 1.23E17 becomes 1.23E+17.
/// Both of these differences can be parsed by the Java and the C++, and we can parse their output too.
/// </summary>
private const string ExoticText =
"repeated_int32: -1\n" +
"repeated_int32: -2147483648\n" +
"repeated_int64: -1\n" +
"repeated_int64: -9223372036854775808\n" +
"repeated_uint32: 4294967295\n" +
"repeated_uint32: 2147483648\n" +
"repeated_uint64: 18446744073709551615\n" +
"repeated_uint64: 9223372036854775808\n" +
"repeated_double: 123\n" +
"repeated_double: 123.5\n" +
"repeated_double: 0.125\n" +
"repeated_double: 1.23E+17\n" +
"repeated_double: 1.235E+22\n" +
"repeated_double: 1.235E-18\n" +
"repeated_double: 123.456789\n" +
"repeated_double: Infinity\n" +
"repeated_double: -Infinity\n" +
"repeated_double: NaN\n" +
"repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
"\\341\\210\\264\"\n" +
"repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
private const string MessageSetText =
"[protobuf_unittest.TestMessageSetExtension1] {\n" +
" i: 123\n" +
"}\n" +
"[protobuf_unittest.TestMessageSetExtension2] {\n" +
" str: \"foo\"\n" +
"}\n";
/// <summary>
/// Print TestAllTypes and compare with golden file.
/// </summary>
[Test]
public void PrintMessage() {
string text = TextFormat.PrintToString(TestUtil.GetAllSet());
Assert.AreEqual(AllFieldsSetText.Replace("\r\n", "\n"), text.Replace("\r\n", "\n"));
}
/// <summary>
/// Print TestAllExtensions and compare with golden file.
/// </summary>
[Test]
public void PrintExtensions() {
string text = TextFormat.PrintToString(TestUtil.GetAllExtensionsSet());
Assert.AreEqual(AllExtensionsSetText.Replace("\r\n", "\n"), text.Replace("\r\n", "\n"));
}
/// <summary>
/// Test printing of unknown fields in a message.
/// </summary>
[Test]
public void PrintUnknownFields() {
TestEmptyMessage message =
TestEmptyMessage.CreateBuilder()
.SetUnknownFields(
UnknownFieldSet.CreateBuilder()
.AddField(5,
UnknownField.CreateBuilder()
.AddVarint(1)
.AddFixed32(2)
.AddFixed64(3)
.AddLengthDelimited(ByteString.CopyFromUtf8("4"))
.AddGroup(
UnknownFieldSet.CreateBuilder()
.AddField(10,
UnknownField.CreateBuilder()
.AddVarint(5)
.Build())
.Build())
.Build())
.AddField(8,
UnknownField.CreateBuilder()
.AddVarint(1)
.AddVarint(2)
.AddVarint(3)
.Build())
.AddField(15,
UnknownField.CreateBuilder()
.AddVarint(0xABCDEF1234567890L)
.AddFixed32(0xABCD1234)
.AddFixed64(0xABCDEF1234567890L)
.Build())
.Build())
.Build();
Assert.AreEqual(
"5: 1\n" +
"5: 0x00000002\n" +
"5: 0x0000000000000003\n" +
"5: \"4\"\n" +
"5 {\n" +
" 10: 5\n" +
"}\n" +
"8: 1\n" +
"8: 2\n" +
"8: 3\n" +
"15: 12379813812177893520\n" +
"15: 0xabcd1234\n" +
"15: 0xabcdef1234567890\n",
TextFormat.PrintToString(message));
}
/// <summary>
/// Helper to construct a ByteString from a string containing only 8-bit
/// characters. The characters are converted directly to bytes, *not*
/// encoded using UTF-8.
/// </summary>
private static ByteString Bytes(string str) {
return ByteString.CopyFrom(Encoding.GetEncoding(28591).GetBytes(str));
}
[Test]
public void PrintExotic() {
IMessage message = TestAllTypes.CreateBuilder()
// Signed vs. unsigned numbers.
.AddRepeatedInt32 (-1)
.AddRepeatedUint32(uint.MaxValue)
.AddRepeatedInt64 (-1)
.AddRepeatedUint64(ulong.MaxValue)
.AddRepeatedInt32 (1 << 31)
.AddRepeatedUint32(1U << 31)
.AddRepeatedInt64 (1L << 63)
.AddRepeatedUint64(1UL << 63)
// Floats of various precisions and exponents.
.AddRepeatedDouble(123)
.AddRepeatedDouble(123.5)
.AddRepeatedDouble(0.125)
.AddRepeatedDouble(123e15)
.AddRepeatedDouble(123.5e20)
.AddRepeatedDouble(123.5e-20)
.AddRepeatedDouble(123.456789)
.AddRepeatedDouble(Double.PositiveInfinity)
.AddRepeatedDouble(Double.NegativeInfinity)
.AddRepeatedDouble(Double.NaN)
// Strings and bytes that needing escaping.
.AddRepeatedString("\0\u0001\u0007\b\f\n\r\t\v\\\'\"\u1234")
.AddRepeatedBytes(Bytes("\0\u0001\u0007\b\f\n\r\t\v\\\'\"\u00fe"))
.Build();
Assert.AreEqual(ExoticText, message.ToString());
}
[Test]
public void PrintMessageSet() {
TestMessageSet messageSet =
TestMessageSet.CreateBuilder()
.SetExtension(
TestMessageSetExtension1.MessageSetExtension,
TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
.SetExtension(
TestMessageSetExtension2.MessageSetExtension,
TestMessageSetExtension2.CreateBuilder().SetStr("foo").Build())
.Build();
Assert.AreEqual(MessageSetText, messageSet.ToString());
}
// =================================================================
[Test]
public void Parse() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TextFormat.Merge(AllFieldsSetText, builder);
TestUtil.AssertAllFieldsSet(builder.Build());
}
[Test]
public void ParseReader() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TextFormat.Merge(new StringReader(AllFieldsSetText), builder);
TestUtil.AssertAllFieldsSet(builder.Build());
}
[Test]
public void ParseExtensions() {
TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
TextFormat.Merge(AllExtensionsSetText,
TestUtil.CreateExtensionRegistry(),
builder);
TestUtil.AssertAllExtensionsSet(builder.Build());
}
[Test]
public void ParseCompatibility() {
string original = "repeated_float: inf\n" +
"repeated_float: -inf\n" +
"repeated_float: nan\n" +
"repeated_float: inff\n" +
"repeated_float: -inff\n" +
"repeated_float: nanf\n" +
"repeated_float: 1.0f\n" +
"repeated_float: infinityf\n" +
"repeated_float: -Infinityf\n" +
"repeated_double: infinity\n" +
"repeated_double: -infinity\n" +
"repeated_double: nan\n";
string canonical = "repeated_float: Infinity\n" +
"repeated_float: -Infinity\n" +
"repeated_float: NaN\n" +
"repeated_float: Infinity\n" +
"repeated_float: -Infinity\n" +
"repeated_float: NaN\n" +
"repeated_float: 1\n" + // Java has 1.0; this is fine
"repeated_float: Infinity\n" +
"repeated_float: -Infinity\n" +
"repeated_double: Infinity\n" +
"repeated_double: -Infinity\n" +
"repeated_double: NaN\n";
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TextFormat.Merge(original, builder);
Assert.AreEqual(canonical, builder.Build().ToString());
}
[Test]
public void ParseExotic() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TextFormat.Merge(ExoticText, builder);
// Too lazy to check things individually. Don't try to debug this
// if testPrintExotic() is Assert.Failing.
Assert.AreEqual(ExoticText, builder.Build().ToString());
}
[Test]
public void ParseMessageSet() {
ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
extensionRegistry.Add(TestMessageSetExtension1.MessageSetExtension);
extensionRegistry.Add(TestMessageSetExtension2.MessageSetExtension);
TestMessageSet.Builder builder = TestMessageSet.CreateBuilder();
TextFormat.Merge(MessageSetText, extensionRegistry, builder);
TestMessageSet messageSet = builder.Build();
Assert.IsTrue(messageSet.HasExtension(TestMessageSetExtension1.MessageSetExtension));
Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.MessageSetExtension).I);
Assert.IsTrue(messageSet.HasExtension(TestMessageSetExtension2.MessageSetExtension));
Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.MessageSetExtension).Str);
}
[Test]
public void ParseNumericEnum() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TextFormat.Merge("optional_nested_enum: 2", builder);
Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR, builder.OptionalNestedEnum);
}
[Test]
public void ParseAngleBrackets() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TextFormat.Merge("OptionalGroup: < a: 1 >", builder);
Assert.IsTrue(builder.HasOptionalGroup);
Assert.AreEqual(1, builder.OptionalGroup.A);
}
[Test]
public void ParseComment() {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
TextFormat.Merge(
"# this is a comment\n" +
"optional_int32: 1 # another comment\n" +
"optional_int64: 2\n" +
"# EOF comment", builder);
Assert.AreEqual(1, builder.OptionalInt32);
Assert.AreEqual(2, builder.OptionalInt64);
}
private static void AssertParseError(string error, string text) {
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
try {
TextFormat.Merge(text, TestUtil.CreateExtensionRegistry(), builder);
Assert.Fail("Expected parse exception.");
} catch (FormatException e) {
Assert.AreEqual(error, e.Message);
}
}
[Test]
public void ParseErrors() {
AssertParseError(
"1:16: Expected \":\".",
"optional_int32 123");
AssertParseError(
"1:23: Expected identifier.",
"optional_nested_enum: ?");
AssertParseError(
"1:18: Couldn't parse integer: Number must be positive: -1",
"optional_uint32: -1");
AssertParseError(
"1:17: Couldn't parse integer: Number out of range for 32-bit signed " +
"integer: 82301481290849012385230157",
"optional_int32: 82301481290849012385230157");
AssertParseError(
"1:16: Expected \"true\" or \"false\".",
"optional_bool: maybe");
AssertParseError(
"1:18: Expected string.",
"optional_string: 123");
AssertParseError(
"1:18: String missing ending quote.",
"optional_string: \"ueoauaoe");
AssertParseError(
"1:18: String missing ending quote.",
"optional_string: \"ueoauaoe\n" +
"optional_int32: 123");
AssertParseError(
"1:18: Invalid escape sequence: '\\z'",
"optional_string: \"\\z\"");
AssertParseError(
"1:18: String missing ending quote.",
"optional_string: \"ueoauaoe\n" +
"optional_int32: 123");
AssertParseError(
"1:2: Extension \"nosuchext\" not found in the ExtensionRegistry.",
"[nosuchext]: 123");
AssertParseError(
"1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " +
"not extend message type \"protobuf_unittest.TestAllTypes\".",
"[protobuf_unittest.optional_int32_extension]: 123");
AssertParseError(
"1:1: Message type \"protobuf_unittest.TestAllTypes\" has no field " +
"named \"nosuchfield\".",
"nosuchfield: 123");
AssertParseError(
"1:21: Expected \">\".",
"OptionalGroup < a: 1");
AssertParseError(
"1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
"value named \"NO_SUCH_VALUE\".",
"optional_nested_enum: NO_SUCH_VALUE");
AssertParseError(
"1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
"value with number 123.",
"optional_nested_enum: 123");
// Delimiters must match.
AssertParseError(
"1:22: Expected identifier.",
"OptionalGroup < a: 1 }");
AssertParseError(
"1:22: Expected identifier.",
"OptionalGroup { a: 1 >");
}
// =================================================================
private static ByteString Bytes(params byte[] bytes) {
return ByteString.CopyFrom(bytes);
}
private delegate void FormattingAction();
private static void AssertFormatException(FormattingAction action) {
try {
action();
Assert.Fail("Should have thrown an exception.");
} catch (FormatException) {
// success
}
}
[Test]
public void Escape() {
// Escape sequences.
Assert.AreEqual("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
TextFormat.EscapeBytes(Bytes("\0\u0001\u0007\b\f\n\r\t\v\\\'\"")));
Assert.AreEqual("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
TextFormat.EscapeText("\0\u0001\u0007\b\f\n\r\t\v\\\'\""));
Assert.AreEqual(Bytes("\0\u0001\u0007\b\f\n\r\t\v\\\'\""),
TextFormat.UnescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
Assert.AreEqual("\0\u0001\u0007\b\f\n\r\t\v\\\'\"",
TextFormat.UnescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
// Unicode handling.
Assert.AreEqual("\\341\\210\\264", TextFormat.EscapeText("\u1234"));
Assert.AreEqual("\\341\\210\\264", TextFormat.EscapeBytes(Bytes(0xe1, 0x88, 0xb4)));
Assert.AreEqual("\u1234", TextFormat.UnescapeText("\\341\\210\\264"));
Assert.AreEqual(Bytes(0xe1, 0x88, 0xb4), TextFormat.UnescapeBytes("\\341\\210\\264"));
Assert.AreEqual("\u1234", TextFormat.UnescapeText("\\xe1\\x88\\xb4"));
Assert.AreEqual(Bytes(0xe1, 0x88, 0xb4), TextFormat.UnescapeBytes("\\xe1\\x88\\xb4"));
// Errors.
AssertFormatException(() => TextFormat.UnescapeText("\\x"));
AssertFormatException(() => TextFormat.UnescapeText("\\z"));
AssertFormatException(() => TextFormat.UnescapeText("\\"));
}
[Test]
public void ParseInteger() {
Assert.AreEqual( 0, TextFormat.ParseInt32( "0"));
Assert.AreEqual( 1, TextFormat.ParseInt32( "1"));
Assert.AreEqual( -1, TextFormat.ParseInt32( "-1"));
Assert.AreEqual( 12345, TextFormat.ParseInt32( "12345"));
Assert.AreEqual( -12345, TextFormat.ParseInt32( "-12345"));
Assert.AreEqual( 2147483647, TextFormat.ParseInt32( "2147483647"));
Assert.AreEqual(-2147483648, TextFormat.ParseInt32("-2147483648"));
Assert.AreEqual( 0, TextFormat.ParseUInt32( "0"));
Assert.AreEqual( 1, TextFormat.ParseUInt32( "1"));
Assert.AreEqual( 12345, TextFormat.ParseUInt32( "12345"));
Assert.AreEqual( 2147483647, TextFormat.ParseUInt32("2147483647"));
Assert.AreEqual(2147483648U, TextFormat.ParseUInt32("2147483648"));
Assert.AreEqual(4294967295U, TextFormat.ParseUInt32("4294967295"));
Assert.AreEqual( 0L, TextFormat.ParseInt64( "0"));
Assert.AreEqual( 1L, TextFormat.ParseInt64( "1"));
Assert.AreEqual( -1L, TextFormat.ParseInt64( "-1"));
Assert.AreEqual( 12345L, TextFormat.ParseInt64( "12345"));
Assert.AreEqual( -12345L, TextFormat.ParseInt64( "-12345"));
Assert.AreEqual( 2147483647L, TextFormat.ParseInt64( "2147483647"));
Assert.AreEqual(-2147483648L, TextFormat.ParseInt64("-2147483648"));
Assert.AreEqual( 4294967295L, TextFormat.ParseInt64( "4294967295"));
Assert.AreEqual( 4294967296L, TextFormat.ParseInt64( "4294967296"));
Assert.AreEqual(9223372036854775807L, TextFormat.ParseInt64("9223372036854775807"));
Assert.AreEqual(-9223372036854775808L, TextFormat.ParseInt64("-9223372036854775808"));
Assert.AreEqual( 0L, TextFormat.ParseUInt64( "0"));
Assert.AreEqual( 1L, TextFormat.ParseUInt64( "1"));
Assert.AreEqual( 12345L, TextFormat.ParseUInt64( "12345"));
Assert.AreEqual( 2147483647L, TextFormat.ParseUInt64( "2147483647"));
Assert.AreEqual( 4294967295L, TextFormat.ParseUInt64( "4294967295"));
Assert.AreEqual( 4294967296L, TextFormat.ParseUInt64( "4294967296"));
Assert.AreEqual(9223372036854775807UL, TextFormat.ParseUInt64("9223372036854775807"));
Assert.AreEqual(9223372036854775808UL, TextFormat.ParseUInt64("9223372036854775808"));
Assert.AreEqual(18446744073709551615UL, TextFormat.ParseUInt64("18446744073709551615"));
// Hex
Assert.AreEqual(0x1234abcd, TextFormat.ParseInt32("0x1234abcd"));
Assert.AreEqual(-0x1234abcd, TextFormat.ParseInt32("-0x1234abcd"));
Assert.AreEqual(0xffffffffffffffffUL, TextFormat.ParseUInt64("0xffffffffffffffff"));
Assert.AreEqual(0x7fffffffffffffffL,
TextFormat.ParseInt64("0x7fffffffffffffff"));
// Octal
Assert.AreEqual(342391, TextFormat.ParseInt32("01234567"));
// Out-of-range
AssertFormatException(() => TextFormat.ParseInt32("2147483648"));
AssertFormatException(() => TextFormat.ParseInt32("-2147483649"));
AssertFormatException(() => TextFormat.ParseUInt32("4294967296"));
AssertFormatException(() => TextFormat.ParseUInt32("-1"));
AssertFormatException(() => TextFormat.ParseInt64("9223372036854775808"));
AssertFormatException(() => TextFormat.ParseInt64("-9223372036854775809"));
AssertFormatException(() => TextFormat.ParseUInt64("18446744073709551616"));
AssertFormatException(() => TextFormat.ParseUInt64("-1"));
AssertFormatException(() => TextFormat.ParseInt32("abcd"));
}
}
}

@ -0,0 +1,314 @@
// 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;
using System.Collections.Generic;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
[TestFixture]
public class UnknownFieldSetTest {
private MessageDescriptor descriptor;
private TestAllTypes allFields;
private ByteString allFieldsData;
/// <summary>
/// An empty message that has been parsed from allFieldsData. So, it has
/// unknown fields of every type.
/// </summary>
private TestEmptyMessage emptyMessage;
private UnknownFieldSet unknownFields;
[SetUp]
public void SetUp() {
descriptor = TestAllTypes.Descriptor;
allFields = TestUtil.GetAllSet();
allFieldsData = allFields.ToByteString();
emptyMessage = TestEmptyMessage.ParseFrom(allFieldsData);
unknownFields = emptyMessage.UnknownFields;
}
private UnknownField GetField(String name) {
FieldDescriptor field = descriptor.FindDescriptor<FieldDescriptor>(name);
Assert.IsNotNull(field);
return unknownFields.FieldDictionary[field.FieldNumber];
}
/// <summary>
/// Constructs a protocol buffer which contains fields with all the same
/// numbers as allFieldsData except that each field is some other wire
/// type.
/// </summary>
private ByteString GetBizarroData() {
UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.CreateBuilder();
UnknownField varintField = UnknownField.CreateBuilder().AddVarint(1).Build();
UnknownField fixed32Field = UnknownField.CreateBuilder().AddFixed32(1).Build();
foreach (KeyValuePair<int, UnknownField> entry in unknownFields.FieldDictionary) {
if (entry.Value.VarintList.Count == 0) {
// Original field is not a varint, so use a varint.
bizarroFields.AddField(entry.Key, varintField);
} else {
// Original field *is* a varint, so use something else.
bizarroFields.AddField(entry.Key, fixed32Field);
}
}
return bizarroFields.Build().ToByteString();
}
// =================================================================
[Test]
public void Varint() {
UnknownField field = GetField("optional_int32");
Assert.AreEqual(1, field.VarintList.Count);
Assert.AreEqual(allFields.OptionalInt32, (long) field.VarintList[0]);
}
[Test]
public void Fixed32() {
UnknownField field = GetField("optional_fixed32");
Assert.AreEqual(1, field.Fixed32List.Count);
Assert.AreEqual(allFields.OptionalFixed32, (int) field.Fixed32List[0]);
}
[Test]
public void Fixed64() {
UnknownField field = GetField("optional_fixed64");
Assert.AreEqual(1, field.Fixed64List.Count);
Assert.AreEqual(allFields.OptionalFixed64, (long) field.Fixed64List[0]);
}
[Test]
public void LengthDelimited() {
UnknownField field = GetField("optional_bytes");
Assert.AreEqual(1, field.LengthDelimitedList.Count);
Assert.AreEqual(allFields.OptionalBytes, field.LengthDelimitedList[0]);
}
[Test]
public void Group() {
FieldDescriptor nestedFieldDescriptor =
TestAllTypes.Types.OptionalGroup.Descriptor.FindDescriptor<FieldDescriptor>("a");
Assert.IsNotNull(nestedFieldDescriptor);
UnknownField field = GetField("optionalgroup");
Assert.AreEqual(1, field.GroupList.Count);
UnknownFieldSet group = field.GroupList[0];
Assert.AreEqual(1, group.FieldDictionary.Count);
Assert.IsTrue(group.HasField(nestedFieldDescriptor.FieldNumber));
UnknownField nestedField = group[nestedFieldDescriptor.FieldNumber];
Assert.AreEqual(1, nestedField.VarintList.Count);
Assert.AreEqual(allFields.OptionalGroup.A, (long) nestedField.VarintList[0]);
}
[Test]
public void Serialize() {
// Check that serializing the UnknownFieldSet produces the original data again.
ByteString data = emptyMessage.ToByteString();
Assert.AreEqual(allFieldsData, data);
}
[Test]
public void CopyFrom() {
TestEmptyMessage message =
TestEmptyMessage.CreateBuilder().MergeFrom(emptyMessage).Build();
Assert.AreEqual(emptyMessage.ToString(), message.ToString());
}
[Test]
public void MergeFrom() {
TestEmptyMessage source =
TestEmptyMessage.CreateBuilder()
.SetUnknownFields(
UnknownFieldSet.CreateBuilder()
.AddField(2,
UnknownField.CreateBuilder()
.AddVarint(2).Build())
.AddField(3,
UnknownField.CreateBuilder()
.AddVarint(4).Build())
.Build())
.Build();
TestEmptyMessage destination =
TestEmptyMessage.CreateBuilder()
.SetUnknownFields(
UnknownFieldSet.CreateBuilder()
.AddField(1,
UnknownField.CreateBuilder()
.AddVarint(1).Build())
.AddField(3,
UnknownField.CreateBuilder()
.AddVarint(3).Build())
.Build())
.MergeFrom(source)
.Build();
Assert.AreEqual(
"1: 1\n" +
"2: 2\n" +
"3: 3\n" +
"3: 4\n",
destination.ToString());
}
[Test]
public void Clear() {
UnknownFieldSet fields =
UnknownFieldSet.CreateBuilder().MergeFrom(unknownFields).Clear().Build();
Assert.AreEqual(0, fields.FieldDictionary.Count);
}
[Test]
public void ClearMessage() {
TestEmptyMessage message =
TestEmptyMessage.CreateBuilder().MergeFrom(emptyMessage).Clear().Build();
Assert.AreEqual(0, message.SerializedSize);
}
[Test]
public void ParseKnownAndUnknown() {
// Test mixing known and unknown fields when parsing.
UnknownFieldSet fields =
UnknownFieldSet.CreateBuilder(unknownFields)
.AddField(123456,
UnknownField.CreateBuilder().AddVarint(654321).Build())
.Build();
ByteString data = fields.ToByteString();
TestAllTypes destination = TestAllTypes.ParseFrom(data);
TestUtil.AssertAllFieldsSet(destination);
Assert.AreEqual(1, destination.UnknownFields.FieldDictionary.Count);
UnknownField field = destination.UnknownFields[123456];
Assert.AreEqual(1, field.VarintList.Count);
Assert.AreEqual(654321, (long) field.VarintList[0]);
}
[Test]
public void WrongTypeTreatedAsUnknown() {
// Test that fields of the wrong wire type are treated like unknown fields
// when parsing.
ByteString bizarroData = GetBizarroData();
TestAllTypes allTypesMessage = TestAllTypes.ParseFrom(bizarroData);
TestEmptyMessage emptyMessage = TestEmptyMessage.ParseFrom(bizarroData);
// All fields should have been interpreted as unknown, so the debug strings
// should be the same.
Assert.AreEqual(emptyMessage.ToString(), allTypesMessage.ToString());
}
[Test]
public void UnknownExtensions() {
// Make sure fields are properly parsed to the UnknownFieldSet even when
// they are declared as extension numbers.
TestEmptyMessageWithExtensions message =
TestEmptyMessageWithExtensions.ParseFrom(allFieldsData);
Assert.AreEqual(unknownFields.FieldDictionary.Count,
message.UnknownFields.FieldDictionary.Count);
Assert.AreEqual(allFieldsData, message.ToByteString());
}
[Test]
public void WrongExtensionTypeTreatedAsUnknown() {
// Test that fields of the wrong wire type are treated like unknown fields
// when parsing extensions.
ByteString bizarroData = GetBizarroData();
TestAllExtensions allExtensionsMessage = TestAllExtensions.ParseFrom(bizarroData);
TestEmptyMessage emptyMessage = TestEmptyMessage.ParseFrom(bizarroData);
// All fields should have been interpreted as unknown, so the debug strings
// should be the same.
Assert.AreEqual(emptyMessage.ToString(),
allExtensionsMessage.ToString());
}
[Test]
public void ParseUnknownEnumValue() {
FieldDescriptor singularField = TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("optional_nested_enum");
FieldDescriptor repeatedField = TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_nested_enum");
Assert.IsNotNull(singularField);
Assert.IsNotNull(repeatedField);
ByteString data =
UnknownFieldSet.CreateBuilder()
.AddField(singularField.FieldNumber,
UnknownField.CreateBuilder()
.AddVarint((int) TestAllTypes.Types.NestedEnum.BAR)
.AddVarint(5) // not valid
.Build())
.AddField(repeatedField.FieldNumber,
UnknownField.CreateBuilder()
.AddVarint((int) TestAllTypes.Types.NestedEnum.FOO)
.AddVarint(4) // not valid
.AddVarint((int) TestAllTypes.Types.NestedEnum.BAZ)
.AddVarint(6) // not valid
.Build())
.Build()
.ToByteString();
{
TestAllTypes message = TestAllTypes.ParseFrom(data);
Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR,
message.OptionalNestedEnum);
TestUtil.AssertEqual(new [] {TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.BAZ},
message.RepeatedNestedEnumList);
TestUtil.AssertEqual(new[] {5UL}, message.UnknownFields[singularField.FieldNumber].VarintList);
TestUtil.AssertEqual(new[] {4UL, 6UL}, message.UnknownFields[repeatedField.FieldNumber].VarintList);
}
{
TestAllExtensions message =
TestAllExtensions.ParseFrom(data, TestUtil.CreateExtensionRegistry());
Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR,
message.GetExtension(UnitTestProtoFile.OptionalNestedEnumExtension));
TestUtil.AssertEqual(new[] { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.BAZ },
message.GetExtension(UnitTestProtoFile.RepeatedNestedEnumExtension));
TestUtil.AssertEqual(new[] { 5UL }, message.UnknownFields[singularField.FieldNumber].VarintList);
TestUtil.AssertEqual(new[] { 4UL, 6UL }, message.UnknownFields[repeatedField.FieldNumber].VarintList);
}
}
[Test]
public void LargeVarint() {
ByteString data =
UnknownFieldSet.CreateBuilder()
.AddField(1,
UnknownField.CreateBuilder()
.AddVarint(0x7FFFFFFFFFFFFFFFL)
.Build())
.Build()
.ToByteString();
UnknownFieldSet parsed = UnknownFieldSet.ParseFrom(data);
UnknownField field = parsed[1];
Assert.AreEqual(1, field.VarintList.Count);
Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, field.VarintList[0]);
}
}
}

@ -0,0 +1,228 @@
// 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.Reflection;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers {
[TestFixture]
public class WireFormatTest {
/// <summary>
/// Keeps the attributes on FieldType and the switch statement in WireFormat in sync.
/// </summary>
[Test]
public void FieldTypeToWireTypeMapping() {
foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) {
FieldType fieldType = (FieldType)field.GetValue(null);
FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
Assert.AreEqual(mapping.WireType, WireFormat.GetWireType(fieldType));
}
}
[Test]
public void Serialization() {
TestAllTypes message = TestUtil.GetAllSet();
ByteString rawBytes = message.ToByteString();
Assert.AreEqual(rawBytes.Length, message.SerializedSize);
TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
TestUtil.AssertAllFieldsSet(message2);
}
[Test]
public void SerializeExtensions() {
// TestAllTypes and TestAllExtensions should have compatible wire formats,
// so if we serealize a TestAllExtensions then parse it as TestAllTypes
// it should work.
TestAllExtensions message = TestUtil.GetAllExtensionsSet();
ByteString rawBytes = message.ToByteString();
Assert.AreEqual(rawBytes.Length, message.SerializedSize);
TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
TestUtil.AssertAllFieldsSet(message2);
}
[Test]
public void ParseExtensions() {
// TestAllTypes and TestAllExtensions should have compatible wire formats,
// so if we serealize a TestAllTypes then parse it as TestAllExtensions
// it should work.
TestAllTypes message = TestUtil.GetAllSet();
ByteString rawBytes = message.ToByteString();
ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
TestUtil.RegisterAllExtensions(registry);
registry = registry.AsReadOnly();
TestAllExtensions message2 =
TestAllExtensions.ParseFrom(rawBytes, registry);
TestUtil.AssertAllExtensionsSet(message2);
}
[Test]
public void ExtensionsSerializedSize() {
Assert.AreEqual(TestUtil.GetAllSet().SerializedSize, TestUtil.GetAllExtensionsSet().SerializedSize);
}
private void AssertFieldsInOrder(ByteString data) {
CodedInputStream input = data.CreateCodedInput();
uint previousTag = 0;
while (true) {
uint tag = input.ReadTag();
if (tag == 0) {
break;
}
Assert.IsTrue(tag > previousTag);
previousTag = tag;
input.SkipField(tag);
}
}
[Test]
public void InterleavedFieldsAndExtensions() {
// Tests that fields are written in order even when extension ranges
// are interleaved with field numbers.
ByteString data =
TestFieldOrderings.CreateBuilder()
.SetMyInt(1)
.SetMyString("foo")
.SetMyFloat(1.0F)
.SetExtension(UnitTestProtoFile.MyExtensionInt, 23)
.SetExtension(UnitTestProtoFile.MyExtensionString, "bar")
.Build().ToByteString();
AssertFieldsInOrder(data);
MessageDescriptor descriptor = TestFieldOrderings.Descriptor;
ByteString dynamic_data =
DynamicMessage.CreateBuilder(TestFieldOrderings.Descriptor)
.SetField(descriptor.FindDescriptor<FieldDescriptor>("my_int"), 1L)
.SetField(descriptor.FindDescriptor<FieldDescriptor>("my_string"), "foo")
.SetField(descriptor.FindDescriptor<FieldDescriptor>("my_float"), 1.0F)
.SetField(UnitTestProtoFile.MyExtensionInt.Descriptor, 23)
.SetField(UnitTestProtoFile.MyExtensionString.Descriptor, "bar")
.WeakBuild().ToByteString();
AssertFieldsInOrder(dynamic_data);
}
private const int UnknownTypeId = 1550055;
private static readonly int TypeId1 = TestMessageSetExtension1.Descriptor.Extensions[0].FieldNumber;
private static readonly int TypeId2 = TestMessageSetExtension2.Descriptor.Extensions[0].FieldNumber;
[Test]
public void SerializeMessageSet() {
// Set up a TestMessageSet with two known messages and an unknown one.
TestMessageSet messageSet =
TestMessageSet.CreateBuilder()
.SetExtension(
TestMessageSetExtension1.MessageSetExtension,
TestMessageSetExtension1.CreateBuilder().SetI(123).Build())
.SetExtension(
TestMessageSetExtension2.MessageSetExtension,
TestMessageSetExtension2.CreateBuilder().SetStr("foo").Build())
.SetUnknownFields(
UnknownFieldSet.CreateBuilder()
.AddField(UnknownTypeId,
UnknownField.CreateBuilder()
.AddLengthDelimited(ByteString.CopyFromUtf8("bar"))
.Build())
.Build())
.Build();
ByteString data = messageSet.ToByteString();
// Parse back using RawMessageSet and check the contents.
RawMessageSet raw = RawMessageSet.ParseFrom(data);
Assert.AreEqual(0, raw.UnknownFields.FieldDictionary.Count);
Assert.AreEqual(3, raw.ItemCount);
Assert.AreEqual(TypeId1, raw.ItemList[0].TypeId);
Assert.AreEqual(TypeId2, raw.ItemList[1].TypeId);
Assert.AreEqual(UnknownTypeId, raw.ItemList[2].TypeId);
TestMessageSetExtension1 message1 = TestMessageSetExtension1.ParseFrom(raw.GetItem(0).Message.ToByteArray());
Assert.AreEqual(123, message1.I);
TestMessageSetExtension2 message2 = TestMessageSetExtension2.ParseFrom(raw.GetItem(1).Message.ToByteArray());
Assert.AreEqual("foo", message2.Str);
Assert.AreEqual("bar", raw.GetItem(2).Message.ToStringUtf8());
}
[Test]
public void ParseMessageSet() {
ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
extensionRegistry.Add(TestMessageSetExtension1.MessageSetExtension);
extensionRegistry.Add(TestMessageSetExtension2.MessageSetExtension);
// Set up a RawMessageSet with two known messages and an unknown one.
RawMessageSet raw =
RawMessageSet.CreateBuilder()
.AddItem(
RawMessageSet.Types.Item.CreateBuilder()
.SetTypeId(TypeId1)
.SetMessage(
TestMessageSetExtension1.CreateBuilder()
.SetI(123)
.Build().ToByteString())
.Build())
.AddItem(
RawMessageSet.Types.Item.CreateBuilder()
.SetTypeId(TypeId2)
.SetMessage(
TestMessageSetExtension2.CreateBuilder()
.SetStr("foo")
.Build().ToByteString())
.Build())
.AddItem(
RawMessageSet.Types.Item.CreateBuilder()
.SetTypeId(UnknownTypeId)
.SetMessage(ByteString.CopyFromUtf8("bar"))
.Build())
.Build();
ByteString data = raw.ToByteString();
// Parse as a TestMessageSet and check the contents.
TestMessageSet messageSet =
TestMessageSet.ParseFrom(data, extensionRegistry);
Assert.AreEqual(123, messageSet.GetExtension(TestMessageSetExtension1.MessageSetExtension).I);
Assert.AreEqual("foo", messageSet.GetExtension(TestMessageSetExtension2.MessageSetExtension).Str);
// Check for unknown field with type LENGTH_DELIMITED,
// number UNKNOWN_TYPE_ID, and contents "bar".
UnknownFieldSet unknownFields = messageSet.UnknownFields;
Assert.AreEqual(1, unknownFields.FieldDictionary.Count);
Assert.IsTrue(unknownFields.HasField(UnknownTypeId));
UnknownField field = unknownFields[UnknownTypeId];
Assert.AreEqual(1, field.LengthDelimitedList.Count);
Assert.AreEqual("bar", field.LengthDelimitedList[0].ToStringUtf8());
}
}
}

@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffers", "ProtocolBuffers\ProtocolBuffers.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffers.Test", "ProtocolBuffers.Test\ProtocolBuffers.Test.csproj", "{DD01ED24-3750-4567-9A23-1DB676A15610}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtoGen", "ProtoGen\ProtoGen.csproj", "{250ADE34-82FD-4BAE-86D5-985FBE589C4A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtoGen.Test", "ProtoGen.Test\ProtoGen.Test.csproj", "{C268DA4C-4004-47DA-AF23-44C983281A68}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.Build.0 = Release|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.Build.0 = Release|Any CPU
{250ADE34-82FD-4BAE-86D5-985FBE589C4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{250ADE34-82FD-4BAE-86D5-985FBE589C4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{250ADE34-82FD-4BAE-86D5-985FBE589C4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{250ADE34-82FD-4BAE-86D5-985FBE589C4A}.Release|Any CPU.Build.0 = Release|Any CPU
{C268DA4C-4004-47DA-AF23-44C983281A68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C268DA4C-4004-47DA-AF23-44C983281A68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C268DA4C-4004-47DA-AF23-44C983281A68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C268DA4C-4004-47DA-AF23-44C983281A68}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,222 @@
// 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;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// Implementation of the non-generic IMessage interface as far as possible.
/// </summary>
public abstract class AbstractBuilder<TMessage, TBuilder> : IBuilder<TMessage, TBuilder>
where TMessage : AbstractMessage<TMessage, TBuilder>
where TBuilder : AbstractBuilder<TMessage, TBuilder> {
protected abstract TBuilder ThisBuilder { get; }
#region Unimplemented members of IBuilder
public abstract UnknownFieldSet UnknownFields { get; set; }
public abstract TBuilder MergeFrom(TMessage other);
public abstract bool IsInitialized { get; }
public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
public abstract object this[FieldDescriptor field] { get; set; }
public abstract MessageDescriptor DescriptorForType { get; }
public abstract int GetRepeatedFieldCount(FieldDescriptor field);
public abstract object this[FieldDescriptor field, int index] { get; set; }
public abstract bool HasField(FieldDescriptor field);
public abstract TMessage Build();
public abstract TMessage BuildPartial();
public abstract TBuilder Clone();
public abstract TMessage DefaultInstanceForType { get; }
public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
public abstract TBuilder ClearField(FieldDescriptor field);
public abstract TBuilder AddRepeatedField(FieldDescriptor field, object value);
#endregion
#region Implementation of methods which don't require type parameter information
public IMessage WeakBuild() {
return Build();
}
public IBuilder WeakAddRepeatedField(FieldDescriptor field, object value) {
return AddRepeatedField(field, value);
}
public IBuilder WeakClear() {
return Clear();
}
public IBuilder WeakMergeFrom(IMessage message) {
return MergeFrom(message);
}
public IBuilder WeakMergeFrom(CodedInputStream input) {
return MergeFrom(input);
}
public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
return MergeFrom(input, registry);
}
public IBuilder WeakMergeFrom(ByteString data) {
return MergeFrom(data);
}
public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
return MergeFrom(data, registry);
}
public IMessage WeakBuildPartial() {
return BuildPartial();
}
public IBuilder WeakClone() {
return Clone();
}
public IMessage WeakDefaultInstanceForType {
get { return DefaultInstanceForType; }
}
public IBuilder WeakClearField(FieldDescriptor field) {
return ClearField(field);
}
#endregion
public TBuilder SetUnknownFields(UnknownFieldSet fields) {
UnknownFields = fields;
return ThisBuilder;
}
public virtual TBuilder Clear() {
foreach(FieldDescriptor field in AllFields.Keys) {
ClearField(field);
}
return ThisBuilder;
}
public virtual TBuilder MergeFrom(IMessage other) {
if (other.DescriptorForType != DescriptorForType) {
throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
}
// Note: We don't attempt to verify that other's fields have valid
// types. Doing so would be a losing battle. We'd have to verify
// all sub-messages as well, and we'd have to make copies of all of
// them to insure that they don't change after verification (since
// the Message interface itself cannot enforce immutability of
// implementations).
// TODO(jonskeet): Provide a function somewhere called MakeDeepCopy()
// which allows people to make secure deep copies of messages.
foreach (KeyValuePair<FieldDescriptor, object> entry in other.AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
// Concatenate repeated fields
foreach (object element in (IEnumerable) entry.Value) {
AddRepeatedField(field, element);
}
} else if (field.MappedType == MappedType.Message) {
// Merge singular messages
IMessage existingValue = (IMessage) this[field];
if (existingValue == existingValue.WeakDefaultInstanceForType) {
this[field] = entry.Value;
} else {
this[field] = existingValue.WeakCreateBuilderForType()
.WeakMergeFrom(existingValue)
.WeakMergeFrom((IMessage) entry.Value)
.WeakBuild();
}
} else {
// Overwrite simple values
this[field] = entry.Value;
}
}
return ThisBuilder;
}
public virtual TBuilder MergeFrom(CodedInputStream input) {
return MergeFrom(input, ExtensionRegistry.Empty);
}
public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
unknownFields.MergeFrom(input, extensionRegistry, this);
UnknownFields = unknownFields.Build();
return ThisBuilder;
}
public virtual TBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
.MergeFrom(unknownFields)
.Build();
return ThisBuilder;
}
public virtual TBuilder MergeFrom(ByteString data) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input);
input.CheckLastTagWas(0);
return ThisBuilder;
}
public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return ThisBuilder;
}
public virtual TBuilder MergeFrom(byte[] data) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input);
input.CheckLastTagWas(0);
return ThisBuilder;
}
public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return ThisBuilder;
}
public virtual TBuilder MergeFrom(Stream input) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput);
codedInput.CheckLastTagWas(0);
return ThisBuilder;
}
public virtual TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput, extensionRegistry);
codedInput.CheckLastTagWas(0);
return ThisBuilder;
}
public virtual IBuilder SetField(FieldDescriptor field, object value) {
this[field] = value;
return ThisBuilder;
}
public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) {
this[field, index] = value;
return ThisBuilder;
}
}
}

@ -0,0 +1,181 @@
// 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.Collections;
using System.Collections.Generic;
using System.IO;
using Google.ProtocolBuffers.Collections;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// Implementation of the non-generic IMessage interface as far as possible.
/// </summary>
public abstract class AbstractMessage<TMessage, TBuilder> : IMessage<TMessage, TBuilder>
where TMessage : AbstractMessage<TMessage, TBuilder>
where TBuilder : AbstractBuilder<TMessage, TBuilder> {
/// <summary>
/// The serialized size if it's already been computed, or null
/// if we haven't computed it yet.
/// </summary>
private int? memoizedSize = null;
#region Unimplemented members of IMessage
public abstract MessageDescriptor DescriptorForType { get; }
public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
public abstract bool HasField(FieldDescriptor field);
public abstract object this[FieldDescriptor field] { get; }
public abstract int GetRepeatedFieldCount(FieldDescriptor field);
public abstract object this[FieldDescriptor field, int index] { get; }
public abstract UnknownFieldSet UnknownFields { get; }
public abstract TMessage DefaultInstanceForType { get; }
public abstract TBuilder CreateBuilderForType();
#endregion
public IBuilder WeakCreateBuilderForType() {
return CreateBuilderForType();
}
public IMessage WeakDefaultInstanceForType {
get { return DefaultInstanceForType; }
}
public virtual bool IsInitialized {
get {
// Check that all required fields are present.
foreach (FieldDescriptor field in DescriptorForType.Fields) {
if (field.IsRequired && !HasField(field)) {
return false;
}
}
// Check that embedded messages are initialized.
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.MappedType == MappedType.Message) {
if (field.IsRepeated) {
// We know it's an IList<T>, but not the exact type - so
// IEnumerable is the best we can do. (C# generics aren't covariant yet.)
foreach (IMessage element in (IEnumerable) entry.Value) {
if (!element.IsInitialized) {
return false;
}
}
} else {
if (!((IMessage)entry.Value).IsInitialized) {
return false;
}
}
}
}
return true;
}
}
public sealed override string ToString() {
return TextFormat.PrintToString(this);
}
public virtual void WriteTo(CodedOutputStream output) {
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
// We know it's an IList<T>, but not the exact type - so
// IEnumerable is the best we can do. (C# generics aren't covariant yet.)
foreach (object element in (IEnumerable)entry.Value) {
output.WriteField(field.FieldType, field.FieldNumber, element);
}
} else {
output.WriteField(field.FieldType, field.FieldNumber, entry.Value);
}
}
UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.MessageSetWireFormat) {
unknownFields.WriteAsMessageSetTo(output);
} else {
unknownFields.WriteTo(output);
}
}
public virtual int SerializedSize {
get {
if (memoizedSize != null) {
return memoizedSize.Value;
}
int size = 0;
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
foreach (object element in (IEnumerable) entry.Value) {
size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, element);
}
} else {
size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, entry.Value);
}
}
UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.MessageSetWireFormat) {
size += unknownFields.SerializedSizeAsMessageSet;
} else {
size += unknownFields.SerializedSize;
}
memoizedSize = size;
return size;
}
}
public ByteString ToByteString() {
ByteString.CodedBuilder output = new ByteString.CodedBuilder(SerializedSize);
WriteTo(output.CodedOutput);
return output.Build();
}
public byte[] ToByteArray() {
byte[] result = new byte[SerializedSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(result);
WriteTo(output);
output.CheckNoSpaceLeft();
return result;
}
public void WriteTo(Stream output) {
CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
WriteTo(codedOutput);
codedOutput.Flush();
}
public override bool Equals(object other) {
if (other == this) {
return true;
}
IMessage otherMessage = other as IMessage;
if (otherMessage == null || otherMessage.DescriptorForType != DescriptorForType) {
return false;
}
return Dictionaries.Equals(AllFields, otherMessage.AllFields);
}
public override int GetHashCode() {
int hash = 41;
hash = (19 * hash) + DescriptorForType.GetHashCode();
hash = (53 * hash) + Dictionaries.GetHashCode(AllFields);
return hash;
}
}
}

@ -0,0 +1,187 @@
using System;
using System.Collections;
using System.Collections.Generic;
// 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;
namespace Google.ProtocolBuffers {
/// <summary>
/// Immutable array of bytes.
/// TODO(jonskeet): Implement the common collection interfaces?
/// </summary>
public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString> {
private static readonly ByteString empty = new ByteString(new byte[0]);
private readonly byte[] bytes;
/// <summary>
/// Constructs a new ByteString from the given byte array. The array is
/// *not* copied, and must not be modified after this constructor is called.
/// </summary>
private ByteString(byte[] bytes) {
this.bytes = bytes;
}
/// <summary>
/// Returns an empty ByteString.
/// </summary>
public static ByteString Empty {
get { return empty; }
}
/// <summary>
/// Returns the length of this ByteString in bytes.
/// </summary>
public int Length {
get { return bytes.Length; }
}
public bool IsEmpty {
get { return Length == 0; }
}
public byte[] ToByteArray() {
return (byte[])bytes.Clone();
}
/// <summary>
/// Constructs a ByteString from the given array. The contents
/// are copied, so further modifications to the array will not
/// be reflected in the returned ByteString.
/// </summary>
public static ByteString CopyFrom(byte[] bytes) {
return new ByteString((byte[]) bytes.Clone());
}
/// <summary>
/// Constructs a ByteString from a portion of a byte array.
/// </summary>
public static ByteString CopyFrom(byte[] bytes, int offset, int count) {
byte[] portion = new byte[count];
Array.Copy(bytes, offset, portion, 0, count);
return new ByteString(portion);
}
/// <summary>
/// Creates a new ByteString by encoding the specified text with
/// the given encoding.
/// </summary>
public static ByteString CopyFrom(string text, Encoding encoding) {
return new ByteString(encoding.GetBytes(text));
}
/// <summary>
/// Creates a new ByteString by encoding the specified text in UTF-8.
/// </summary>
public static ByteString CopyFromUtf8(string text) {
return CopyFrom(text, Encoding.UTF8);
}
/// <summary>
/// Retuns the byte at the given index.
/// </summary>
public byte this[int index] {
get { return bytes[index]; }
}
public string ToString(Encoding encoding) {
return encoding.GetString(bytes);
}
public string ToStringUtf8() {
return ToString(Encoding.UTF8);
}
public IEnumerator<byte> GetEnumerator() {
return ((IEnumerable<byte>) bytes).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
/// <summary>
/// Creates a CodedInputStream from this ByteString's data.
/// </summary>
public CodedInputStream CreateCodedInput() {
// We trust CodedInputStream not to reveal the provided byte array or modify it
return CodedInputStream.CreateInstance(bytes);
}
// TODO(jonskeet): CopyTo if it turns out to be required
public override bool Equals(object obj) {
ByteString other = obj as ByteString;
if (obj == null) {
return false;
}
return Equals(other);
}
public override int GetHashCode() {
int ret = 23;
foreach (byte b in bytes) {
ret = (ret << 8) | b;
}
return ret;
}
public bool Equals(ByteString other) {
if (other.bytes.Length != bytes.Length) {
return false;
}
for (int i = 0; i < bytes.Length; i++) {
if (other.bytes[i] != bytes[i]) {
return false;
}
}
return true;
}
/// <summary>
/// Builder for ByteStrings which allows them to be created without extra
/// copying being involved. This has to be a nested type in order to have access
/// to the private ByteString constructor.
/// </summary>
internal sealed class CodedBuilder {
private readonly CodedOutputStream output;
private readonly byte[] buffer;
internal CodedBuilder(int size) {
buffer = new byte[size];
output = CodedOutputStream.CreateInstance(buffer);
}
public ByteString Build() {
output.CheckNoSpaceLeft();
// We can be confident that the CodedOutputStream will not modify the
// underlying bytes anymore because it already wrote all of them. So,
// no need to make a copy.
return new ByteString(buffer);
}
public CodedOutputStream CodedOutput {
get {
return output;
}
}
}
}
}

@ -0,0 +1,843 @@
// 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;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// Readings and decodes protocol message fields.
/// </summary>
/// <remarks>
/// This class contains two kinds of methods: methods that read specific
/// protocol message constructs and field types (e.g. ReadTag and
/// ReadInt32) and methods that read low-level values (e.g.
/// ReadRawVarint32 and ReadRawBytes). If you are reading encoded protocol
/// messages, you should use the former methods, but if you are reading some
/// other format of your own design, use the latter. The names of the former
/// methods are taken from the protocol buffer type names, not .NET types.
/// (Hence ReadFloat instead of ReadSingle, and ReadBool instead of ReadBoolean.)
///
/// TODO(jonskeet): Consider whether recursion and size limits shouldn't be readonly,
/// set at construction time.
/// </remarks>
public sealed class CodedInputStream {
private readonly byte[] buffer;
private int bufferSize;
private int bufferSizeAfterLimit = 0;
private int bufferPos = 0;
private readonly Stream input;
private uint lastTag = 0;
const int DefaultRecursionLimit = 64;
const int DefaultSizeLimit = 64 << 20; // 64MB
const int BufferSize = 4096;
/// <summary>
/// The total number of bytes read before the current buffer. The
/// total bytes read up to the current position can be computed as
/// totalBytesRetired + bufferPos.
/// </summary>
private int totalBytesRetired = 0;
/// <summary>
/// The absolute position of the end of the current message.
/// </summary>
private int currentLimit = int.MaxValue;
/// <summary>
/// <see cref="SetRecursionLimit"/>
/// </summary>
private int recursionDepth = 0;
private int recursionLimit = DefaultRecursionLimit;
/// <summary>
/// <see cref="SetSizeLimit"/>
/// </summary>
private int sizeLimit = DefaultSizeLimit;
#region Construction
/// <summary>
/// Creates a new CodedInputStream reading data from the given
/// stream.
/// </summary>
public static CodedInputStream CreateInstance(Stream input) {
return new CodedInputStream(input);
}
/// <summary>
/// Creates a new CodedInputStream reading data from the given
/// byte array.
/// </summary>
public static CodedInputStream CreateInstance(byte[] buf) {
return new CodedInputStream(buf);
}
private CodedInputStream(byte[] buffer) {
this.buffer = buffer;
this.bufferSize = buffer.Length;
this.input = null;
}
private CodedInputStream(Stream input) {
this.buffer = new byte[BufferSize];
this.bufferSize = 0;
this.input = input;
}
#endregion
#region Validation
/// <summary>
/// Verifies that the last call to ReadTag() returned the given tag value.
/// This is used to verify that a nested group ended with the correct
/// end tag.
/// </summary>
/// <exception cref="InvalidProtocolBufferException">The last
/// tag read was not the one specified</exception>
public void CheckLastTagWas(uint value) {
if (lastTag != value) {
throw InvalidProtocolBufferException.InvalidEndTag();
}
}
#endregion
#region Reading of tags etc
/// <summary>
/// Attempt to read a field tag, returning 0 if we have reached the end
/// of the input data. Protocol message parsers use this to read tags,
/// since a protocol message may legally end wherever a tag occurs, and
/// zero is not a valid tag number.
/// </summary>
public uint ReadTag() {
if (bufferPos == bufferSize && !RefillBuffer(false)) {
lastTag = 0;
return 0;
}
lastTag = ReadRawVarint32();
if (lastTag == 0) {
// If we actually read zero, that's not a valid tag.
throw InvalidProtocolBufferException.InvalidTag();
}
return lastTag;
}
/// <summary>
/// Read a double field from the stream.
/// </summary>
public double ReadDouble() {
// TODO(jonskeet): Test this on different endiannesses
return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
}
/// <summary>
/// Read a float field from the stream.
/// </summary>
public float ReadFloat() {
// TODO(jonskeet): Test this on different endiannesses
uint raw = ReadRawLittleEndian32();
byte[] rawBytes = BitConverter.GetBytes(raw);
return BitConverter.ToSingle(rawBytes, 0);
}
/// <summary>
/// Read a uint64 field from the stream.
/// </summary>
public ulong ReadUInt64() {
return ReadRawVarint64();
}
/// <summary>
/// Read an int64 field from the stream.
/// </summary>
public long ReadInt64() {
return (long) ReadRawVarint64();
}
/// <summary>
/// Read an int32 field from the stream.
/// </summary>
public int ReadInt32() {
return (int) ReadRawVarint32();
}
/// <summary>
/// Read a fixed64 field from the stream.
/// </summary>
public ulong ReadFixed64() {
return ReadRawLittleEndian64();
}
/// <summary>
/// Read a fixed32 field from the stream.
/// </summary>
public uint ReadFixed32() {
return ReadRawLittleEndian32();
}
/// <summary>
/// Read a bool field from the stream.
/// </summary>
public bool ReadBool() {
return ReadRawVarint32() != 0;
}
/// <summary>
/// Reads a string field from the stream.
/// </summary>
public String ReadString() {
int size = (int) ReadRawVarint32();
if (size < bufferSize - bufferPos && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
String result = Encoding.UTF8.GetString(buffer, bufferPos, size);
bufferPos += size;
return result;
} else {
// Slow path: Build a byte array first then copy it.
return Encoding.UTF8.GetString(ReadRawBytes(size));
}
}
/// <summary>
/// Reads a group field value from the stream.
/// </summary>
public void ReadGroup(int fieldNumber, IBuilder builder,
ExtensionRegistry extensionRegistry) {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
++recursionDepth;
builder.WeakMergeFrom(this, extensionRegistry);
CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
--recursionDepth;
}
/// <summary>
/// Reads a group field value from the stream and merges it into the given
/// UnknownFieldSet.
/// </summary>
public void ReadUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder) {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
++recursionDepth;
builder.MergeFrom(this);
CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
--recursionDepth;
}
/// <summary>
/// Reads an embedded message field value from the stream.
/// </summary>
public void ReadMessage(IBuilder builder, ExtensionRegistry extensionRegistry) {
int length = (int) ReadRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
int oldLimit = PushLimit(length);
++recursionDepth;
builder.WeakMergeFrom(this, extensionRegistry);
CheckLastTagWas(0);
--recursionDepth;
PopLimit(oldLimit);
}
/// <summary>
/// Reads a bytes field value from the stream.
/// </summary>
public ByteString ReadBytes() {
int size = (int) ReadRawVarint32();
if (size < bufferSize - bufferPos && size > 0) {
// Fast path: We already have the bytes in a contiguous buffer, so
// just copy directly from it.
ByteString result = ByteString.CopyFrom(buffer, bufferPos, size);
bufferPos += size;
return result;
} else {
// Slow path: Build a byte array first then copy it.
return ByteString.CopyFrom(ReadRawBytes(size));
}
}
/// <summary>
/// Reads a uint32 field value from the stream.
/// </summary>
public uint ReadUInt32() {
return ReadRawVarint32();
}
/// <summary>
/// Reads an enum field value from the stream. The caller is responsible
/// for converting the numeric value to an actual enum.
/// </summary>
public int ReadEnum() {
return (int) ReadRawVarint32();
}
/// <summary>
/// Reads an sfixed32 field value from the stream.
/// </summary>
public int ReadSFixed32() {
return (int) ReadRawLittleEndian32();
}
/// <summary>
/// Reads an sfixed64 field value from the stream.
/// </summary>
public long ReadSFixed64() {
return (long) ReadRawLittleEndian64();
}
/// <summary>
/// Reads an sint32 field value from the stream.
/// </summary>
public int ReadSInt32() {
return DecodeZigZag32(ReadRawVarint32());
}
/// <summary>
/// Reads an sint64 field value from the stream.
/// </summary>
public long ReadSInt64() {
return DecodeZigZag64(ReadRawVarint64());
}
/// <summary>
/// Reads a field of any primitive type. Enums, groups and embedded
/// messages are not handled by this method.
/// </summary>
public object ReadPrimitiveField(FieldType fieldType) {
switch (fieldType) {
case FieldType.Double: return ReadDouble();
case FieldType.Float: return ReadFloat();
case FieldType.Int64: return ReadInt64();
case FieldType.UInt64: return ReadUInt64();
case FieldType.Int32: return ReadInt32();
case FieldType.Fixed64: return ReadFixed64();
case FieldType.Fixed32: return ReadFixed32();
case FieldType.Bool: return ReadBool();
case FieldType.String: return ReadString();
case FieldType.Bytes: return ReadBytes();
case FieldType.UInt32: return ReadUInt32();
case FieldType.SFixed32: return ReadSFixed32();
case FieldType.SFixed64: return ReadSFixed64();
case FieldType.SInt32: return ReadSInt32();
case FieldType.SInt64: return ReadSInt64();
case FieldType.Group:
throw new ArgumentException("ReadPrimitiveField() cannot handle nested groups.");
case FieldType.Message:
throw new ArgumentException("ReadPrimitiveField() cannot handle embedded messages.");
// We don't handle enums because we don't know what to do if the
// value is not recognized.
case FieldType.Enum:
throw new ArgumentException("ReadPrimitiveField() cannot handle enums.");
default:
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
}
}
#endregion
#region Underlying reading primitives
/// <summary>
/// Same code as ReadRawVarint32, but read each byte individually, checking for
/// buffer overflow.
/// </summary>
private uint SlowReadRawVarint32() {
int tmp = ReadRawByte();
if (tmp < 128) {
return (uint)tmp;
}
int result = tmp & 0x7f;
if ((tmp = ReadRawByte()) < 128) {
result |= tmp << 7;
} else {
result |= (tmp & 0x7f) << 7;
if ((tmp = ReadRawByte()) < 128) {
result |= tmp << 14;
} else {
result |= (tmp & 0x7f) << 14;
if ((tmp = ReadRawByte()) < 128) {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = ReadRawByte()) << 28;
if (tmp >= 128) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
if (ReadRawByte() < 128) return (uint)result;
}
throw InvalidProtocolBufferException.MalformedVarint();
}
}
}
}
return (uint)result;
}
/// <summary>
/// Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
/// This method is optimised for the case where we've got lots of data in the buffer.
/// That means we can check the size just once, then just read directly from the buffer
/// without constant rechecking of the buffer length.
/// </summary>
public uint ReadRawVarint32() {
if (bufferPos + 5 > bufferSize) {
return SlowReadRawVarint32();
}
int tmp = buffer[bufferPos++];
if (tmp < 128) {
return (uint)tmp;
}
int result = tmp & 0x7f;
if ((tmp = buffer[bufferPos++]) < 128) {
result |= tmp << 7;
} else {
result |= (tmp & 0x7f) << 7;
if ((tmp = buffer[bufferPos++]) < 128) {
result |= tmp << 14;
} else {
result |= (tmp & 0x7f) << 14;
if ((tmp = buffer[bufferPos++]) < 128) {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = buffer[bufferPos++]) << 28;
if (tmp >= 128) {
// Discard upper 32 bits.
// Note that this has to use ReadRawByte() as we only ensure we've
// got at least 5 bytes at the start of the method. This lets us
// use the fast path in more cases, and we rarely hit this section of code.
for (int i = 0; i < 5; i++) {
if (ReadRawByte() < 128) return (uint)result;
}
throw InvalidProtocolBufferException.MalformedVarint();
}
}
}
}
return (uint)result;
}
/// <summary>
/// Read a raw varint from the stream.
/// </summary>
public ulong ReadRawVarint64() {
int shift = 0;
ulong result = 0;
while (shift < 64) {
byte b = ReadRawByte();
result |= (ulong)(b & 0x7F) << shift;
if ((b & 0x80) == 0) {
return result;
}
shift += 7;
}
throw InvalidProtocolBufferException.MalformedVarint();
}
/// <summary>
/// Read a 32-bit little-endian integer from the stream.
/// </summary>
public uint ReadRawLittleEndian32() {
uint b1 = ReadRawByte();
uint b2 = ReadRawByte();
uint b3 = ReadRawByte();
uint b4 = ReadRawByte();
return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
}
/// <summary>
/// Read a 64-bit little-endian integer from the stream.
/// </summary>
public ulong ReadRawLittleEndian64() {
ulong b1 = ReadRawByte();
ulong b2 = ReadRawByte();
ulong b3 = ReadRawByte();
ulong b4 = ReadRawByte();
ulong b5 = ReadRawByte();
ulong b6 = ReadRawByte();
ulong b7 = ReadRawByte();
ulong b8 = ReadRawByte();
return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
| (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
}
#endregion
/// <summary>
/// Decode a 32-bit value with ZigZag encoding.
/// </summary>
/// <remarks>
/// ZigZag encodes signed integers into values that can be efficiently
/// encoded with varint. (Otherwise, negative values must be
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static int DecodeZigZag32(uint n) {
return (int)(n >> 1) ^ -(int)(n & 1);
}
/// <summary>
/// Decode a 32-bit value with ZigZag encoding.
/// </summary>
/// <remarks>
/// ZigZag encodes signed integers into values that can be efficiently
/// encoded with varint. (Otherwise, negative values must be
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static long DecodeZigZag64(ulong n) {
return (long)(n >> 1) ^ -(long)(n & 1);
}
/// <summary>
/// Set the maximum message recursion depth.
/// </summary>
/// <remarks>
/// In order to prevent malicious
/// messages from causing stack overflows, CodedInputStream limits
/// how deeply messages may be nested. The default limit is 64.
/// </remarks>
public int SetRecursionLimit(int limit) {
if (limit < 0) {
throw new ArgumentOutOfRangeException("Recursion limit cannot be negative: " + limit);
}
int oldLimit = recursionLimit;
recursionLimit = limit;
return oldLimit;
}
/// <summary>
/// Set the maximum message size.
/// </summary>
/// <remarks>
/// In order to prevent malicious messages from exhausting memory or
/// causing integer overflows, CodedInputStream limits how large a message may be.
/// The default limit is 64MB. You should set this limit as small
/// as you can without harming your app's functionality. Note that
/// size limits only apply when reading from an InputStream, not
/// when constructed around a raw byte array (nor with ByteString.NewCodedInput).
/// </remarks>
public int SetSizeLimit(int limit) {
if (limit < 0) {
throw new ArgumentOutOfRangeException("Size limit cannot be negative: " + limit);
}
int oldLimit = sizeLimit;
sizeLimit = limit;
return oldLimit;
}
#region Internal reading and buffer management
/// <summary>
/// Sets currentLimit to (current position) + byteLimit. This is called
/// when descending into a length-delimited embedded message. The previous
/// limit is returned.
/// </summary>
/// <returns>The old limit.</returns>
public int PushLimit(int byteLimit) {
if (byteLimit < 0) {
throw InvalidProtocolBufferException.NegativeSize();
}
byteLimit += totalBytesRetired + bufferPos;
int oldLimit = currentLimit;
if (byteLimit > oldLimit) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
currentLimit = byteLimit;
RecomputeBufferSizeAfterLimit();
return oldLimit;
}
private void RecomputeBufferSizeAfterLimit() {
bufferSize += bufferSizeAfterLimit;
int bufferEnd = totalBytesRetired + bufferSize;
if (bufferEnd > currentLimit) {
// Limit is in current buffer.
bufferSizeAfterLimit = bufferEnd - currentLimit;
bufferSize -= bufferSizeAfterLimit;
} else {
bufferSizeAfterLimit = 0;
}
}
/// <summary>
/// Discards the current limit, returning the previous limit.
/// </summary>
public void PopLimit(int oldLimit) {
currentLimit = oldLimit;
RecomputeBufferSizeAfterLimit();
}
/// <summary>
/// Called when buffer is empty to read more bytes from the
/// input. If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that
/// either there will be at least one byte in the buffer when it returns
/// or it will throw an exception. If <paramref name="mustSucceed"/> is false,
/// RefillBuffer() returns false if no more bytes were available.
/// </summary>
/// <param name="mustSucceed"></param>
/// <returns></returns>
private bool RefillBuffer(bool mustSucceed) {
if (bufferPos < bufferSize) {
throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
}
if (totalBytesRetired + bufferSize == currentLimit) {
// Oops, we hit a limit.
if (mustSucceed) {
throw InvalidProtocolBufferException.TruncatedMessage();
} else {
return false;
}
}
totalBytesRetired += bufferSize;
bufferPos = 0;
bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
if (bufferSize == 0) {
if (mustSucceed) {
throw InvalidProtocolBufferException.TruncatedMessage();
} else {
return false;
}
} else {
RecomputeBufferSizeAfterLimit();
int totalBytesRead =
totalBytesRetired + bufferSize + bufferSizeAfterLimit;
if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
throw InvalidProtocolBufferException.SizeLimitExceeded();
}
return true;
}
}
/// <summary>
/// Read one byte from the input.
/// </summary>
/// <exception cref="InvalidProtocolBufferException">
/// he end of the stream or the current limit was reached
/// </exception>
public byte ReadRawByte() {
if (bufferPos == bufferSize) {
RefillBuffer(true);
}
return buffer[bufferPos++];
}
/// <summary>
/// Read a fixed size of bytes from the input.
/// </summary>
/// <exception cref="InvalidProtocolBufferException">
/// the end of the stream or the current limit was reached
/// </exception>
public byte[] ReadRawBytes(int size) {
if (size < 0) {
throw InvalidProtocolBufferException.NegativeSize();
}
if (totalBytesRetired + bufferPos + size > currentLimit) {
// Read to the end of the stream anyway.
SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
// Then fail.
throw InvalidProtocolBufferException.TruncatedMessage();
}
if (size <= bufferSize - bufferPos) {
// We have all the bytes we need already.
byte[] bytes = new byte[size];
Array.Copy(buffer, bufferPos, bytes, 0, size);
bufferPos += size;
return bytes;
} else if (size < BufferSize) {
// Reading more bytes than are in the buffer, but not an excessive number
// of bytes. We can safely allocate the resulting array ahead of time.
// First copy what we have.
byte[] bytes = new byte[size];
int pos = bufferSize - bufferPos;
Array.Copy(buffer, bufferPos, bytes, 0, pos);
bufferPos = bufferSize;
// We want to use RefillBuffer() and then copy from the buffer into our
// byte array rather than reading directly into our byte array because
// the input may be unbuffered.
RefillBuffer(true);
while (size - pos > bufferSize) {
Array.Copy(buffer, 0, bytes, pos, bufferSize);
pos += bufferSize;
bufferPos = bufferSize;
RefillBuffer(true);
}
Array.Copy(buffer, 0, bytes, pos, size - pos);
bufferPos = size - pos;
return bytes;
} else {
// The size is very large. For security reasons, we can't allocate the
// entire byte array yet. The size comes directly from the input, so a
// maliciously-crafted message could provide a bogus very large size in
// order to trick the app into allocating a lot of memory. We avoid this
// by allocating and reading only a small chunk at a time, so that the
// malicious message must actually *be* extremely large to cause
// problems. Meanwhile, we limit the allowed size of a message elsewhere.
// Remember the buffer markers since we'll have to copy the bytes out of
// it later.
int originalBufferPos = bufferPos;
int originalBufferSize = bufferSize;
// Mark the current buffer consumed.
totalBytesRetired += bufferSize;
bufferPos = 0;
bufferSize = 0;
// Read all the rest of the bytes we need.
int sizeLeft = size - (originalBufferSize - originalBufferPos);
List<byte[]> chunks = new List<byte[]>();
while (sizeLeft > 0) {
byte[] chunk = new byte[Math.Min(sizeLeft, BufferSize)];
int pos = 0;
while (pos < chunk.Length) {
int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);
if (n <= 0) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
totalBytesRetired += n;
pos += n;
}
sizeLeft -= chunk.Length;
chunks.Add(chunk);
}
// OK, got everything. Now concatenate it all into one buffer.
byte[] bytes = new byte[size];
// Start by copying the leftover bytes from this.buffer.
int newPos = originalBufferSize - originalBufferPos;
Array.Copy(buffer, originalBufferPos, bytes, 0, newPos);
// And now all the chunks.
foreach (byte[] chunk in chunks) {
Array.Copy(chunk, 0, bytes, newPos, chunk.Length);
newPos += chunk.Length;
}
// Done.
return bytes;
}
}
/// <summary>
/// Reads and discards a single field, given its tag value.
/// </summary>
/// <returns>false if the tag is an end-group tag, in which case
/// nothing is skipped. Otherwise, returns true.</returns>
public bool SkipField(uint tag) {
switch (WireFormat.GetTagWireType(tag)) {
case WireFormat.WireType.Varint:
ReadInt32();
return true;
case WireFormat.WireType.Fixed64:
ReadRawLittleEndian64();
return true;
case WireFormat.WireType.LengthDelimited:
SkipRawBytes((int) ReadRawVarint32());
return true;
case WireFormat.WireType.StartGroup:
SkipMessage();
CheckLastTagWas(
WireFormat.MakeTag(WireFormat.GetTagFieldNumber(tag),
WireFormat.WireType.EndGroup));
return true;
case WireFormat.WireType.EndGroup:
return false;
case WireFormat.WireType.Fixed32:
ReadRawLittleEndian32();
return true;
default:
throw InvalidProtocolBufferException.InvalidWireType();
}
}
/// <summary>
/// Reads and discards an entire message. This will read either until EOF
/// or until an endgroup tag, whichever comes first.
/// </summary>
public void SkipMessage() {
while (true) {
uint tag = ReadTag();
if (tag == 0 || !SkipField(tag)) {
return;
}
}
}
/// <summary>
/// Reads and discards <paramref name="size"/> bytes.
/// </summary>
/// <exception cref="InvalidProtocolBufferException">the end of the stream
/// or the current limit was reached</exception>
public void SkipRawBytes(int size) {
if (size < 0) {
throw InvalidProtocolBufferException.NegativeSize();
}
if (totalBytesRetired + bufferPos + size > currentLimit) {
// Read to the end of the stream anyway.
SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
// Then fail.
throw InvalidProtocolBufferException.TruncatedMessage();
}
if (size < bufferSize - bufferPos) {
// We have all the bytes we need already.
bufferPos += size;
} else {
// Skipping more bytes than are in the buffer. First skip what we have.
int pos = bufferSize - bufferPos;
totalBytesRetired += pos;
bufferPos = 0;
bufferSize = 0;
// Then skip directly from the InputStream for the rest.
if (pos < size) {
// TODO(jonskeet): Java implementation uses skip(). Not sure whether this is really equivalent...
if (input == null) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
input.Seek(size - pos, SeekOrigin.Current);
if (input.Position > input.Length) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
totalBytesRetired += size - pos;
}
}
}
#endregion
}
}

@ -0,0 +1,765 @@
// 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;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// Encodes and writes protocol message fields.
/// </summary>
/// <remarks>
/// This class contains two kinds of methods: methods that write specific
/// protocol message constructs and field types (e.g. WriteTag and
/// WriteInt32) and methods that write low-level values (e.g.
/// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
/// messages, you should use the former methods, but if you are writing some
/// other format of your own design, use the latter. The names of the former
/// methods are taken from the protocol buffer type names, not .NET types.
/// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
/// </remarks>
public sealed class CodedOutputStream {
/// <summary>
/// The buffer size used by CreateInstance(Stream).
/// </summary>
public static readonly int DefaultBufferSize = 4096;
private readonly byte[] buffer;
private readonly int limit;
private int position;
private readonly Stream output;
#region Construction
private CodedOutputStream(byte[] buffer, int offset, int length) {
this.output = null;
this.buffer = buffer;
this.position = offset;
this.limit = offset + length;
}
private CodedOutputStream(Stream output, byte[] buffer) {
this.output = output;
this.buffer = buffer;
this.position = 0;
this.limit = buffer.Length;
}
/// <summary>
/// Creates a new CodedOutputStream which write to the given stream.
/// </summary>
public static CodedOutputStream CreateInstance(Stream output) {
return CreateInstance(output, DefaultBufferSize);
}
/// <summary>
/// Creates a new CodedOutputStream which write to the given stream and uses
/// the specified buffer size.
/// </summary>
public static CodedOutputStream CreateInstance(Stream output, int bufferSize) {
return new CodedOutputStream(output, new byte[bufferSize]);
}
/// <summary>
/// Creates a new CodedOutputStream that writes directly to the given
/// byte array. If more bytes are written than fit in the array,
/// OutOfSpaceException will be thrown.
/// </summary>
public static CodedOutputStream CreateInstance(byte[] flatArray) {
return CreateInstance(flatArray, 0, flatArray.Length);
}
/// <summary>
/// Creates a new CodedOutputStream that writes directly to the given
/// byte array slice. If more bytes are written than fit in the array,
/// OutOfSpaceException will be thrown.
/// </summary>
public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length) {
return new CodedOutputStream(flatArray, offset, length);
}
#endregion
#region Writing of tags etc
/// <summary>
/// Writes a double field value, including tag, to the stream.
/// </summary>
public void WriteDouble(int fieldNumber, double value) {
// TODO(jonskeet): Test this on different endiannesses
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
}
/// <summary>
/// Writes a float field value, including tag, to the stream.
/// </summary>
public void WriteFloat(int fieldNumber, float value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
// TODO(jonskeet): Test this on different endiannesses
byte[] rawBytes = BitConverter.GetBytes(value);
uint asInteger = BitConverter.ToUInt32(rawBytes, 0);
WriteRawLittleEndian32(asInteger);
}
/// <summary>
/// Writes a uint64 field value, including tag, to the stream.
/// </summary>
public void WriteUInt64(int fieldNumber, ulong value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint64(value);
}
/// <summary>
/// Writes an int64 field value, including tag, to the stream.
/// </summary>
public void WriteInt64(int fieldNumber, long value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint64((ulong)value);
}
/// <summary>
/// Writes an int32 field value, including tag, to the stream.
/// </summary>
public void WriteInt32(int fieldNumber, int value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
if (value >= 0) {
WriteRawVarint32((uint)value);
} else {
// Must sign-extend.
WriteRawVarint64((ulong)value);
}
}
/// <summary>
/// Writes a fixed64 field value, including tag, to the stream.
/// </summary>
public void WriteFixed64(int fieldNumber, ulong value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteRawLittleEndian64(value);
}
/// <summary>
/// Writes a fixed32 field value, including tag, to the stream.
/// </summary>
public void WriteFixed32(int fieldNumber, uint value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteRawLittleEndian32(value);
}
/// <summary>
/// Writes a bool field value, including tag, to the stream.
/// </summary>
public void WriteBool(int fieldNumber, bool value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawByte(value ? (byte)1 : (byte)0);
}
/// <summary>
/// Writes a string field value, including tag, to the stream.
/// </summary>
public void WriteString(int fieldNumber, string value) {
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
// Optimise the case where we have enough space to write
// the string directly to the buffer, which should be common.
int length = Encoding.UTF8.GetByteCount(value);
WriteRawVarint32((uint) length);
if (limit - position >= length) {
Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
position += length;
} else {
byte[] bytes = Encoding.UTF8.GetBytes(value);
WriteRawBytes(bytes);
}
}
/// <summary>
/// Writes a group field value, including tag, to the stream.
/// </summary>
public void WriteGroup(int fieldNumber, IMessage value) {
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
value.WriteTo(this);
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
public void WriteUnknownGroup(int fieldNumber, UnknownFieldSet value) {
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
value.WriteTo(this);
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
public void WriteMessage(int fieldNumber, IMessage value) {
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32((uint)value.SerializedSize);
value.WriteTo(this);
}
public void WriteBytes(int fieldNumber, ByteString value) {
// TODO(jonskeet): Optimise this! (No need to copy the bytes twice.)
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
byte[] bytes = value.ToByteArray();
WriteRawVarint32((uint)bytes.Length);
WriteRawBytes(bytes);
}
public void WriteUInt32(int fieldNumber, uint value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint32(value);
}
public void WriteEnum(int fieldNumber, int value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint32((uint)value);
}
public void WriteSFixed32(int fieldNumber, int value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
WriteRawLittleEndian32((uint)value);
}
public void WriteSFixed64(int fieldNumber, long value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteRawLittleEndian64((ulong)value);
}
public void WriteSInt32(int fieldNumber, int value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint32(EncodeZigZag32(value));
}
public void WriteSInt64(int fieldNumber, long value) {
WriteTag(fieldNumber, WireFormat.WireType.Varint);
WriteRawVarint64(EncodeZigZag64(value));
}
public void WriteMessageSetExtension(int fieldNumber, IMessage value) {
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber);
WriteMessage(WireFormat.MessageSetField.Message, value);
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
}
public void WriteRawMessageSetExtension(int fieldNumber, ByteString value) {
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber);
WriteBytes(WireFormat.MessageSetField.Message, value);
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
}
public void WriteField(FieldType fieldType, int fieldNumber, object value) {
switch (fieldType) {
case FieldType.Double: WriteDouble(fieldNumber, (double)value); break;
case FieldType.Float: WriteFloat(fieldNumber, (float)value); break;
case FieldType.Int64: WriteInt64(fieldNumber, (long)value); break;
case FieldType.UInt64: WriteUInt64(fieldNumber, (ulong)value); break;
case FieldType.Int32: WriteInt32(fieldNumber, (int)value); break;
case FieldType.Fixed64: WriteFixed64(fieldNumber, (ulong)value); break;
case FieldType.Fixed32: WriteFixed32(fieldNumber, (uint)value); break;
case FieldType.Bool: WriteBool(fieldNumber, (bool)value); break;
case FieldType.String: WriteString(fieldNumber, (string)value); break;
case FieldType.Group: WriteGroup(fieldNumber, (IMessage)value); break;
case FieldType.Message: WriteMessage(fieldNumber, (IMessage)value); break;
case FieldType.Bytes: WriteBytes(fieldNumber, (ByteString)value); break;
case FieldType.UInt32: WriteUInt32(fieldNumber, (uint)value); break;
case FieldType.SFixed32: WriteSFixed32(fieldNumber, (int)value); break;
case FieldType.SFixed64: WriteSFixed64(fieldNumber, (long)value); break;
case FieldType.SInt32: WriteSInt32(fieldNumber, (int)value); break;
case FieldType.SInt64: WriteSInt64(fieldNumber, (long)value); break;
case FieldType.Enum: WriteEnum(fieldNumber, ((EnumValueDescriptor)value).Number);
break;
}
}
#endregion
#region Underlying writing primitives
/// <summary>
/// Encodes and writes a tag.
/// </summary>
public void WriteTag(int fieldNumber, WireFormat.WireType type) {
WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
}
private void SlowWriteRawVarint32(uint value) {
while (true) {
if ((value & ~0x7F) == 0) {
WriteRawByte(value);
return;
} else {
WriteRawByte((value & 0x7F) | 0x80);
value >>= 7;
}
}
}
/// <summary>
/// Writes a 32 bit value as a varint. The fast route is taken when
/// there's enough buffer space left to whizz through without checking
/// for each byte; otherwise, we resort to calling WriteRawByte each time.
/// </summary>
public void WriteRawVarint32(uint value) {
if (position + 5 > limit) {
SlowWriteRawVarint32(value);
return;
}
while (true) {
if ((value & ~0x7F) == 0) {
buffer[position++] = (byte) value;
return;
} else {
buffer[position++] = (byte)((value & 0x7F) | 0x80);
value >>= 7;
}
}
}
public void WriteRawVarint64(ulong value) {
while (true) {
if ((value & ~0x7FUL) == 0) {
WriteRawByte((uint)value);
return;
} else {
WriteRawByte(((uint)value & 0x7F) | 0x80);
value >>= 7;
}
}
}
public void WriteRawLittleEndian32(uint value) {
WriteRawByte((byte)value);
WriteRawByte((byte)(value >> 8));
WriteRawByte((byte)(value >> 16));
WriteRawByte((byte)(value >> 24));
}
public void WriteRawLittleEndian64(ulong value) {
WriteRawByte((byte)value);
WriteRawByte((byte)(value >> 8));
WriteRawByte((byte)(value >> 16));
WriteRawByte((byte)(value >> 24));
WriteRawByte((byte)(value >> 32));
WriteRawByte((byte)(value >> 40));
WriteRawByte((byte)(value >> 48));
WriteRawByte((byte)(value >> 56));
}
public void WriteRawByte(byte value) {
if (position == limit) {
RefreshBuffer();
}
buffer[position++] = value;
}
public void WriteRawByte(uint value) {
WriteRawByte((byte)value);
}
/// <summary>
/// Writes out an array of bytes.
/// </summary>
public void WriteRawBytes(byte[] value) {
WriteRawBytes(value, 0, value.Length);
}
/// <summary>
/// Writes out part of an array of bytes.
/// </summary>
public void WriteRawBytes(byte[] value, int offset, int length) {
if (limit - position >= length) {
Array.Copy(value, offset, buffer, position, length);
// We have room in the current buffer.
position += length;
} else {
// Write extends past current buffer. Fill the rest of this buffer and
// flush.
int bytesWritten = limit - position;
Array.Copy(value, offset, buffer, position, bytesWritten);
offset += bytesWritten;
length -= bytesWritten;
position = limit;
RefreshBuffer();
// Now deal with the rest.
// Since we have an output stream, this is our buffer
// and buffer offset == 0
if (length <= limit) {
// Fits in new buffer.
Array.Copy(value, offset, buffer, 0, length);
position = length;
} else {
// Write is very big. Let's do it all at once.
output.Write(value, offset, length);
}
}
}
#endregion
#region Size computations
const int LittleEndian64Size = 8;
const int LittleEndian32Size = 4;
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// double field, including the tag.
/// </summary>
public static int ComputeDoubleSize(int fieldNumber, double value) {
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// float field, including the tag.
/// </summary>
public static int ComputeFloatSize(int fieldNumber, float value) {
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// uint64 field, including the tag.
/// </summary>
public static int ComputeUInt64Size(int fieldNumber, ulong value) {
return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size(value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// int64 field, including the tag.
/// </summary>
public static int ComputeInt64Size(int fieldNumber, long value) {
return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size((ulong)value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// int32 field, including the tag.
/// </summary>
public static int ComputeInt32Size(int fieldNumber, int value) {
if (value >= 0) {
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)value);
} else {
// Must sign-extend.
return ComputeTagSize(fieldNumber) + 10;
}
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// fixed64 field, including the tag.
/// </summary>
public static int ComputeFixed64Size(int fieldNumber, ulong value) {
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// fixed32 field, including the tag.
/// </summary>
public static int ComputeFixed32Size(int fieldNumber, uint value) {
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// bool field, including the tag.
/// </summary>
public static int ComputeBoolSize(int fieldNumber, bool value) {
return ComputeTagSize(fieldNumber) + 1;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// string field, including the tag.
/// </summary>
public static int ComputeStringSize(int fieldNumber, String value) {
int byteArraySize = Encoding.UTF8.GetByteCount(value);
return ComputeTagSize(fieldNumber) +
ComputeRawVarint32Size((uint)byteArraySize) +
byteArraySize;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// group field, including the tag.
/// </summary>
public static int ComputeGroupSize(int fieldNumber, IMessage value) {
return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// group field represented by an UnknownFieldSet, including the tag.
/// </summary>
public static int ComputeUnknownGroupSize(int fieldNumber,
UnknownFieldSet value) {
return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// embedded message field, including the tag.
/// </summary>
public static int ComputeMessageSize(int fieldNumber, IMessage value) {
int size = value.SerializedSize;
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)size) + size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// bytes field, including the tag.
/// </summary>
public static int ComputeBytesSize(int fieldNumber, ByteString value) {
return ComputeTagSize(fieldNumber) +
ComputeRawVarint32Size((uint)value.Length) +
value.Length;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// uint32 field, including the tag.
/// </summary>
public static int ComputeUInt32Size(int fieldNumber, uint value) {
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size(value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// enum field, including the tag. The caller is responsible for
/// converting the enum value to its numeric value.
/// </summary>
public static int ComputeEnumSize(int fieldNumber, int value) {
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sfixed32 field, including the tag.
/// </summary>
public static int ComputeSFixed32Size(int fieldNumber, int value) {
return ComputeTagSize(fieldNumber) + LittleEndian32Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sfixed64 field, including the tag.
/// </summary>
public static int ComputeSFixed64Size(int fieldNumber, long value) {
return ComputeTagSize(fieldNumber) + LittleEndian64Size;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sint32 field, including the tag.
/// </summary>
public static int ComputeSInt32Size(int fieldNumber, int value) {
return ComputeTagSize(fieldNumber) +
ComputeRawVarint32Size(EncodeZigZag32(value));
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// sint64 field, including the tag.
/// </summary>
public static int ComputeSInt64Size(int fieldNumber, long value) {
return ComputeTagSize(fieldNumber) +
ComputeRawVarint64Size(EncodeZigZag64(value));
}
/*
* Compute the number of bytes that would be needed to encode a
* MessageSet extension to the stream. For historical reasons,
* the wire format differs from normal fields.
*/
/// <summary>
/// Compute the number of bytes that would be needed to encode a
/// MessageSet extension to the stream. For historical reasons,
/// the wire format differs from normal fields.
/// </summary>
public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessage value) {
return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 +
ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
ComputeMessageSize(WireFormat.MessageSetField.Message, value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode an
/// unparsed MessageSet extension field to the stream. For
/// historical reasons, the wire format differs from normal fields.
/// </summary>
public static int ComputeRawMessageSetExtensionSize(int fieldNumber, ByteString value) {
return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 +
ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
ComputeBytesSize(WireFormat.MessageSetField.Message, value);
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a varint.
/// </summary>
public static int ComputeRawVarint32Size(uint value) {
if ((value & (0xffffffff << 7)) == 0) return 1;
if ((value & (0xffffffff << 14)) == 0) return 2;
if ((value & (0xffffffff << 21)) == 0) return 3;
if ((value & (0xffffffff << 28)) == 0) return 4;
return 5;
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a varint.
/// </summary>
public static int ComputeRawVarint64Size(ulong value) {
if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
return 10;
}
/*
* Compute the number of bytes that would be needed to encode a
* field of arbitrary type, including tag, to the stream.
*
* @param type The field's type.
* @param number The field's number.
* @param value Object representing the field's value. Must be of the exact
* type which would be returned by
* {@link Message#getField(FieldDescriptor)} for
* this field.
*/
public static int ComputeFieldSize(FieldType fieldType, int fieldNumber, Object value) {
switch (fieldType) {
case FieldType.Double: return ComputeDoubleSize(fieldNumber, (double)value);
case FieldType.Float: return ComputeFloatSize(fieldNumber, (float)value);
case FieldType.Int64: return ComputeInt64Size(fieldNumber, (long)value);
case FieldType.UInt64: return ComputeUInt64Size(fieldNumber, (ulong)value);
case FieldType.Int32: return ComputeInt32Size(fieldNumber, (int)value);
case FieldType.Fixed64: return ComputeFixed64Size(fieldNumber, (ulong)value);
case FieldType.Fixed32: return ComputeFixed32Size(fieldNumber, (uint)value);
case FieldType.Bool: return ComputeBoolSize(fieldNumber, (bool)value);
case FieldType.String: return ComputeStringSize(fieldNumber, (string)value);
case FieldType.Group: return ComputeGroupSize(fieldNumber, (IMessage)value);
case FieldType.Message: return ComputeMessageSize(fieldNumber, (IMessage)value);
case FieldType.Bytes: return ComputeBytesSize(fieldNumber, (ByteString)value);
case FieldType.UInt32: return ComputeUInt32Size(fieldNumber, (uint)value);
case FieldType.SFixed32: return ComputeSFixed32Size(fieldNumber, (int)value);
case FieldType.SFixed64: return ComputeSFixed64Size(fieldNumber, (long)value);
case FieldType.SInt32: return ComputeSInt32Size(fieldNumber, (int)value);
case FieldType.SInt64: return ComputeSInt64Size(fieldNumber, (long)value);
case FieldType.Enum: return ComputeEnumSize(fieldNumber, ((EnumValueDescriptor)value).Number);
default:
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
}
}
/// <summary>
/// Compute the number of bytes that would be needed to encode a tag.
/// </summary>
public static int ComputeTagSize(int fieldNumber) {
return ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0));
}
#endregion
/// <summary>
/// Encode a 32-bit value with ZigZag encoding.
/// </summary>
/// <remarks>
/// ZigZag encodes signed integers into values that can be efficiently
/// encoded with varint. (Otherwise, negative values must be
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static uint EncodeZigZag32(int n) {
// Note: the right-shift must be arithmetic
return (uint)((n << 1) ^ (n >> 31));
}
/// <summary>
/// Encode a 64-bit value with ZigZag encoding.
/// </summary>
/// <remarks>
/// ZigZag encodes signed integers into values that can be efficiently
/// encoded with varint. (Otherwise, negative values must be
/// sign-extended to 64 bits to be varint encoded, thus always taking
/// 10 bytes on the wire.)
/// </remarks>
public static ulong EncodeZigZag64(long n) {
return (ulong)((n << 1) ^ (n >> 63));
}
private void RefreshBuffer() {
if (output == null) {
// We're writing to a single buffer.
throw new OutOfSpaceException();
}
// Since we have an output stream, this is our buffer
// and buffer offset == 0
output.Write(buffer, 0, position);
position = 0;
}
/// <summary>
/// Indicates that a CodedOutputStream wrapping a flat byte array
/// ran out of space.
/// </summary>
public sealed class OutOfSpaceException : IOException {
internal OutOfSpaceException()
: base("CodedOutputStream was writing to a flat byte array and ran out of space.") {
}
}
public void Flush() {
if (output != null) {
RefreshBuffer();
}
}
/// <summary>
/// Verifies that SpaceLeft returns zero. It's common to create a byte array
/// that is exactly big enough to hold a message, then write to it with
/// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
/// the message was actually as big as expected, which can help bugs.
/// </summary>
public void CheckNoSpaceLeft() {
if (SpaceLeft != 0) {
throw new InvalidOperationException("Did not write as much data as expected.");
}
}
/// <summary>
/// If writing to a flat array, returns the space left in the array. Otherwise,
/// throws an InvalidOperationException.
/// </summary>
public int SpaceLeft {
get {
if (output == null) {
return limit - position;
} else {
throw new InvalidOperationException(
"SpaceLeft can only be called on CodedOutputStreams that are " +
"writing to a flat array.");
}
}
}
}
}

@ -0,0 +1,108 @@
// 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;
using System.Collections;
using System.Collections.Generic;
namespace Google.ProtocolBuffers.Collections {
/// <summary>
/// Non-generic class with generic methods which proxy to the non-generic methods
/// in the generic class.
/// </summary>
public static class Dictionaries {
/// <summary>
/// Compares two dictionaries for equality. Each value is compared with equality using Equals
/// for non-IEnumerable implementations, and using EnumerableEquals otherwise.
/// TODO(jonskeet): This is clearly pretty slow, and involves lots of boxing/unboxing...
/// </summary>
public static bool Equals<TKey, TValue>(IDictionary<TKey, TValue> left, IDictionary<TKey, TValue> right) {
if (left.Count != right.Count) {
return false;
}
foreach (KeyValuePair<TKey,TValue> leftEntry in left)
{
TValue rightValue;
if (!right.TryGetValue(leftEntry.Key, out rightValue)) {
return false;
}
IEnumerable leftEnumerable = leftEntry.Value as IEnumerable;
IEnumerable rightEnumerable = rightValue as IEnumerable;
if (leftEnumerable == null || rightEnumerable == null) {
if (!object.Equals(leftEntry.Value, rightValue)) {
return false;
}
} else {
IEnumerator leftEnumerator = leftEnumerable.GetEnumerator();
try {
foreach (object rightObject in rightEnumerable) {
if (!leftEnumerator.MoveNext()) {
return false;
}
if (!object.Equals(leftEnumerator.Current, rightObject)) {
return false;
}
}
if (leftEnumerator.MoveNext()) {
return false;
}
} finally {
if (leftEnumerator is IDisposable) {
((IDisposable)leftEnumerator).Dispose();
}
}
}
}
return true;
}
public static IDictionary<TKey, TValue> AsReadOnly<TKey, TValue> (IDictionary<TKey, TValue> dictionary) {
return dictionary.IsReadOnly ? dictionary : new ReadOnlyDictionary<TKey, TValue>(dictionary);
}
/// <summary>
/// Creates a hashcode for a dictionary by XORing the hashcodes of all the fields
/// and values. (By XORing, we avoid ordering issues.)
/// TODO(jonskeet): Currently XORs other stuff too, and assumes non-null values.
/// </summary>
public static int GetHashCode<TKey, TValue>(IDictionary<TKey, TValue> dictionary) {
int ret = 31;
foreach (KeyValuePair<TKey, TValue> entry in dictionary) {
int hash = entry.Key.GetHashCode() ^ GetDeepHashCode(entry.Value);
ret ^= hash;
}
return ret;
}
/// <summary>
/// Determines the hash of a value by either taking it directly or hashing all the elements
/// for IEnumerable implementations.
/// </summary>
private static int GetDeepHashCode(object value) {
IEnumerable iterable = value as IEnumerable;
if (iterable == null) {
return value.GetHashCode();
}
int hash = 29;
foreach (object element in iterable) {
hash = hash * 37 + element.GetHashCode();
}
return hash;
}
}
}

@ -0,0 +1,56 @@
// 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.Collections.Generic;
using System.Collections.ObjectModel;
namespace Google.ProtocolBuffers.Collections {
/// <summary>
/// Utility non-generic class for calling into Lists{T} using type inference.
/// </summary>
public static class Lists {
/// <summary>
/// Returns a read-only view of the specified list.
/// </summary>
public static IList<T> AsReadOnly<T>(IList<T> list) {
return Lists<T>.AsReadOnly(list);
}
}
/// <summary>
/// Utility class for dealing with lists.
/// </summary>
public static class Lists<T> {
static readonly ReadOnlyCollection<T> empty = new ReadOnlyCollection<T>(new T[0]);
/// <summary>
/// Returns an immutable empty list.
/// </summary>
public static ReadOnlyCollection<T> Empty {
get { return empty; }
}
/// <summary>
/// Returns either the original reference if it's already read-only,
/// or a new ReadOnlyCollection wrapping the original list.
/// </summary>
public static IList<T> AsReadOnly(IList<T> list) {
return list.IsReadOnly ? list : new ReadOnlyCollection<T>(list);
}
}
}

@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace Google.ProtocolBuffers.Collections {
/// <summary>
/// Proxies calls to a <see cref="List{T}" />, but allows the list
/// to be made read-only (with the <see cref="MakeReadOnly" /> method),
/// after which any modifying methods throw <see cref="NotSupportedException" />.
/// </summary>
public sealed class PopsicleList<T> : IList<T> {
private readonly List<T> items = new List<T>();
private bool readOnly = false;
/// <summary>
/// Makes this list read-only ("freezes the popsicle"). From this
/// point on, mutating methods (Clear, Add etc) will throw a
/// NotSupportedException. There is no way of "defrosting" the list afterwards.
/// </summary>
public void MakeReadOnly() {
readOnly = true;
}
public int IndexOf(T item) {
return items.IndexOf(item);
}
public void Insert(int index, T item) {
ValidateModification();
items.Insert(index, item);
}
public void RemoveAt(int index) {
ValidateModification();
items.RemoveAt(index);
}
public T this[int index] {
get {
return items[index];
}
set {
ValidateModification();
items[index] = value;
}
}
public void Add(T item) {
ValidateModification();
items.Add(item);
}
public void Clear() {
ValidateModification();
items.Clear();
}
public bool Contains(T item) {
return items.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex) {
items.CopyTo(array, arrayIndex);
}
public int Count {
get { return items.Count; }
}
public bool IsReadOnly {
get { return readOnly; }
}
public bool Remove(T item) {
ValidateModification();
return items.Remove(item);
}
public IEnumerator<T> GetEnumerator() {
return items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
private void ValidateModification() {
if (readOnly) {
throw new NotSupportedException("List is read-only");
}
}
}
}

@ -0,0 +1,112 @@
// 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;
using System.Collections;
using System.Collections.Generic;
namespace Google.ProtocolBuffers.Collections {
/// <summary>
/// Read-only wrapper around another dictionary.
/// </summary>
public sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue> {
readonly IDictionary<TKey, TValue> wrapped;
public ReadOnlyDictionary(IDictionary<TKey, TValue> wrapped) {
this.wrapped = wrapped;
}
public void Add(TKey key, TValue value) {
throw new InvalidOperationException();
}
public bool ContainsKey(TKey key) {
return wrapped.ContainsKey(key);
}
public ICollection<TKey> Keys {
get { return wrapped.Keys; }
}
public bool Remove(TKey key) {
throw new InvalidOperationException();
}
public bool TryGetValue(TKey key, out TValue value) {
return wrapped.TryGetValue(key, out value);
}
public ICollection<TValue> Values {
get { return wrapped.Values; }
}
public TValue this[TKey key] {
get {
return wrapped[key];
}
set {
throw new InvalidOperationException();
}
}
public void Add(KeyValuePair<TKey, TValue> item) {
throw new InvalidOperationException();
}
public void Clear() {
throw new InvalidOperationException();
}
public bool Contains(KeyValuePair<TKey, TValue> item) {
return wrapped.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
wrapped.CopyTo(array, arrayIndex);
}
public int Count {
get { return wrapped.Count; }
}
public bool IsReadOnly {
get { return true; }
}
public bool Remove(KeyValuePair<TKey, TValue> item) {
throw new InvalidOperationException();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
return wrapped.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return ((IEnumerable) wrapped).GetEnumerator();
}
public override bool Equals(object obj) {
return wrapped.Equals(obj);
}
public override int GetHashCode() {
return wrapped.GetHashCode();
}
public override string ToString() {
return wrapped.ToString();
}
}
}

@ -0,0 +1,32 @@
// 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.IO;
namespace Google.ProtocolBuffers {
/// <summary>
/// Delegate to return a stream when asked, used by MessageStreamIterator.
/// </summary>
public delegate Stream StreamProvider();
// These delegate declarations mirror the ones in .NET 3.5 for the sake of familiarity.
internal delegate TResult Func<TResult>();
internal delegate TResult Func<T, TResult>(T arg);
internal delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
internal delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
internal delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
internal delegate void Action();
internal delegate void Action<T1, T2>(T1 arg1, T2 arg2);
}

@ -0,0 +1,49 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace Google.ProtocolBuffers.DescriptorProtos {
public static partial class CSharpOptions {
#region Descriptor
public static pbd::FileDescriptor Descriptor {
get { return descriptor; }
}
private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(
global::System.Convert.FromBase64String(
"CiRnb29nbGUvcHJvdG9idWYvY3NoYXJwX29wdGlvbnMucHJvdG8SD2dvb2ds" +
"ZS5wcm90b2J1ZhogZ29vZ2xlL3Byb3RvYnVmL2Rlc2NyaXB0b3IucHJvdG86" +
"NwoPQ1NoYXJwTmFtZXNwYWNlEhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRp" +
"b25zGKCcASABKAk6PwoXQ1NoYXJwVW1icmVsbGFDbGFzc25hbWUSHC5nb29n" +
"bGUucHJvdG9idWYuRmlsZU9wdGlvbnMYoZwBIAEoCTo7ChNDU2hhcnBNdWx0" +
"aXBsZUZpbGVzEhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGKKcASAB" +
"KAg6OQoRQ1NoYXJwTmVzdENsYXNzZXMSHC5nb29nbGUucHJvdG9idWYuRmls" +
"ZU9wdGlvbnMYo5wBIAEoCDo7ChNDU2hhcnBQdWJsaWNDbGFzc2VzEhwuZ29v" +
"Z2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGKScASABKAhCPILiCSdHb29nbGUu" +
"UHJvdG9jb2xCdWZmZXJzLkRlc2NyaXB0b3JQcm90b3OK4gkNQ1NoYXJwT3B0" +
"aW9ucw=="),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
});
#endregion
#region Extensions
public static readonly pb::GeneratedExtensionBase<string> CSharpNamespace =
pb::GeneratedSingleExtension<string>.CreateInstance(Descriptor.Extensions[0]);
public static readonly pb::GeneratedExtensionBase<string> CSharpUmbrellaClassname =
pb::GeneratedSingleExtension<string>.CreateInstance(Descriptor.Extensions[1]);
public static readonly pb::GeneratedExtensionBase<bool> CSharpMultipleFiles =
pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[2]);
public static readonly pb::GeneratedExtensionBase<bool> CSharpNestClasses =
pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[3]);
public static readonly pb::GeneratedExtensionBase<bool> CSharpPublicClasses =
pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[4]);
#endregion
#region Static variables
#endregion
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,36 @@
// 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.
namespace Google.ProtocolBuffers.DescriptorProtos {
/// <summary>
/// Interface implemented by all DescriptorProtos. The generator doesn't
/// emit the interface implementation claim, so PartialClasses.cs contains
/// partial class declarations for each of them.
/// </summary>
/// <typeparam name="TOptions">The associated options protocol buffer type</typeparam>
public interface IDescriptorProto<TOptions> {
/// <summary>
/// The brief name of the descriptor's target.
/// </summary>
string Name { get; }
/// <summary>
/// The options for this descriptor.
/// </summary>
TOptions Options { get; }
}
}

@ -0,0 +1,43 @@
// 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.
// This file just contains partial classes for each of the
// autogenerated classes, so that they implement
// IDescriptorProto
namespace Google.ProtocolBuffers.DescriptorProtos {
// TODO(jonskeet): Find a better way of fixing this. It's needed in order to
// cope with unknown fields during initialization.
public partial class DescriptorProtoFile {
private static readonly bool initialized = false;
internal static bool Bootstrapping {
get { return !initialized; }
}
static DescriptorProtoFile() {
initialized = true;
}
}
public partial class DescriptorProto : IDescriptorProto<MessageOptions> { }
public partial class EnumDescriptorProto : IDescriptorProto<EnumOptions> { }
public partial class EnumValueDescriptorProto : IDescriptorProto<EnumValueOptions> { }
public partial class FieldDescriptorProto : IDescriptorProto<FieldOptions> { }
public partial class FileDescriptorProto : IDescriptorProto<FileOptions> { }
public partial class MethodDescriptorProto : IDescriptorProto<MethodOptions> { }
public partial class ServiceDescriptorProto : IDescriptorProto<ServiceOptions> { }
}

@ -0,0 +1,83 @@
// 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 Google.ProtocolBuffers.DescriptorProtos;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Base class for nearly all descriptors, providing common functionality.
/// </summary>
/// <typeparam name="TProto">Type of the protocol buffer form of this descriptor</typeparam>
/// <typeparam name="TOptions">Type of the options protocol buffer for this descriptor</typeparam>
public abstract class DescriptorBase<TProto, TOptions> : IDescriptor<TProto>
where TProto : IMessage, IDescriptorProto<TOptions> {
private readonly TProto proto;
private readonly FileDescriptor file;
private readonly string fullName;
protected DescriptorBase(TProto proto, FileDescriptor file, string fullName) {
this.proto = proto;
this.file = file;
this.fullName = fullName;
}
protected static string ComputeFullName(FileDescriptor file, MessageDescriptor parent, string name) {
if (parent != null) {
return parent.FullName + "." + name;
}
if (file.Package.Length > 0) {
return file.Package + "." + name;
}
return name;
}
IMessage IDescriptor.Proto {
get { return proto; }
}
/// <summary>
/// Returns the protocol buffer form of this descriptor
/// </summary>
public TProto Proto {
get { return proto; }
}
public TOptions Options {
get { return proto.Options; }
}
/// <summary>
/// The fully qualified name of the descriptor's target.
/// </summary>
public string FullName {
get { return fullName; }
}
/// <summary>
/// The brief name of the descriptor's target.
/// </summary>
public string Name {
get { return proto.Name; }
}
/// <value>
/// The file this descriptor was declared in.
/// </value>
public FileDescriptor File {
get { return file; }
}
}
}

@ -0,0 +1,281 @@
// 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.Collections.Generic;
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Contains lookup tables containing all the descriptors defined in a particular file.
/// </summary>
internal sealed class DescriptorPool {
private readonly IDictionary<string, IDescriptor> descriptorsByName =
new Dictionary<string, IDescriptor>();
private readonly IDictionary<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
new Dictionary<DescriptorIntPair, FieldDescriptor>();
private readonly IDictionary<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
new Dictionary<DescriptorIntPair, EnumValueDescriptor>();
private readonly DescriptorPool[] dependencies;
internal DescriptorPool(FileDescriptor[] dependencyFiles) {
dependencies = new DescriptorPool[dependencyFiles.Length];
for (int i = 0; i < dependencyFiles.Length; i++) {
dependencies[i] = dependencyFiles[i].DescriptorPool;
}
foreach (FileDescriptor dependency in dependencyFiles) {
AddPackage(dependency.Package, dependency);
}
}
/// <summary>
/// Finds a symbol of the given name within the pool.
/// </summary>
/// <typeparam name="T">The type of symbol to look for</typeparam>
/// <param name="fullName">Fully-qualified name to look up</param>
/// <returns>The symbol with the given name and type,
/// or null if the symbol doesn't exist or has the wrong type</returns>
internal T FindSymbol<T>(string fullName) where T : class, IDescriptor {
IDescriptor result;
descriptorsByName.TryGetValue(fullName, out result);
T descriptor = result as T;
if (descriptor != null) {
return descriptor;
}
foreach (DescriptorPool dependency in dependencies) {
dependency.descriptorsByName.TryGetValue(fullName, out result);
descriptor = result as T;
if (descriptor != null) {
return descriptor;
}
}
return null;
}
/// <summary>
/// Adds a package to the symbol tables. If a package by the same name
/// already exists, that is fine, but if some other kind of symbol
/// exists under the same name, an exception is thrown. If the package
/// has multiple components, this also adds the parent package(s).
/// </summary>
internal void AddPackage(string fullName, FileDescriptor file) {
int dotpos = fullName.LastIndexOf('.');
String name;
if (dotpos != -1) {
AddPackage(fullName.Substring(0, dotpos), file);
name = fullName.Substring(dotpos + 1);
} else {
name = fullName;
}
IDescriptor old;
if (descriptorsByName.TryGetValue(fullName, out old)) {
if (!(old is PackageDescriptor)) {
throw new DescriptorValidationException(file,
"\"" + name + "\" is already defined (as something other than a " +
"package) in file \"" + old.File.Name + "\".");
}
}
// TODO(jonskeet): Check issue 25 wrt the ordering of these parameters
descriptorsByName[fullName] = new PackageDescriptor(fullName, name, file);
}
/// <summary>
/// Adds a symbol to the symbol table.
/// </summary>
/// <exception cref="DescriptorValidationException">The symbol already existed
/// in the symbol table.</exception>
internal void AddSymbol(IDescriptor descriptor) {
ValidateSymbolName(descriptor);
String fullName = descriptor.FullName;
IDescriptor old;
if (descriptorsByName.TryGetValue(fullName, out old)) {
int dotPos = fullName.LastIndexOf('.');
string message;
if (descriptor.File == old.File) {
if (dotPos == -1) {
message = "\"" + fullName + "\" is already defined.";
} else {
message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" + fullName.Substring(0, dotPos) + "\".";
}
} else {
message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\".";
}
throw new DescriptorValidationException(descriptor, message);
}
descriptorsByName[fullName] = descriptor;
}
private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$", RegexOptions.Compiled);
/// <summary>
/// Verifies that the descriptor's name is valid (i.e. it contains
/// only letters, digits and underscores, and does not start with a digit).
/// </summary>
/// <param name="descriptor"></param>
private static void ValidateSymbolName(IDescriptor descriptor) {
if (descriptor.Name == "") {
throw new DescriptorValidationException(descriptor, "Missing name.");
}
if (!ValidationRegex.IsMatch(descriptor.Name)) {
throw new DescriptorValidationException(descriptor,
"\"" + descriptor.Name + "\" is not a valid identifier.");
}
}
/// <summary>
/// Returns the field with the given number in the given descriptor,
/// or null if it can't be found.
/// </summary>
internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number) {
FieldDescriptor ret;
fieldsByNumber.TryGetValue(new DescriptorIntPair(messageDescriptor, number), out ret);
return ret;
}
internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number) {
EnumValueDescriptor ret;
enumValuesByNumber.TryGetValue(new DescriptorIntPair(enumDescriptor, number), out ret);
return ret;
}
/// <summary>
/// Adds a field to the fieldsByNumber table.
/// </summary>
/// <exception cref="DescriptorValidationException">A field with the same
/// containing type and number already exists.</exception>
internal void AddFieldByNumber(FieldDescriptor field) {
DescriptorIntPair key = new DescriptorIntPair(field.ContainingType, field.FieldNumber);
FieldDescriptor old;
if (fieldsByNumber.TryGetValue(key, out old)) {
throw new DescriptorValidationException(field, "Field number " + field.FieldNumber +
"has already been used in \"" + field.ContainingType.FullName +
"\" by field \"" + old.Name + "\".");
}
fieldsByNumber[key] = field;
}
/// <summary>
/// Adds an enum value to the enumValuesByNumber table. If an enum value
/// with the same type and number already exists, this method does nothing.
/// (This is allowed; the first value defined with the number takes precedence.)
/// </summary>
internal void AddEnumValueByNumber(EnumValueDescriptor enumValue) {
DescriptorIntPair key = new DescriptorIntPair(enumValue.EnumDescriptor, enumValue.Number);
if (!enumValuesByNumber.ContainsKey(key)) {
enumValuesByNumber[key] = enumValue;
}
}
/// <summary>
/// Looks up a descriptor by name, relative to some other descriptor.
/// The name may be fully-qualified (with a leading '.'), partially-qualified,
/// or unqualified. C++-like name lookup semantics are used to search for the
/// matching descriptor.
/// </summary>
public IDescriptor LookupSymbol(string name, IDescriptor relativeTo) {
// TODO(jonskeet): This could be optimized in a number of ways.
IDescriptor result;
if (name.StartsWith(".")) {
// Fully-qualified name.
result = FindSymbol<IDescriptor>(name.Substring(1));
} else {
// If "name" is a compound identifier, we want to search for the
// first component of it, then search within it for the rest.
int firstPartLength = name.IndexOf('.');
string firstPart = firstPartLength == -1 ? name : name.Substring(0, firstPartLength);
// We will search each parent scope of "relativeTo" looking for the
// symbol.
StringBuilder scopeToTry = new StringBuilder(relativeTo.FullName);
while (true) {
// Chop off the last component of the scope.
// TODO(jonskeet): Make this more efficient. May not be worth using StringBuilder at all
int dotpos = scopeToTry.ToString().LastIndexOf(".");
if (dotpos == -1) {
result = FindSymbol<IDescriptor>(name);
break;
} else {
scopeToTry.Length = dotpos + 1;
// Append firstPart and try to find.
scopeToTry.Append(firstPart);
result = FindSymbol<IDescriptor>(scopeToTry.ToString());
if (result != null) {
if (firstPartLength != -1) {
// We only found the first part of the symbol. Now look for
// the whole thing. If this fails, we *don't* want to keep
// searching parent scopes.
scopeToTry.Length = dotpos + 1;
scopeToTry.Append(name);
result = FindSymbol<IDescriptor>(scopeToTry.ToString());
}
break;
}
// Not found. Remove the name so we can try again.
scopeToTry.Length = dotpos;
}
}
}
if (result == null) {
throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined.");
} else {
return result;
}
}
/// <summary>
/// Struct used to hold the keys for the fieldByNumber table.
/// </summary>
struct DescriptorIntPair : IEquatable<DescriptorIntPair> {
private readonly int number;
private readonly IDescriptor descriptor;
internal DescriptorIntPair(IDescriptor descriptor, int number) {
this.number = number;
this.descriptor = descriptor;
}
public bool Equals(DescriptorIntPair other) {
return descriptor == other.descriptor
&& number == other.number;
}
public override bool Equals(object obj) {
if (obj is DescriptorIntPair) {
return Equals((DescriptorIntPair)obj);
}
return false;
}
public override int GetHashCode() {
return descriptor.GetHashCode() * ((1 << 16) - 1) + number;
}
}
}
}

@ -0,0 +1,43 @@
// 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.Collections.Generic;
using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Internal class containing utility methods when working with descriptors.
/// </summary>
internal static class DescriptorUtil {
/// <summary>
/// Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert
/// arrays.
/// </summary>
internal delegate TOutput IndexedConverter<TInput, TOutput>(TInput element, int index);
/// <summary>
/// Converts the given array into a read-only list, applying the specified conversion to
/// each input element.
/// </summary>
internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>(IList<TInput> input,
IndexedConverter<TInput, TOutput> converter) {
TOutput[] array = new TOutput[input.Count];
for (int i = 0; i < array.Length; i++) {
array[i] = converter(input[i], i);
}
return Lists<TOutput>.AsReadOnly(array);
}
}
}

@ -0,0 +1,70 @@
// 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;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Thrown when building descriptors fails because the source DescriptorProtos
/// are not valid.
/// </summary>
public sealed class DescriptorValidationException : Exception {
private readonly String name;
private readonly IMessage proto;
private readonly string description;
/// <value>
/// The full name of the descriptor where the error occurred.
/// </value>
public String ProblemSymbolName {
get { return name; }
}
/// <value>
/// The protocol message representation of the invalid descriptor.
/// </value>
public IMessage ProblemProto {
get { return proto; }
}
/// <value>
/// A human-readable description of the error. (The Message property
/// is made up of the descriptor's name and this description.)
/// </value>
public string Description {
get { return description; }
}
internal DescriptorValidationException(IDescriptor problemDescriptor, string description) :
base(problemDescriptor.FullName + ": " + description) {
// Note that problemDescriptor may be partially uninitialized, so we
// don't want to expose it directly to the user. So, we only provide
// the name and the original proto.
name = problemDescriptor.FullName;
proto = problemDescriptor.Proto;
this.description = description;
}
internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) :
base(problemDescriptor.FullName + ": " + description, cause) {
name = problemDescriptor.FullName;
proto = problemDescriptor.Proto;
this.description = description;
}
}
}

@ -0,0 +1,76 @@
// 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.Collections.Generic;
using Google.ProtocolBuffers.DescriptorProtos;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Descriptor for an enum type in a .proto file.
/// </summary>
public sealed class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions> {
private readonly MessageDescriptor containingType;
private readonly IList<EnumValueDescriptor> values;
internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)
: base(proto, file, ComputeFullName(file, parent, proto.Name), index) {
containingType = parent;
if (proto.ValueCount == 0) {
// We cannot allow enums with no values because this would mean there
// would be no valid default value for fields of this type.
throw new DescriptorValidationException(this, "Enums must contain at least one value.");
}
values = DescriptorUtil.ConvertAndMakeReadOnly(proto.ValueList,
(value, i) => new EnumValueDescriptor(value, file, this, i));
File.DescriptorPool.AddSymbol(this);
}
/// <value>
/// If this is a nested type, get the outer descriptor, otherwise null.
/// </value>
public MessageDescriptor ContainingType {
get { return containingType; }
}
/// <value>
/// An unmodifiable list of defined value descriptors for this enum.
/// </value>
public IList<EnumValueDescriptor> Values {
get { return values; }
}
/// <summary>
/// Finds an enum value by number. If multiple enum values have the
/// same number, this returns the first defined value with that number.
/// </summary>
internal EnumValueDescriptor FindValueByNumber(int number) {
return File.DescriptorPool.FindEnumValueByNumber(this, number);
}
/// <summary>
/// Finds an enum value by name.
/// </summary>
/// <param name="name">The unqualified name of the value (e.g. "FOO").</param>
/// <returns>The value's descriptor, or null if not found.</returns>
internal EnumValueDescriptor FindValueByName(string name) {
return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name);
}
}
}

@ -0,0 +1,43 @@
// 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 Google.ProtocolBuffers.DescriptorProtos;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Descriptor for a single enum value within an enum in a .proto file.
/// </summary>
public sealed class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions> {
private readonly EnumDescriptor enumDescriptor;
internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file,
EnumDescriptor parent, int index)
: base (proto, file, parent.FullName + "." + proto.Name, index) {
enumDescriptor = parent;
file.DescriptorPool.AddSymbol(this);
file.DescriptorPool.AddEnumValueByNumber(this);
}
public int Number {
get { return Proto.Number; }
}
public EnumDescriptor EnumDescriptor {
get { return enumDescriptor; }
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save