Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
9fd0f1526f
3
.gitignore
vendored
3
.gitignore
vendored
@ -79,8 +79,7 @@ java/target
|
||||
javanano/target
|
||||
|
||||
# Windows native output.
|
||||
vsprojects/Debug
|
||||
vsprojects/Release
|
||||
cmake/build
|
||||
|
||||
# NuGet packages: we want the repository configuration, but not the
|
||||
# packages themselves.
|
||||
|
4
BUILD
4
BUILD
@ -162,10 +162,10 @@ cc_library(
|
||||
"src/google/protobuf/compiler/cpp/cpp_string_field.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_enum.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_extension.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_field_base.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_generator.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_helpers.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_map_field.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_message.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_message_field.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
|
||||
@ -174,7 +174,7 @@ cc_library(
|
||||
"src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_writer.cc",
|
||||
"src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
|
||||
"src/google/protobuf/compiler/java/java_context.cc",
|
||||
"src/google/protobuf/compiler/java/java_doc_comment.cc",
|
||||
"src/google/protobuf/compiler/java/java_enum.cc",
|
||||
|
354
Makefile.am
354
Makefile.am
@ -40,254 +40,112 @@ clean-local:
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = protobuf.pc protobuf-lite.pc
|
||||
|
||||
csharp_EXTRA_DIST= \
|
||||
csharp/src/ProtocolBuffers.sln \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestImportPublicLite.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasLite.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasFull.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestImport.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLiteImportsNonlite.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestImportLite.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestImportPublic.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/ExtendableMessageLiteTest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/packages.config \
|
||||
csharp/src/ProtocolBuffersLite.Test/LiteTest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/AbstractMessageLiteTest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/MissingFieldAndExtensionTest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/ProtocolBuffersLite.Test.csproj \
|
||||
csharp/src/ProtocolBuffersLite.Test/App.xaml.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/InteropLiteTest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/ExtendableBuilderLiteTest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/App.xaml \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestLiteByApi.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/Properties/AppManifest.xml \
|
||||
csharp/src/ProtocolBuffersLite.Test/Properties/OutOfBrowserSettings.xml \
|
||||
csharp/src/ProtocolBuffersLite.Test/ProtocolBuffersLiteMixed.Test.csproj \
|
||||
csharp/src/ProtocolBuffersLite.Test/AbstractBuilderLiteTest.cs \
|
||||
csharp/src/ProtoDump/ProtoDump.csproj \
|
||||
csharp/src/ProtoDump/app.config \
|
||||
csharp/src/ProtoDump/Program.cs \
|
||||
csharp/src/ProtoDump/Properties/AssemblyInfo.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/AbstractReader.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/JsonFormatReader.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/JsonTextCursor.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/ProtocolBuffers.Serialization.csproj \
|
||||
csharp/src/ProtocolBuffers.Serialization/DictionaryWriter.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/AbstractWriter.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/ProtocolBuffersLite.Serialization.csproj \
|
||||
csharp/src/ProtocolBuffers.Serialization/XmlReaderOptions.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/AbstractTextReader.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/XmlWriterOptions.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/JsonFormatWriter.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/Properties/AssemblyInfo.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/DictionaryReader.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/Extensions.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/AbstractTextWriter.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/XmlFormatWriter.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/Http/FormUrlEncodedReader.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/Http/MessageFormatOptions.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/Http/MessageFormatFactory.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/XmlFormatReader.cs \
|
||||
csharp/src/ProtocolBuffers.Serialization/RecursionLimitExceeded.cs \
|
||||
csharp/src/ProtoBench/GoogleSize.cs \
|
||||
csharp/src/ProtoBench/GoogleSpeed.cs \
|
||||
csharp/src/ProtoBench/UnittestImport.cs \
|
||||
csharp/src/ProtoBench/google_message1.dat \
|
||||
csharp/src/ProtoBench/ProtoBench.csproj \
|
||||
csharp/src/ProtoBench/app.config \
|
||||
csharp/src/ProtoBench/Program.cs \
|
||||
csharp/src/ProtoBench/google_message2.dat \
|
||||
csharp/src/ProtoBench/Properties/AssemblyInfo.cs \
|
||||
csharp/src/ProtoBench/Unittest.cs \
|
||||
csharp/src/ProtoBench/UnittestImportPublic.cs \
|
||||
csharp/src/ProtoMunge/app.config \
|
||||
csharp/src/ProtoMunge/Program.cs \
|
||||
csharp/src/ProtoMunge/Properties/AssemblyInfo.cs \
|
||||
csharp/src/ProtoMunge/ProtoMunge.csproj \
|
||||
csharp/src/ProtocolBuffers/GeneratedMessage.cs \
|
||||
csharp/src/ProtocolBuffers/ICodedInputStream.cs \
|
||||
csharp/src/ProtocolBuffers/AbstractBuilder.cs \
|
||||
csharp/src/ProtocolBuffers/FieldSet.cs \
|
||||
csharp/src/ProtocolBuffers/TextGenerator.cs \
|
||||
csharp/src/ProtocolBuffers/CodedInputStream.cs \
|
||||
csharp/src/ProtocolBuffers/GeneratedExtensionLite.cs \
|
||||
csharp/src/ProtocolBuffers/FrameworkPortability.cs \
|
||||
csharp/src/ProtocolBuffers/SortedList.cs \
|
||||
csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs \
|
||||
csharp/src/ProtocolBuffers/ExtendableMessage.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/ServiceDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/DescriptorBase.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/PackageDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/DescriptorValidationException.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/MethodDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/DescriptorUtil.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/MappedType.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/FieldType.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/IDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers/Descriptors/DescriptorPool.cs \
|
||||
csharp/src/ProtocolBuffers/Delegates.cs \
|
||||
csharp/src/ProtocolBuffers/AbstractMessageLite.cs \
|
||||
csharp/src/ProtocolBuffers/IMessageLite.cs \
|
||||
csharp/src/ProtocolBuffers/TextFormat.cs \
|
||||
csharp/src/ProtocolBuffers/Collections/Enumerables.cs \
|
||||
csharp/src/ProtocolBuffers/Collections/PopsicleList.cs \
|
||||
csharp/src/ProtocolBuffers/Collections/IPopsicleList.cs \
|
||||
csharp/src/ProtocolBuffers/Collections/ReadOnlyDictionary.cs \
|
||||
csharp/src/ProtocolBuffers/Collections/Dictionaries.cs \
|
||||
csharp/src/ProtocolBuffers/Collections/Lists.cs \
|
||||
csharp/src/ProtocolBuffers/IMessage.cs \
|
||||
csharp/src/ProtocolBuffers/TextTokenizer.cs \
|
||||
csharp/src/ProtocolBuffers/ByteString.cs \
|
||||
csharp/src/ProtocolBuffers/AbstractBuilderLite.cs \
|
||||
csharp/src/ProtocolBuffers/GeneratedExtensionBase.cs \
|
||||
csharp/src/ProtocolBuffers/EnumLite.cs \
|
||||
csharp/src/ProtocolBuffers/ByteArray.cs \
|
||||
csharp/src/ProtocolBuffers/ExtensionInfo.cs \
|
||||
csharp/src/ProtocolBuffers/MessageStreamIterator.cs \
|
||||
csharp/src/ProtocolBuffers/DynamicMessage.cs \
|
||||
csharp/src/ProtocolBuffers/ExtendableMessageLite.cs \
|
||||
csharp/src/ProtocolBuffers/ICodedOutputStream.cs \
|
||||
csharp/src/ProtocolBuffers/GeneratedRepeatExtension.cs \
|
||||
csharp/src/ProtocolBuffers/IBuilderLite.cs \
|
||||
csharp/src/ProtocolBuffers/UnknownField.cs \
|
||||
csharp/src/ProtocolBuffers/ThrowHelper.cs \
|
||||
csharp/src/ProtocolBuffers/UnknownFieldSet.cs \
|
||||
csharp/src/ProtocolBuffers/AbstractMessage.cs \
|
||||
csharp/src/ProtocolBuffers/GeneratedBuilderLite.cs \
|
||||
csharp/src/ProtocolBuffers/NameHelpers.cs \
|
||||
csharp/src/ProtocolBuffers/DescriptorProtos/PartialClasses.cs \
|
||||
csharp/src/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs \
|
||||
csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs \
|
||||
csharp/src/ProtocolBuffers/ExtendableBuilder.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/IFieldAccessor.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs \
|
||||
csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs \
|
||||
csharp/src/ProtocolBuffers/Properties/AssemblyInfo.cs \
|
||||
csharp/src/ProtocolBuffers/IBuilder.cs \
|
||||
csharp/src/ProtocolBuffers/ExtensionRegistry.cs \
|
||||
csharp/src/ProtocolBuffers/CodedOutputStream.cs \
|
||||
csharp/src/ProtocolBuffers/MessageStreamWriter.cs \
|
||||
csharp/src/ProtocolBuffers/MessageUtil.cs \
|
||||
csharp/src/ProtocolBuffers/UninitializedMessageException.cs \
|
||||
csharp/src/ProtocolBuffers/ProtocolBuffersLite.csproj \
|
||||
csharp/src/ProtocolBuffers/InvalidProtocolBufferException.cs \
|
||||
csharp/src/ProtocolBuffers/ProtocolBuffers.csproj \
|
||||
csharp/src/ProtocolBuffers/ExtendableBuilderLite.cs \
|
||||
csharp/src/ProtocolBuffers/GeneratedMessageLite.cs \
|
||||
csharp/src/ProtocolBuffers/GeneratedSingleExtension.cs \
|
||||
csharp/src/ProtocolBuffers/ExtensionRegistryLite.cs \
|
||||
csharp/src/ProtocolBuffers/WireFormat.cs \
|
||||
csharp/src/ProtocolBuffers/GeneratedBuilder.cs \
|
||||
csharp/src/AddressBook/ListPeople.cs \
|
||||
csharp/src/AddressBook/Addressbook.cs \
|
||||
csharp/src/AddressBook/AddPerson.cs \
|
||||
csharp/src/AddressBook/AddressBook.csproj \
|
||||
csharp/src/AddressBook/SampleUsage.cs \
|
||||
csharp/src/AddressBook/app.config \
|
||||
csharp/src/AddressBook/Program.cs \
|
||||
csharp/src/AddressBook/Properties/AssemblyInfo.cs \
|
||||
csharp/src/packages/repositories.config \
|
||||
csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/GoogleSize.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/GoogleSpeed.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestEnormousDescriptor.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnknownEnumTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestMset.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImport.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestCustomOptions.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestOptimizeFor.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestNoFieldPresence.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestExtrasXmltest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublic.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestDropUnknownFields.cs \
|
||||
csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/packages.config \
|
||||
csharp/src/ProtocolBuffers.Test/TestReaderForUrlEncoded.cs \
|
||||
csharp/src/ProtocolBuffers.Test/ByteStringTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/ReusableBuilderTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestUtil.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestResources.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj \
|
||||
csharp/src/ProtocolBuffers.Test/IssuesTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/UnknownFieldSetTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestMimeMessageFormats.cs \
|
||||
csharp/src/ProtocolBuffers.Test/App.xaml.cs \
|
||||
csharp/src/ProtocolBuffers.Test/DeprecatedMemberTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/MessageStreamWriterTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/NameHelpersTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestWriterFormatXml.cs \
|
||||
csharp/src/ProtocolBuffers.Test/ExtendableMessageTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/WireFormatTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestWriterFormatJson.cs \
|
||||
csharp/src/ProtocolBuffers.Test/MessageUtilTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/App.xaml \
|
||||
csharp/src/ProtocolBuffers.Test/Properties/AppManifest.xml \
|
||||
csharp/src/ProtocolBuffers.Test/Properties/AssemblyInfo.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Properties/OutOfBrowserSettings.xml \
|
||||
csharp/src/ProtocolBuffers.Test/TextFormatTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/MessageTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/DictionaryCompatibilityTests.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/TextCompatibilityTests.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/TestResources.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/google_message1.dat \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/CompatibilityTests.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/google_message2.dat \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs \
|
||||
csharp/src/ProtocolBuffers.Test/Compatibility/BinaryCompatibilityTests.cs \
|
||||
csharp/src/ProtocolBuffers.Test/GeneratedBuilderTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/ReflectionTester.cs \
|
||||
csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs \
|
||||
csharp/src/ProtocolBuffers.Test/TestCornerCases.cs \
|
||||
csharp/src/ProtocolBuffers.Test/MessageStreamIteratorTest.cs \
|
||||
csharp/buildall.sh \
|
||||
csharp/README.md \
|
||||
csharp/.gitignore \
|
||||
csharp/protos/extest/unittest_extras_lite.proto \
|
||||
csharp/protos/extest/unittest_extras_xmltest.proto \
|
||||
csharp/protos/extest/unittest_extras_full.proto \
|
||||
csharp/protos/extest/unittest_issues.proto \
|
||||
csharp/generate_protos.sh \
|
||||
csharp/CHANGES.txt \
|
||||
csharp/keys/generate_new_key.bat \
|
||||
csharp/keys/Google.ProtocolBuffers.snk \
|
||||
csharp/testdata/golden_message \
|
||||
csharp/testdata/text_format_unittest_data.txt \
|
||||
csharp/testdata/golden_packed_fields_message \
|
||||
csharp/testdata/text_format_unittest_extensions_data.txt \
|
||||
csharp/build/build.bat \
|
||||
csharp/build/googlecode_upload.py \
|
||||
csharp/build/build.csproj \
|
||||
csharp/build/Google.ProtocolBuffersLite.nuspec \
|
||||
csharp/build/Common.targets \
|
||||
csharp/build/Google.ProtocolBuffers.nuspec \
|
||||
csharp/build/target.csproj \
|
||||
csharp/build/nuspec.xsd \
|
||||
csharp/build/BuildAll.bat \
|
||||
csharp/build/RunBenchmarks.bat \
|
||||
csharp/build/publish.csproj
|
||||
csharp_EXTRA_DIST= \
|
||||
csharp/CHANGES.txt \
|
||||
csharp/README.md \
|
||||
csharp/build_packages.bat \
|
||||
csharp/buildall.sh \
|
||||
csharp/generate_protos.sh \
|
||||
csharp/keys/Google.Protobuf.public.snk \
|
||||
csharp/keys/README.md \
|
||||
csharp/protos/unittest_issues.proto \
|
||||
csharp/src/AddressBook/AddPerson.cs \
|
||||
csharp/src/AddressBook/AddressBook.csproj \
|
||||
csharp/src/AddressBook/Addressbook.cs \
|
||||
csharp/src/AddressBook/ListPeople.cs \
|
||||
csharp/src/AddressBook/Program.cs \
|
||||
csharp/src/AddressBook/Properties/AssemblyInfo.cs \
|
||||
csharp/src/AddressBook/SampleUsage.cs \
|
||||
csharp/src/AddressBook/app.config \
|
||||
csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj \
|
||||
csharp/src/Google.Protobuf.JsonDump/Program.cs \
|
||||
csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs \
|
||||
csharp/src/Google.Protobuf.JsonDump/app.config \
|
||||
csharp/src/Google.Protobuf.Test/ByteStringTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs \
|
||||
csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/EqualityTester.cs \
|
||||
csharp/src/Google.Protobuf.Test/FieldCodecTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj \
|
||||
csharp/src/Google.Protobuf.Test/IssuesTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml \
|
||||
csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs \
|
||||
csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/SampleEnum.cs \
|
||||
csharp/src/Google.Protobuf.Test/SampleMessages.cs \
|
||||
csharp/src/Google.Protobuf.Test/TestCornerCases.cs \
|
||||
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs \
|
||||
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs \
|
||||
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs \
|
||||
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs \
|
||||
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs \
|
||||
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs \
|
||||
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs \
|
||||
csharp/src/Google.Protobuf.Test/packages.config \
|
||||
csharp/src/Google.Protobuf.sln \
|
||||
csharp/src/Google.Protobuf/ByteArray.cs \
|
||||
csharp/src/Google.Protobuf/ByteString.cs \
|
||||
csharp/src/Google.Protobuf/CodedInputStream.cs \
|
||||
csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs \
|
||||
csharp/src/Google.Protobuf/CodedOutputStream.cs \
|
||||
csharp/src/Google.Protobuf/Collections/MapField.cs \
|
||||
csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs \
|
||||
csharp/src/Google.Protobuf/Collections/RepeatedField.cs \
|
||||
csharp/src/Google.Protobuf/FieldCodec.cs \
|
||||
csharp/src/Google.Protobuf/FrameworkPortability.cs \
|
||||
csharp/src/Google.Protobuf/Google.Protobuf.csproj \
|
||||
csharp/src/Google.Protobuf/Google.Protobuf.nuspec \
|
||||
csharp/src/Google.Protobuf/IMessage.cs \
|
||||
csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs \
|
||||
csharp/src/Google.Protobuf/JsonFormatter.cs \
|
||||
csharp/src/Google.Protobuf/LimitedInputStream.cs \
|
||||
csharp/src/Google.Protobuf/MessageExtensions.cs \
|
||||
csharp/src/Google.Protobuf/MessageParser.cs \
|
||||
csharp/src/Google.Protobuf/Preconditions.cs \
|
||||
csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/FieldType.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/IDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/PartialClasses.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs \
|
||||
csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Any.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Api.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Type.cs \
|
||||
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \
|
||||
csharp/src/Google.Protobuf/WireFormat.cs \
|
||||
csharp/src/packages/repositories.config
|
||||
|
||||
java_EXTRA_DIST= \
|
||||
java/src/main/java/com/google/protobuf/AbstractMessage.java \
|
||||
|
29
appveyor.bat
Normal file
29
appveyor.bat
Normal file
@ -0,0 +1,29 @@
|
||||
setlocal
|
||||
|
||||
IF %language%==cpp GOTO build_cpp
|
||||
IF %language%==csharp GOTO build_csharp
|
||||
|
||||
echo Unsupported language %language%. Exiting.
|
||||
goto :error
|
||||
|
||||
:build_cpp
|
||||
echo Building C++
|
||||
mkdir build_msvc
|
||||
cd build_msvc
|
||||
cmake -G "%generator%" -DBUILD_SHARED_LIBS=%BUILD_DLL% ../cmake
|
||||
msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
|
||||
cd %configuration%
|
||||
tests.exe || goto error
|
||||
goto :EOF
|
||||
|
||||
:build_csharp
|
||||
echo Building C#
|
||||
cd csharp\src
|
||||
nuget restore
|
||||
msbuild Google.Protobuf.sln /p:Platform="Any CPU" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
|
||||
nunit-console Google.Protobuf.Test\bin\%configuration%\Google.Protobuf.Test.dll || goto error
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo Failed!
|
||||
EXIT /b %ERRORLEVEL%
|
12
appveyor.yml
12
appveyor.yml
@ -9,7 +9,10 @@ configuration:
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- BUILD_DLL: ON
|
||||
- language: cpp
|
||||
BUILD_DLL: ON
|
||||
|
||||
- language: csharp
|
||||
|
||||
install:
|
||||
- ps: Start-FileDownload https://googlemock.googlecode.com/files/gmock-1.7.0.zip
|
||||
@ -23,12 +26,7 @@ before_build:
|
||||
- if %platform%==Win64 set vcplatform=x64
|
||||
|
||||
build_script:
|
||||
- mkdir build_msvc
|
||||
- cd build_msvc
|
||||
- cmake -G "%generator%" -DBUILD_SHARED_LIBS=%BUILD_DLL% ../cmake
|
||||
- msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
- cd %configuration%
|
||||
- tests.exe
|
||||
- CALL appveyor.bat
|
||||
|
||||
skip_commits:
|
||||
message: /.*\[skip appveyor\].*/
|
||||
|
@ -4,7 +4,6 @@ package benchmarks;
|
||||
|
||||
option java_outer_classname = "GoogleSize";
|
||||
option optimize_for = CODE_SIZE;
|
||||
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
|
||||
|
||||
message SizeMessage1 {
|
||||
required string field1 = 1;
|
||||
|
@ -4,7 +4,6 @@ package benchmarks;
|
||||
|
||||
option java_outer_classname = "GoogleSpeed";
|
||||
option optimize_for = SPEED;
|
||||
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
|
||||
|
||||
message SpeedMessage1 {
|
||||
required string field1 = 1;
|
||||
|
@ -21,6 +21,7 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generato
|
||||
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h include\google\protobuf\compiler\command_line_interface.h
|
||||
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
|
||||
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h include\google\protobuf\compiler\csharp\csharp_generator.h
|
||||
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h include\google\protobuf\compiler\csharp\csharp_names.h
|
||||
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
|
||||
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
|
||||
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h include\google\protobuf\compiler\java\java_names.h
|
||||
|
@ -24,6 +24,7 @@ set(libprotobuf_lite_files
|
||||
|
||||
add_library(libprotobuf-lite ${libprotobuf_lite_files})
|
||||
target_link_libraries(libprotobuf-lite ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_include_directories(libprotobuf-lite PUBLIC ${protobuf_source_dir}/src)
|
||||
set_target_properties(libprotobuf-lite PROPERTIES
|
||||
COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS
|
||||
OUTPUT_NAME ${LIB_PREFIX}protobuf-lite)
|
||||
|
@ -54,6 +54,7 @@ set(libprotobuf_files
|
||||
|
||||
add_library(libprotobuf ${libprotobuf_lite_files} ${libprotobuf_files})
|
||||
target_link_libraries(libprotobuf ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
|
||||
target_include_directories(libprotobuf PUBLIC ${protobuf_source_dir}/src)
|
||||
set_target_properties(libprotobuf PROPERTIES
|
||||
COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS
|
||||
OUTPUT_NAME ${LIB_PREFIX}protobuf)
|
||||
|
@ -16,10 +16,10 @@ set(libprotoc_files
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_extension.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_field_base.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_helpers.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_map_field.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message_field.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
|
||||
@ -28,7 +28,7 @@ set(libprotoc_files
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_writer.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_context.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum.cc
|
||||
|
26
csharp/.gitignore
vendored
26
csharp/.gitignore
vendored
@ -3,25 +3,12 @@
|
||||
#
|
||||
src/AddressBook/bin
|
||||
src/AddressBook/obj
|
||||
src/ProtocolBuffers/bin/
|
||||
src/ProtocolBuffers/obj/
|
||||
src/ProtocolBuffers/objCF
|
||||
src/ProtocolBuffers.Serialization/bin/
|
||||
src/ProtocolBuffers.Serialization/obj/
|
||||
src/ProtocolBuffers.Test/bin/
|
||||
src/ProtocolBuffers.Test/obj/
|
||||
src/ProtocolBuffersLite.Test/bin/
|
||||
src/ProtocolBuffersLite.Test/obj/
|
||||
src/ProtoBench/bin/
|
||||
src/ProtoBench/obj/
|
||||
src/ProtoDump/bin/
|
||||
src/ProtoDump/obj/
|
||||
src/ProtoGen/bin/
|
||||
src/ProtoGen/obj/
|
||||
src/ProtoGen.Test/bin/
|
||||
src/ProtoGen.Test/obj/
|
||||
src/ProtoMunge/bin/
|
||||
src/ProtoMunge/obj/
|
||||
src/Google.Protobuf/bin/
|
||||
src/Google.Protobuf/obj/
|
||||
src/Google.Protobuf.Test/bin/
|
||||
src/Google.Protobuf.Test/obj/
|
||||
src/Google.Protobuf.JsonDump/bin/
|
||||
src/Google.Protobuf.JsonDump/obj/
|
||||
mono/bin
|
||||
mono/tmp
|
||||
mono/protoc
|
||||
@ -36,6 +23,7 @@ lib/NUnit
|
||||
#
|
||||
*.user
|
||||
*.suo
|
||||
*.nupkg
|
||||
_ReSharper.*
|
||||
*.sln.cache
|
||||
mono/TestResult.xml
|
||||
|
@ -1,33 +1,45 @@
|
||||
|
||||
This directory contains the C# Protocol Buffers runtime library.
|
||||
|
||||
Warning: experimental!
|
||||
======================
|
||||
|
||||
This code is still under significant churn. Unlike the original port,
|
||||
it only supports proto3 (but not *all* of proto3 yet) - there are no
|
||||
unknown fields or extensions, for example. protoc will (eventually)
|
||||
deliberately fail if it is asked to generate C# code for proto2
|
||||
messages other than descriptor.proto, which is still required for
|
||||
reflection. (It's currently exposed publicly, but won't be
|
||||
eventually.)
|
||||
|
||||
Also unlike the original port, the new version embraces mutability -
|
||||
there are no builder types. We plan to add "freezing" operations as
|
||||
well as cloning, however.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The easiest way to use C# protocol buffers in your project is to use the [Google.ProtocolBuffers NuGet package](http://www.nuget.org/packages/Google.ProtocolBuffers/). This package is the legacy package for C# protocol buffers, but it will work fine with C# code generated by `protoc` if you use proto2 syntax (The API of the runtime library haven't changed so far).
|
||||
Use `protoc` with the `--csharp_out` option to generate C# files in the specified directory.
|
||||
Include these in your C# project, and add a reference to the `Google.Protobuf` project. Currently
|
||||
there is no NuGet package for this, but we will be building one as soon as the API is stable.
|
||||
|
||||
*WARNING: If you specify `syntax = "proto3";` in your .proto files, the generated code won't necessarily work with the legacy NuGet package. So before we officially add proto3 support, always use `syntax = "proto2";` (the default) in your protos.*
|
||||
Supported platforms
|
||||
===================
|
||||
|
||||
We will definitely release a new NuGet package for the runtime library in the future. The new runtime library WILL contain significant semantic, backwardly-incompatible changes in proto handling (mostly because we will be adding proto3 support and we will be using that oportunity to make some design changes). So keep in mind that you will need to regenerate your proto files and switch to a new NuGet package once the new version of runtime library becomes available.
|
||||
The runtime library is built as a portable class library, supporting:
|
||||
|
||||
- .NET 4.5
|
||||
- Windows 8
|
||||
- Windows Phone Silverlight 8
|
||||
- Windows Phone 8.1
|
||||
- .NET Core (dnxcore)
|
||||
|
||||
Building
|
||||
========
|
||||
|
||||
Open the `src/ProtocolBuffers.sln` solution in Visual Studio. Click "Build solution" to build the solution. You should be able to run the NUnit test from Test Explorer (you might need to install NUnit Visual Studio add-in).
|
||||
Open the `src/Google.Protobuf.sln` solution in Visual Studio. Click "Build solution" to build the solution. You should be able to run the NUnit test from Test Explorer (you might need to install NUnit Visual Studio add-in).
|
||||
|
||||
Supported Visual Studio versions are VS2013 (update 4) and VS2015. On Linux, you can also use Monodevelop 5.9 (older versions might work fine).
|
||||
|
||||
Proto2 & Proto3
|
||||
===============
|
||||
|
||||
*WARNING: Only proto2 is supported for now, proto3 is under construction.*
|
||||
|
||||
C# protocol buffers are currently under development and you should expect semantic, backward-incompatible changes in the future.
|
||||
|
||||
Also, as of now, only proto2 is supported. Proto3 support for C# is currently in progress
|
||||
(both design & implementation) and you should not expect any of the proto3 features to work.
|
||||
In fact, always use `syntax = "proto2";` in your .proto files for now, unless you are feeling like experimenting.
|
||||
|
||||
History of C# protobufs
|
||||
=======================
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
@echo off
|
||||
SET BUILD_TARGET=%~1
|
||||
SET BUILD_CONFIG=%~2
|
||||
|
||||
IF "%BUILD_TARGET%"=="" SET BUILD_TARGET=Rebuild
|
||||
IF "%BUILD_CONFIG%"=="" SET BUILD_CONFIG=Debug
|
||||
|
||||
CMD.exe /Q /C "CD %~dp0 && %WINDIR%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /nologo build.csproj /t:%BUILD_TARGET% /toolsversion:4.0 "/p:Configuration=%BUILD_CONFIG%" %3 %4 %5 %6
|
@ -1,122 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For Clean
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_CleanFolder">
|
||||
<Message Importance="normal" Text="Removing temporary directory '$(CleanFolderDirectory)'"/>
|
||||
<Error Text="Can not remove empty directory name." Condition=" '$(CleanFolderDirectory)' == '' " />
|
||||
|
||||
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" Condition="Exists($(CleanFolderDirectory))" Outputs="@(Ignore)"
|
||||
Command="MOVE /Y "$(CleanFolderDirectory)" "$(CleanFolderDirectory)-deleted" > NUL" />
|
||||
|
||||
<RemoveDir Directories="$(CleanFolderDirectory)-deleted" Condition="Exists('$(CleanFolderDirectory)-deleted')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CleanTempOutput">
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)" Properties="CleanFolderDirectory=%(TempBuildFolder.Identity);" Targets="_CleanFolder" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CleanAll" DependsOnTargets="_CleanTempOutput">
|
||||
<MakeDir Directories="$(BuildTempDirectory)" />
|
||||
<MakeDir Directories="$(BuildOutputDirectory)" />
|
||||
</Target>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For Build
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_CompileAll">
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)" Properties="SolutionTarget=Rebuild;" Targets="_BuildAllConfigurations" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_BuildAllConfigurations">
|
||||
<MSBuild Properties="TargetVersion=cf20;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=cf35;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=net20;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=net35;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=net40;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=sl20;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=sl30;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=sl40;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="TargetVersion=pl40;Configuration=$(Configuration);Platform=$(Platform);" Targets="$(SolutionTarget)" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
</Target>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For Tools
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_BuildTools">
|
||||
|
||||
<MSBuild Targets="Build" ToolsVersion="3.5" Projects="$(ProjectDirectory)\src\ProtocolBuffers.sln" Properties="Configuration=Release;Platform=Any CPU;" />
|
||||
<Copy SourceFiles="%(ToolsOutputItem.Identity)" DestinationFolder="$(BuildOutputDirectory)\tools" />
|
||||
|
||||
<Copy SourceFiles="$(LibDirectory)\NUnit-config\nunit-console.v2.0.config" DestinationFiles="$(NUnitExePath).config" />
|
||||
<Exec
|
||||
WorkingDirectory="%(ToolsTestContainer.RootDir)%(ToolsTestContainer.Directory)"
|
||||
Command=""$(NUnitExePath)" /nologo /noshadow "%(ToolsTestContainer.Identity)" /xml:"$(BuildTempDirectory)\%(ToolsTestContainer.Filename).xml"" />
|
||||
|
||||
</Target>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For GenerateSource
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_GenerateProjects">
|
||||
<Exec Command=""$(CsProjectProjector)" csproj_templates src\ProtocolBuffersLibrary.sln" WorkingDirectory="$(ProjectDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CleanTempSource">
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)" Properties="CleanFolderDirectory=$(SourceTempDirectory);" Targets="_CleanFolder" />
|
||||
<MakeDir Directories="$(SourceTempDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_GenerateSource" DependsOnTargets="_CleanTempSource">
|
||||
<Message Importance="high" Text="Generating source from proto files" />
|
||||
<Exec Command=""$(ProtocExePath)" --proto_path=$(ProtosDirectory) --descriptor_set_out=compiled.pb @(Protos->'%(RelativeDir)%(Filename)%(Extension)', ' ')" WorkingDirectory="$(SourceTempDirectory)" />
|
||||
<Exec Command=""$(ProtogenExePath)" compiled.pb" WorkingDirectory="$(SourceTempDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CopyGeneratedSource" DependsOnTargets="_GenerateSource">
|
||||
<Copy SourceFiles="%(GeneratedSource.Identity)" DestinationFiles="%(GeneratedSource.TargetDirectory)\%(GeneratedSource.Filename)%(GeneratedSource.Extension)" />
|
||||
</Target>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For Package
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_PackageAll">
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)" Properties="SolutionTarget=_Publish;" Targets="_BuildAllConfigurations" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_GeneratePackage">
|
||||
<Copy SourceFiles="@(StaticPackageItem)" DestinationFolder="$(BuildOutputPackage)\%(StaticPackageItem.TargetDirectory)\%(StaticPackageItem.RecursiveDir)" />
|
||||
<Exec Command=""$(ZipExePath)" a -tzip $(BuildTempDirectory)\$(PackageName)-binaries.zip * -x!*.pdb -r" WorkingDirectory="$(BuildOutputPackage)" />
|
||||
<Exec Command=""$(ZipExePath)" a -tzip $(BuildTempDirectory)\$(PackageName)-symbols.zip * -r" WorkingDirectory="$(BuildOutputPackage)" />
|
||||
</Target>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For Benchmark
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_RunBenchmarks">
|
||||
<ItemGroup>
|
||||
<BenchmarkParameter Include="Google.ProtocolBuffers.ProtoBench.SizeMessage1,ProtoBench" />
|
||||
<BenchmarkParameter Include="google_message1.dat" />
|
||||
<BenchmarkParameter Include="Google.ProtocolBuffers.ProtoBench.SpeedMessage1,ProtoBench" />
|
||||
<BenchmarkParameter Include="google_message1.dat" />
|
||||
<BenchmarkParameter Include="Google.ProtocolBuffers.ProtoBench.SizeMessage2,ProtoBench" />
|
||||
<BenchmarkParameter Include="google_message2.dat" />
|
||||
<BenchmarkParameter Include="Google.ProtocolBuffers.ProtoBench.SpeedMessage2,ProtoBench" />
|
||||
<BenchmarkParameter Include="google_message2.dat" />
|
||||
</ItemGroup>
|
||||
|
||||
<Message Text="Running ProtoBench.exe" />
|
||||
<Exec Command="ProtoBench.exe $(BenchmarkArgs) @(BenchmarkParameter->'%(Identity)', ' ') "/log:$(BenchmarkOutputFile)""
|
||||
WorkingDirectory="$(SourceDirectory)\ProtoBench\bin\NET35\Release" />
|
||||
|
||||
</Target>
|
||||
|
||||
</Project>
|
@ -1,59 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Google.ProtocolBuffers</id>
|
||||
<version>$version$</version>
|
||||
<owners>Jon Skeet</owners>
|
||||
<authors>Jon Skeet</authors>
|
||||
<licenseUrl>http://code.google.com/p/protobuf-csharp-port/source/browse/license.txt</licenseUrl>
|
||||
<projectUrl>http://code.google.com/p/protobuf-csharp-port/</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<copyright>Copyright 2008 Google Inc. All rights reserved.</copyright>
|
||||
<tags>Protocol Buffers Binary Serialization Format Google</tags>
|
||||
|
||||
<title>Google.ProtocolBuffers</title>
|
||||
<summary>A managed code generator and library for Google's data interchange format.</summary>
|
||||
<description><![CDATA[
|
||||
Protocol Buffers is a binary serialization format and technology, released to the open source community by Google in 2008.
|
||||
Its primary use is to produce small fast binary representations of a 'message' or object for serialization or transportation.
|
||||
There are various implementations of Protocol Buffers in .NET. This project is a fairly close port of the Google Java implementation.
|
||||
|
||||
There are two main parts:
|
||||
|
||||
tools/protoc.exe, which takes the textual representation of the protocol buffer and turns it into a binary representation for use with ProtoGen.exe.
|
||||
tools/ProtoGen.exe, which takes binary representations of protocol buffer descriptors (as generated by the "stock" protoc binary supplied by Google) and creates C# source code. This is only required at build time.
|
||||
|
||||
lib/*/Google.ProtocolBuffers.dll, which is a supporting library. This is required at execution time.
|
||||
lib/*/Google.ProtocolBuffers.Serialization.dll, a supplementary library that provides extensions for reading and writing protocol buffers to xml, json, and others.
|
||||
|
||||
LINKS:
|
||||
|
||||
Project Home - http://code.google.com/p/protobuf-csharp-port
|
||||
Online Help - http://help.protobuffers.net
|
||||
Developer Guide - http://code.google.com/apis/protocolbuffers/docs/overview.html
|
||||
Language Guide - http://code.google.com/apis/protocolbuffers/docs/proto.html
|
||||
|
||||
]]></description>
|
||||
|
||||
<references>
|
||||
<reference file="Google.ProtocolBuffers.dll"/>
|
||||
<reference file="Google.ProtocolBuffers.Serialization.dll"/>
|
||||
</references>
|
||||
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- Release Binaries -->
|
||||
<file src="..\build_output\Release\**\Google.ProtocolBuffers.???" target="lib\" />
|
||||
<file src="..\build_output\Release\**\Google.ProtocolBuffers.Serialization.???" target="lib\" />
|
||||
<!-- Tools -->
|
||||
<file src="..\build_output\tools\**\*" target="tools\" />
|
||||
<file src="..\build_output\protos\**\*" target="tools\" />
|
||||
<!-- Content -->
|
||||
<file src="..\build_output\CHANGES.txt" target="tools\"/>
|
||||
<file src="..\build_output\license.txt" target="tools\"/>
|
||||
<file src="..\build_output\tools\protoc-license.txt" target="tools\"/>
|
||||
<!-- Source -->
|
||||
<file src="..\src\ProtocolBuffers\**\*.cs" target="src\ProtocolBuffers\"/>
|
||||
<file src="..\src\ProtocolBuffers.Serialization\**\*.cs" target="src\ProtocolBuffers.Serialization\"/>
|
||||
</files>
|
||||
</package>
|
@ -1,60 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Google.ProtocolBuffersLite</id>
|
||||
<version>$version$</version>
|
||||
<owners>Jon Skeet</owners>
|
||||
<authors>Jon Skeet</authors>
|
||||
<licenseUrl>http://code.google.com/p/protobuf-csharp-port/source/browse/license.txt</licenseUrl>
|
||||
<projectUrl>http://code.google.com/p/protobuf-csharp-port/</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<copyright>Copyright 2008 Google Inc. All rights reserved.</copyright>
|
||||
<tags>Protocol Buffers Binary Serialization Format Google</tags>
|
||||
|
||||
<title>Google.ProtocolBuffersLite</title>
|
||||
<summary>A managed code generator and library for Google's data interchange format.</summary>
|
||||
<description><![CDATA[
|
||||
Protocol Buffers is a binary serialization format and technology, released to the open source community by Google in 2008.
|
||||
Its primary use is to produce small fast binary representations of a 'message' or object for serialization or transportation.
|
||||
There are various implementations of Protocol Buffers in .NET. This project is a fairly close port of the Google Java implementation.
|
||||
|
||||
There are two main parts:
|
||||
|
||||
tools/protoc.exe, which takes the textual representation of the protocol buffer and turns it into a binary representation for use with ProtoGen.exe.
|
||||
tools/ProtoGen.exe, which takes binary representations of protocol buffer descriptors (as generated by the "stock" protoc binary supplied by Google) and creates C# source code. This is only required at build time.
|
||||
|
||||
lib/*/Google.ProtocolBuffersLite.dll, which is a supporting library. This is required at execution time.
|
||||
lib/*/Google.ProtocolBuffersLite.Serialization.dll, a supplementary library that provides extensions for reading and writing protocol buffers to xml, json, and others.
|
||||
|
||||
LINKS:
|
||||
|
||||
Project Home - http://code.google.com/p/protobuf-csharp-port
|
||||
Online Help - http://help.protobuffers.net
|
||||
Developer Guide - http://code.google.com/apis/protocolbuffers/docs/overview.html
|
||||
Language Guide - http://code.google.com/apis/protocolbuffers/docs/proto.html
|
||||
|
||||
]]></description>
|
||||
|
||||
<references>
|
||||
<reference file="Google.ProtocolBuffersLite.dll"/>
|
||||
<reference file="Google.ProtocolBuffersLite.Serialization.dll"/>
|
||||
</references>
|
||||
|
||||
</metadata>
|
||||
|
||||
<files>
|
||||
<!-- Release Binaries -->
|
||||
<file src="..\build_output\Release\**\Google.ProtocolBuffersLite.???" target="lib\" />
|
||||
<file src="..\build_output\Release\**\Google.ProtocolBuffersLite.Serialization.???" target="lib\" />
|
||||
<!-- Tools -->
|
||||
<file src="..\build_output\tools\**\*" target="tools\" />
|
||||
<file src="..\build_output\protos\**\*" target="tools\" />
|
||||
<!-- Content -->
|
||||
<file src="..\build_output\CHANGES.txt" target="tools\"/>
|
||||
<file src="..\build_output\license.txt" target="tools\"/>
|
||||
<file src="..\build_output\tools\protoc-license.txt" target="tools\"/>
|
||||
<!-- Source -->
|
||||
<file src="..\src\ProtocolBuffers\**\*.cs" target="src\ProtocolBuffers\"/>
|
||||
<file src="..\src\ProtocolBuffers.Serialization\**\*.cs" target="src\ProtocolBuffers.Serialization\"/>
|
||||
</files>
|
||||
</package>
|
@ -1,2 +0,0 @@
|
||||
@echo off
|
||||
CMD.exe /Q /C "CD %~dp0 && %WINDIR%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /nologo build.csproj /toolsversion:4.0 /t:RunBenchmarks %1 %2 %3 %4
|
@ -1,20 +0,0 @@
|
||||
@echo off
|
||||
SET BUILD_VERSION=%~1
|
||||
SET BUILD_TARGET=%~2
|
||||
SET BUILD_CONFIG=%~3
|
||||
|
||||
IF NOT "%BUILD_VERSION%"=="" GOTO RUN
|
||||
ECHO.
|
||||
ECHO Usage: build.bat platform [target] [config] [msbuild arguments]
|
||||
ECHO.
|
||||
ECHO - platform: CF20, CF35, NET20, NET35, NET40, PL40, SL20, SL30, or SL40
|
||||
ECHO - [target]: Rebuild, Clean, Build, Test, or Publish
|
||||
ECHO - [config]: Debug or Release
|
||||
ECHO.
|
||||
EXIT /B 1
|
||||
|
||||
:RUN
|
||||
IF "%BUILD_TARGET%"=="" SET BUILD_TARGET=Rebuild
|
||||
IF "%BUILD_CONFIG%"=="" SET BUILD_CONFIG=Debug
|
||||
|
||||
CMD.exe /Q /C "CD %~dp0 && %WINDIR%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /nologo target.csproj /toolsversion:4.0 %4 %5 %6 "/t:%BUILD_TARGET%" "/p:Configuration=%BUILD_CONFIG%;TargetVersion=%BUILD_VERSION%"
|
@ -1,241 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- build targets -->
|
||||
<Target Name="Clean" DependsOnTargets="_CleanAll" />
|
||||
<Target Name="BuildTools" DependsOnTargets="_BuildTools" />
|
||||
<Target Name="GenerateProjects" DependsOnTargets="_GenerateProjects" />
|
||||
<Target Name="GenerateSource" DependsOnTargets="_GenerateSource;_CopyGeneratedSource" />
|
||||
<Target Name="RebuildSource" DependsOnTargets="Clean;BuildTools;GenerateSource" />
|
||||
<Target Name="Build" DependsOnTargets="GenerateProjects;BuildTools;GenerateSource;_CompileAll" />
|
||||
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
|
||||
<Target Name="GeneratePackage" DependsOnTargets="_PackageAll;_GeneratePackage" />
|
||||
<Target Name="FullBuild" DependsOnTargets="Rebuild;GeneratePackage" />
|
||||
<!-- misc targets -->
|
||||
<Target Name="RunBenchmarks" DependsOnTargets="_CleanAll;_BuildTools;_RunBenchmarks" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectName>Protocol Buffers</ProjectName>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">Any CPU</Platform>
|
||||
|
||||
<!--Directory Paths-->
|
||||
<ProjectDirectory>$(MSBuildProjectDirectory)\..</ProjectDirectory>
|
||||
<SourceDirectory>$(ProjectDirectory)\src</SourceDirectory>
|
||||
<LibDirectory>$(ProjectDirectory)\lib</LibDirectory>
|
||||
<ProtosDirectory>$(ProjectDirectory)\protos</ProtosDirectory>
|
||||
|
||||
<SourceTempDirectory>$(ProjectDirectory)\build_temp\GeneratedSource</SourceTempDirectory>
|
||||
<BuildTempDirectory>$(ProjectDirectory)\build_temp</BuildTempDirectory>
|
||||
<BuildOutputDirectory>$(ProjectDirectory)\build_output</BuildOutputDirectory>
|
||||
<BuildOutputPackage>$(BuildOutputDirectory)</BuildOutputPackage>
|
||||
|
||||
<BenchmarkArgs>/v2 /fast /formats</BenchmarkArgs>
|
||||
<BenchmarkOutputFile>$(BuildTempDirectory)\..\BenchmarkResults.txt</BenchmarkOutputFile>
|
||||
<BenchmarkProtosDirectory>$(ProjectDirectory)\benchmarks</BenchmarkProtosDirectory>
|
||||
|
||||
<PackageName Condition=" '$(PackageName)' == '' ">$(Configuration)</PackageName>
|
||||
|
||||
<!--Tool Paths-->
|
||||
<ProtocExePath>$(BuildOutputDirectory)\tools\protoc.exe</ProtocExePath>
|
||||
<ProtogenExePath>$(BuildOutputDirectory)\tools\protogen.exe</ProtogenExePath>
|
||||
<NUnitExePath>$(LibDirectory)\NUnit\tools\nunit-console.exe</NUnitExePath>
|
||||
<CsProjectProjector>$(LibDirectory)\CsProjectProjector\CsProjectProjector.exe</CsProjectProjector>
|
||||
<ZipExePath>$(LibDirectory)\7-Zip 9.20\7za.exe</ZipExePath>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Common.targets"/>
|
||||
|
||||
<!-- Proto Files -->
|
||||
<ItemGroup>
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_issues.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_extras.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_extras_full.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_extras_lite.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_extras_xmltest.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_generic_services.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_rpc_interop.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\extest\unittest_rpc_interop_lite.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\descriptor.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\csharp_options.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_csharp_options.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_custom_options.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_embed_optimize_for.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_empty.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_import.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_import_lite.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_lite.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_lite_imports_nonlite.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_mset.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_no_generic_services.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\protobuf\unittest_optimize_for.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\test\google_size.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\google\test\google_speed.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\tutorial\addressbook.proto" />
|
||||
<!-- for benchmark -->
|
||||
<Protos Include="$(ProtosDirectory)\benchmarks\google_size.proto" />
|
||||
<Protos Include="$(ProtosDirectory)\benchmarks\google_speed.proto" />
|
||||
</ItemGroup>
|
||||
<!-- Generated Source -->
|
||||
<ItemGroup>
|
||||
<!-- Main protos -->
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\CSharpOptions.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers\DescriptorProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\DescriptorProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers\DescriptorProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
|
||||
<!-- Address book sample -->
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\AddressBookProtos.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\AddressBook</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<!-- Unit test -->
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestExtrasProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestExtrasIssuesProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestXmlSerializerTestProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestCSharpOptionsProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestCustomOptionsProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestEmbedOptimizeForProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestEmptyProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestImportLiteProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestImportProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestMessageSetProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestNoGenericServicesProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestOptimizeForProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestRpcInterop.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestRpcInteropLite.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestGenericServices.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<!-- Lite unit test -->
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestExtrasFullProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestExtrasLiteProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestImportLiteProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestImportProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestLiteImportNonLiteProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestLiteProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffersLite.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestGoogleSizeProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestGoogleSpeedProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtocolBuffers.Test\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\GoogleSizeProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtoBench\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\GoogleSpeedProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtoBench\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestImportProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtoBench\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
<GeneratedSource Include="$(SourceTempDirectory)\UnitTestProtoFile.cs">
|
||||
<TargetDirectory>$(SourceDirectory)\ProtoBench\TestProtos</TargetDirectory>
|
||||
</GeneratedSource>
|
||||
</ItemGroup>
|
||||
<!-- Package Items -->
|
||||
<ItemGroup>
|
||||
<StaticPackageItem Include="$(ProjectDirectory)\CHANGES.txt" />
|
||||
<StaticPackageItem Include="$(ProjectDirectory)\license.txt" />
|
||||
<StaticPackageItem Include="$(ProjectDirectory)\protos\google\protobuf\descriptor.proto">
|
||||
<TargetDirectory>\protos\google\protobuf</TargetDirectory>
|
||||
</StaticPackageItem>
|
||||
<StaticPackageItem Include="$(ProjectDirectory)\protos\google\protobuf\compiler\plugin.proto">
|
||||
<TargetDirectory>\protos\google\protobuf\compiler</TargetDirectory>
|
||||
</StaticPackageItem>
|
||||
<StaticPackageItem Include="$(ProjectDirectory)\protos\google\protobuf\csharp_options.proto">
|
||||
<TargetDirectory>\protos\google\protobuf</TargetDirectory>
|
||||
</StaticPackageItem>
|
||||
<StaticPackageItem Include="$(ProjectDirectory)\protos\tutorial\addressbook.proto">
|
||||
<TargetDirectory>\protos\tutorial</TargetDirectory>
|
||||
</StaticPackageItem>
|
||||
</ItemGroup>
|
||||
<!-- Tools -->
|
||||
<ItemGroup>
|
||||
<ToolsTestContainer Include="$(SourceDirectory)\ProtoGen.Test\bin\NET35\Release\Google.ProtocolBuffers.ProtoGen.Test.dll" />
|
||||
|
||||
<ToolsOutputItem Include="$(SourceDirectory)\ProtocolBuffers\bin\NET35\Release\Google.ProtocolBuffers.dll" />
|
||||
<ToolsOutputItem Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin\NET35\Release\Google.ProtocolBuffers.Serialization.dll" />
|
||||
<ToolsOutputItem Include="$(SourceDirectory)\ProtoGen\bin\NET35\Release\ProtoGen.exe" />
|
||||
<ToolsOutputItem Include="$(SourceDirectory)\ProtoGen\bin\NET35\Release\ProtoGen.exe.config" />
|
||||
<ToolsOutputItem Include="$(SourceDirectory)\ProtoMunge\bin\NET35\Release\ProtoMunge.exe" />
|
||||
<ToolsOutputItem Include="$(SourceDirectory)\ProtoDump\bin\NET35\Release\ProtoDump.exe" />
|
||||
<ToolsOutputItem Include="$(SourceDirectory)\ProtoBench\bin\NET35\Release\ProtoBench.exe" />
|
||||
<ToolsOutputItem Include="$(LibDirectory)\protoc.exe" />
|
||||
<ToolsOutputItem Include="$(LibDirectory)\protoc-license.txt" />
|
||||
</ItemGroup>
|
||||
<!-- Temporary Directories -->
|
||||
<ItemGroup>
|
||||
<TempBuildFolder Include="$(BuildTempDirectory)" />
|
||||
<TempBuildFolder Include="$(BuildOutputDirectory)" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\AddressBook\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\AddressBook\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoBench\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoBench\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffers\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffers\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffers.Serialization\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffers.Test\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffers.Test\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffersLite.Test\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtocolBuffersLite.Test\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoDump\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoDump\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoGen\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoGen\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoGen.Test\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoGen.Test\bin" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoMunge\obj" />
|
||||
<TempBuildFolder Include="$(SourceDirectory)\ProtoMunge\bin" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,248 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2006, 2007 Google Inc. All Rights Reserved.
|
||||
# Author: danderson@google.com (David Anderson)
|
||||
#
|
||||
# Script for uploading files to a Google Code project.
|
||||
#
|
||||
# This is intended to be both a useful script for people who want to
|
||||
# streamline project uploads and a reference implementation for
|
||||
# uploading files to Google Code projects.
|
||||
#
|
||||
# To upload a file to Google Code, you need to provide a path to the
|
||||
# file on your local machine, a small summary of what the file is, a
|
||||
# project name, and a valid account that is a member or owner of that
|
||||
# project. You can optionally provide a list of labels that apply to
|
||||
# the file. The file will be uploaded under the same name that it has
|
||||
# in your local filesystem (that is, the "basename" or last path
|
||||
# component). Run the script with '--help' to get the exact syntax
|
||||
# and available options.
|
||||
#
|
||||
# Note that the upload script requests that you enter your
|
||||
# googlecode.com password. This is NOT your Gmail account password!
|
||||
# This is the password you use on googlecode.com for committing to
|
||||
# Subversion and uploading files. You can find your password by going
|
||||
# to http://code.google.com/hosting/settings when logged in with your
|
||||
# Gmail account. If you have already committed to your project's
|
||||
# Subversion repository, the script will automatically retrieve your
|
||||
# credentials from there (unless disabled, see the output of '--help'
|
||||
# for details).
|
||||
#
|
||||
# If you are looking at this script as a reference for implementing
|
||||
# your own Google Code file uploader, then you should take a look at
|
||||
# the upload() function, which is the meat of the uploader. You
|
||||
# basically need to build a multipart/form-data POST request with the
|
||||
# right fields and send it to https://PROJECT.googlecode.com/files .
|
||||
# Authenticate the request using HTTP Basic authentication, as is
|
||||
# shown below.
|
||||
#
|
||||
# Licensed under the terms of the Apache Software License 2.0:
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Questions, comments, feature requests and patches are most welcome.
|
||||
# Please direct all of these to the Google Code users group:
|
||||
# http://groups.google.com/group/google-code-hosting
|
||||
|
||||
"""Google Code file uploader script.
|
||||
"""
|
||||
|
||||
__author__ = 'danderson@google.com (David Anderson)'
|
||||
|
||||
import httplib
|
||||
import os.path
|
||||
import optparse
|
||||
import getpass
|
||||
import base64
|
||||
import sys
|
||||
|
||||
|
||||
def upload(file, project_name, user_name, password, summary, labels=None):
|
||||
"""Upload a file to a Google Code project's file server.
|
||||
|
||||
Args:
|
||||
file: The local path to the file.
|
||||
project_name: The name of your project on Google Code.
|
||||
user_name: Your Google account name.
|
||||
password: The googlecode.com password for your account.
|
||||
Note that this is NOT your global Google Account password!
|
||||
summary: A small description for the file.
|
||||
labels: an optional list of label strings with which to tag the file.
|
||||
|
||||
Returns: a tuple:
|
||||
http_status: 201 if the upload succeeded, something else if an
|
||||
error occured.
|
||||
http_reason: The human-readable string associated with http_status
|
||||
file_url: If the upload succeeded, the URL of the file on Google
|
||||
Code, None otherwise.
|
||||
"""
|
||||
# The login is the user part of user@gmail.com. If the login provided
|
||||
# is in the full user@domain form, strip it down.
|
||||
if user_name.endswith('@gmail.com'):
|
||||
user_name = user_name[:user_name.index('@gmail.com')]
|
||||
|
||||
form_fields = [('summary', summary)]
|
||||
if labels is not None:
|
||||
form_fields.extend([('label', l.strip()) for l in labels])
|
||||
|
||||
content_type, body = encode_upload_request(form_fields, file)
|
||||
|
||||
upload_host = '%s.googlecode.com' % project_name
|
||||
upload_uri = '/files'
|
||||
auth_token = base64.b64encode('%s:%s'% (user_name, password))
|
||||
headers = {
|
||||
'Authorization': 'Basic %s' % auth_token,
|
||||
'User-Agent': 'Googlecode.com uploader v0.9.4',
|
||||
'Content-Type': content_type,
|
||||
}
|
||||
|
||||
server = httplib.HTTPSConnection(upload_host)
|
||||
server.request('POST', upload_uri, body, headers)
|
||||
resp = server.getresponse()
|
||||
server.close()
|
||||
|
||||
if resp.status == 201:
|
||||
location = resp.getheader('Location', None)
|
||||
else:
|
||||
location = None
|
||||
return resp.status, resp.reason, location
|
||||
|
||||
|
||||
def encode_upload_request(fields, file_path):
|
||||
"""Encode the given fields and file into a multipart form body.
|
||||
|
||||
fields is a sequence of (name, value) pairs. file is the path of
|
||||
the file to upload. The file will be uploaded to Google Code with
|
||||
the same file name.
|
||||
|
||||
Returns: (content_type, body) ready for httplib.HTTP instance
|
||||
"""
|
||||
BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla'
|
||||
CRLF = '\r\n'
|
||||
|
||||
body = []
|
||||
|
||||
# Add the metadata about the upload first
|
||||
for key, value in fields:
|
||||
body.extend(
|
||||
['--' + BOUNDARY,
|
||||
'Content-Disposition: form-data; name="%s"' % key,
|
||||
'',
|
||||
value,
|
||||
])
|
||||
|
||||
# Now add the file itself
|
||||
file_name = os.path.basename(file_path)
|
||||
f = open(file_path, 'rb')
|
||||
file_content = f.read()
|
||||
f.close()
|
||||
|
||||
body.extend(
|
||||
['--' + BOUNDARY,
|
||||
'Content-Disposition: form-data; name="filename"; filename="%s"'
|
||||
% file_name,
|
||||
# The upload server determines the mime-type, no need to set it.
|
||||
'Content-Type: application/octet-stream',
|
||||
'',
|
||||
file_content,
|
||||
])
|
||||
|
||||
# Finalize the form body
|
||||
body.extend(['--' + BOUNDARY + '--', ''])
|
||||
|
||||
return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body)
|
||||
|
||||
|
||||
def upload_find_auth(file_path, project_name, summary, labels=None,
|
||||
user_name=None, password=None, tries=3):
|
||||
"""Find credentials and upload a file to a Google Code project's file server.
|
||||
|
||||
file_path, project_name, summary, and labels are passed as-is to upload.
|
||||
|
||||
Args:
|
||||
file_path: The local path to the file.
|
||||
project_name: The name of your project on Google Code.
|
||||
summary: A small description for the file.
|
||||
labels: an optional list of label strings with which to tag the file.
|
||||
config_dir: Path to Subversion configuration directory, 'none', or None.
|
||||
user_name: Your Google account name.
|
||||
tries: How many attempts to make.
|
||||
"""
|
||||
|
||||
while tries > 0:
|
||||
if user_name is None:
|
||||
# Read username if not specified or loaded from svn config, or on
|
||||
# subsequent tries.
|
||||
sys.stdout.write('Please enter your googlecode.com username: ')
|
||||
sys.stdout.flush()
|
||||
user_name = sys.stdin.readline().rstrip()
|
||||
if password is None:
|
||||
# Read password if not loaded from svn config, or on subsequent tries.
|
||||
print 'Please enter your googlecode.com password.'
|
||||
print '** Note that this is NOT your Gmail account password! **'
|
||||
print 'It is the password you use to access Subversion repositories,'
|
||||
print 'and can be found here: http://code.google.com/hosting/settings'
|
||||
password = getpass.getpass()
|
||||
|
||||
status, reason, url = upload(file_path, project_name, user_name, password,
|
||||
summary, labels)
|
||||
# Returns 403 Forbidden instead of 401 Unauthorized for bad
|
||||
# credentials as of 2007-07-17.
|
||||
if status in [httplib.FORBIDDEN, httplib.UNAUTHORIZED]:
|
||||
# Rest for another try.
|
||||
user_name = password = None
|
||||
tries = tries - 1
|
||||
else:
|
||||
# We're done.
|
||||
break
|
||||
|
||||
return status, reason, url
|
||||
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser(usage='googlecode-upload.py -s SUMMARY '
|
||||
'-p PROJECT [options] FILE')
|
||||
parser.add_option('-s', '--summary', dest='summary',
|
||||
help='Short description of the file')
|
||||
parser.add_option('-p', '--project', dest='project',
|
||||
help='Google Code project name')
|
||||
parser.add_option('-u', '--user', dest='user',
|
||||
help='Your Google Code username')
|
||||
parser.add_option('-w', '--password', dest='password',
|
||||
help='Your Google Code password')
|
||||
parser.add_option('-l', '--labels', dest='labels',
|
||||
help='An optional list of comma-separated labels to attach '
|
||||
'to the file')
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if not options.summary:
|
||||
parser.error('File summary is missing.')
|
||||
elif not options.project:
|
||||
parser.error('Project name is missing.')
|
||||
elif len(args) < 1:
|
||||
parser.error('File to upload not provided.')
|
||||
elif len(args) > 1:
|
||||
parser.error('Only one file may be specified.')
|
||||
|
||||
file_path = args[0]
|
||||
|
||||
if options.labels:
|
||||
labels = options.labels.split(',')
|
||||
else:
|
||||
labels = None
|
||||
|
||||
status, reason, url = upload_find_auth(file_path, options.project,
|
||||
options.summary, labels,
|
||||
options.user, options.password)
|
||||
if url:
|
||||
print 'The file was uploaded successfully.'
|
||||
print 'URL: %s' % url
|
||||
return 0
|
||||
else:
|
||||
print 'An error occurred. Your file was not uploaded.'
|
||||
print 'Google Code upload server said: %s (%s)' % (reason, status)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- original location: https://hg01.codeplex.com/nuget/raw-file/tip/src/Core/Authoring/nuspec.xsd -->
|
||||
<xs:schema id="nuspec" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="package">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="metadata" maxOccurs="1" minOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="id" maxOccurs="1" minOccurs="1" type="xs:string" />
|
||||
<xs:element name="version" maxOccurs="1" minOccurs="1" type="xs:string" />
|
||||
<xs:element name="title" maxOccurs="1" minOccurs="0" type="xs:string" />
|
||||
<xs:element name="authors" maxOccurs="1" minOccurs="1" type="xs:string" />
|
||||
<xs:element name="owners" maxOccurs="1" minOccurs="0" type="xs:string" />
|
||||
<xs:element name="licenseUrl" maxOccurs="1" minOccurs="0" type="xs:anyURI" />
|
||||
<xs:element name="projectUrl" maxOccurs="1" minOccurs="0" type="xs:anyURI" />
|
||||
<xs:element name="iconUrl" maxOccurs="1" minOccurs="0" type="xs:anyURI" />
|
||||
<xs:element name="requireLicenseAcceptance" maxOccurs="1" minOccurs="0" type="xs:boolean" />
|
||||
<xs:element name="description" maxOccurs="1" minOccurs="1" type="xs:string" />
|
||||
<xs:element name="summary" maxOccurs="1" minOccurs="0" type="xs:string" />
|
||||
<xs:element name="releaseNotes" maxOccurs="1" minOccurs="0" type="xs:string" />
|
||||
<xs:element name="copyright" maxOccurs="1" minOccurs="0" type="xs:string" />
|
||||
<xs:element name="language" maxOccurs="1" minOccurs="0" type="xs:string" default="en-US" />
|
||||
<xs:element name="tags" maxOccurs="1" minOccurs="0" type="xs:string" />
|
||||
<xs:element name="dependencies" maxOccurs="1" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="dependency" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="id" type="xs:string" use="required" />
|
||||
<xs:attribute name="version" type="xs:string" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="frameworkAssemblies" maxOccurs="1" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="frameworkAssembly" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="assemblyName" type="xs:string" use="required" />
|
||||
<xs:attribute name="targetFramework" type="xs:string" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="references" maxOccurs="1" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="reference" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="file" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="files" minOccurs="0" maxOccurs="1" nillable="true">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="file" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="src" use="required" type="xs:string" />
|
||||
<xs:attribute name="target" use="optional" type="xs:string" />
|
||||
<xs:attribute name="exclude" use="optional" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
@ -1,186 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Publish" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- build targets -->
|
||||
<Target Name="Clean" DependsOnTargets="_Clean" />
|
||||
<Target Name="Build" DependsOnTargets="_Clean;_Prerequisites;_StampVersion;_GenerateSource;_Build" />
|
||||
<Target Name="Label" DependsOnTargets="_HgLabel" />
|
||||
<Target Name="Package" DependsOnTargets="_HgPack;_NugetPack" />
|
||||
<Target Name="Prepare" DependsOnTargets="Clean;Build;Label;Package" />
|
||||
<Target Name="PushAll" DependsOnTargets="_HgPush;_NugetPush" />
|
||||
<Target Name="Publish" DependsOnTargets="Prepare;PushAll" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectName>Protocol Buffers</ProjectName>
|
||||
<VersionMajor>2</VersionMajor>
|
||||
<VersionMinor>4</VersionMinor>
|
||||
<VersionBuild>1</VersionBuild>
|
||||
<VersionRevision></VersionRevision>
|
||||
<VersionLabel></VersionLabel>
|
||||
|
||||
<PackagePrefix>protobuf-csharp-port-</PackagePrefix>
|
||||
<PublishDebug>false</PublishDebug>
|
||||
|
||||
<GoogleUsername></GoogleUsername>
|
||||
<GooglePassword></GooglePassword>
|
||||
|
||||
<!--Directory Paths-->
|
||||
<ProjectDirectory>$(MSBuildProjectDirectory)\..</ProjectDirectory>
|
||||
<BuildTempDirectory>$(ProjectDirectory)\build_temp</BuildTempDirectory>
|
||||
<BuildOutputDirectory>$(ProjectDirectory)\build_output</BuildOutputDirectory>
|
||||
<SourceDirectory>$(ProjectDirectory)\src</SourceDirectory>
|
||||
<LibDirectory>$(ProjectDirectory)\lib</LibDirectory>
|
||||
|
||||
<!-- File Paths -->
|
||||
<SigningKey>$(ProjectDirectory)\release-key\Google.ProtocolBuffers.snk</SigningKey>
|
||||
|
||||
<!--Tool Paths-->
|
||||
<HgTool>hg.exe</HgTool>
|
||||
<Python>C:\Python25\python.exe</Python>
|
||||
<SnTool>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)Bin\sn.exe</SnTool>
|
||||
<StampVer>$(LibDirectory)\StampVersion.exe</StampVer>
|
||||
<ZipExePath>$(LibDirectory)\7-Zip 9.20\7za.exe</ZipExePath>
|
||||
<NuGet>$(LibDirectory)\NuGet.exe</NuGet>
|
||||
<ProtogenExePath>$(BuildOutputDirectory)\tools\protogen.exe</ProtogenExePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Import user settings -->
|
||||
<Import Project="$(MSBuildProjectFullPath).user" Condition="Exists('$(MSBuildProjectFullPath).user')" />
|
||||
|
||||
<!-- Files -->
|
||||
<ItemGroup>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Tasks -->
|
||||
|
||||
<Target Name="_Prerequisites" DependsOnTargets="_CheckEnvironment;_ReadVersion" />
|
||||
|
||||
<Target Name="_Clean">
|
||||
<MSBuild Properties="Configuration=Debug;" Targets="Clean" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MSBuild Properties="Configuration=Release;" Targets="Clean" Projects="$(MSBuildProjectDirectory)\target.csproj" />
|
||||
<MakeDir Directories="$(BuildTempDirectory)" />
|
||||
<MakeDir Directories="$(BuildOutputDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_WriteUserConfig">
|
||||
<ItemGroup>
|
||||
<Lines Include="<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>" />
|
||||
<Lines Include=" <PropertyGroup>"/>
|
||||
<Lines Include=" <GoogleUsername> (Enter your google-code user/password here) </GoogleUsername>"/>
|
||||
<Lines Include=" <GooglePassword></GooglePassword>"/>
|
||||
<Lines Include=" </PropertyGroup>" />
|
||||
<Lines Include="</Project>" />
|
||||
</ItemGroup>
|
||||
<WriteLinesToFile File="$(MSBuildProjectFullPath).user" Lines="@(Lines)" Overwrite="true" Condition="!Exists('$(MSBuildProjectFullPath).user')" />
|
||||
<Exec Command="Notepad.exe $(MSBuildProjectFullPath).user" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CheckEnvironment">
|
||||
<!-- Require google credentials -->
|
||||
<CallTarget Targets="_WriteUserConfig" Condition=" '$(GooglePassword)' == '' " />
|
||||
<Error Text="Restart after you verify your credentials in $(MSBuildProjectFullPath).user" Condition=" '$(GooglePassword)' == '' " />
|
||||
<!-- Require Win7.0A SDK to verify strong-name -->
|
||||
<Error Text="Unable to locate Win7SDK Tools: $(SnTool)" Condition="!Exists($(SnTool))" />
|
||||
<!-- Require Python 2.5 installed -->
|
||||
<!-- Error Text="Unable to locate Python 2.5: $(Python)" Condition="!Exists($(Python))" / -->
|
||||
<!-- Require production signing key -->
|
||||
<Exec Command="$(HgTool) clone https://bitbucket.org/rknapp/protobuf-csharp-port-keyfile $(ProjectDirectory)\release-key" Condition="!Exists('$(SigningKey)')" />
|
||||
<Error Text="Unable to locate release signing key: $(SigningKey)" Condition="!Exists($(SigningKey))" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_ReadVersion" Condition=" '$(VersionLabel)' == '' ">
|
||||
<Exec Command="$(HgTool) log -l 1 --template "{rev}" > "$(BuildTempDirectory)\revision.txt""></Exec>
|
||||
<ReadLinesFromFile File="$(BuildTempDirectory)\revision.txt">
|
||||
<Output TaskParameter="Lines" PropertyName="VersionRevision"/>
|
||||
</ReadLinesFromFile>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionLabel>$(VersionMajor).$(VersionMinor).$(VersionBuild).$(VersionRevision)</VersionLabel>
|
||||
</PropertyGroup>
|
||||
|
||||
<Message Text="Building version $(VersionLabel)" Importance="high" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_StampVersion" DependsOnTargets="_Prerequisites">
|
||||
<Exec Command="$(StampVer) /major:$(VersionMajor) /minor:$(VersionMinor) /build:$(VersionBuild) /revision:$(VersionRevision)" WorkingDirectory="$(SourceDirectory)" />
|
||||
<Exec Command="FIND "$(VersionLabel)" ProtocolBuffers\Properties\AssemblyInfo.cs" WorkingDirectory="$(SourceDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_GenerateSource" DependsOnTargets="_Prerequisites">
|
||||
<MSBuild Properties="Configuration=Release;AssemblyOriginatorKeyFile=$(SigningKey)" Targets="GenerateProjects;BuildTools;GenerateSource" Projects="$(MSBuildProjectDirectory)\build.csproj" />
|
||||
<Exec Command=""$(SnTool)" -T "$(ProtogenExePath)" > signkey.txt" WorkingDirectory="$(BuildTempDirectory)" />
|
||||
<!-- Make sure we are signing with the correct key -->
|
||||
<Exec Command="FIND "55f7125234beb589" signkey.txt" WorkingDirectory="$(BuildTempDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_Build" DependsOnTargets="_Prerequisites">
|
||||
<!-- Release Build -->
|
||||
<MSBuild Properties="Configuration=Release;AssemblyOriginatorKeyFile=$(SigningKey)" Targets="_CompileAll" Projects="$(MSBuildProjectDirectory)\build.csproj" />
|
||||
<MSBuild Properties="Configuration=Release;AssemblyOriginatorKeyFile=$(SigningKey);PackageName=$(PackagePrefix)$(VersionLabel)-release" Targets="GeneratePackage" Projects="$(MSBuildProjectDirectory)\build.csproj" />
|
||||
<!-- Debug Build -->
|
||||
<MSBuild Condition=" '$(PublishDebug)' == 'true' " Properties="Configuration=Debug;AssemblyOriginatorKeyFile=$(SigningKey)" Targets="_CompileAll" Projects="$(MSBuildProjectDirectory)\build.csproj" />
|
||||
<MSBuild Condition=" '$(PublishDebug)' == 'true' " Properties="Configuration=Debug;AssemblyOriginatorKeyFile=$(SigningKey);PackageName=$(PackagePrefix)$(VersionLabel)-full" Targets="GeneratePackage" Projects="$(MSBuildProjectDirectory)\build.csproj" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_HgPack" DependsOnTargets="_Prerequisites">
|
||||
<Exec Command="$(HgTool) archive $(BuildTempDirectory)\$(PackagePrefix)$(VersionLabel)-source.zip" WorkingDirectory="$(ProjectDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_HgLabel" DependsOnTargets="_Prerequisites">
|
||||
<Exec Command="$(HgTool) commit -m "version $(VersionLabel)"" WorkingDirectory="$(ProjectDirectory)" />
|
||||
<Exec Command="$(HgTool) tag $(VersionLabel)" WorkingDirectory="$(ProjectDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_HgPush" DependsOnTargets="_Prerequisites">
|
||||
<Exec Command="$(HgTool) push" WorkingDirectory="$(ProjectDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_PkgPush" DependsOnTargets="_Prerequisites">
|
||||
<PropertyGroup>
|
||||
<UploadPackage>$(Python) "$(MSBuildProjectDirectory)\googlecode_upload.py" --project protobuf-csharp-port --user "$(GoogleUsername)" --password "$(GooglePassword)"</UploadPackage>
|
||||
|
||||
<SourcePackage>$(BuildTempDirectory)\$(PackagePrefix)$(VersionLabel)-source.zip</SourcePackage>
|
||||
<ReleasePackageBin>$(BuildTempDirectory)\$(PackagePrefix)$(VersionLabel)-release-binaries.zip</ReleasePackageBin>
|
||||
<ReleasePackageSyb>$(BuildTempDirectory)\$(PackagePrefix)$(VersionLabel)-release-symbols.zip</ReleasePackageSyb>
|
||||
<DebugPackageBin>$(BuildTempDirectory)\$(PackagePrefix)$(VersionLabel)-full-binaries.zip</DebugPackageBin>
|
||||
<DebugPackageSyb>$(BuildTempDirectory)\$(PackagePrefix)$(VersionLabel)-full-symbols.zip</DebugPackageSyb>
|
||||
</PropertyGroup>
|
||||
|
||||
<Error Condition="!Exists('$(SourcePackage)')" Text="File not found: $(SourcePackage)" />
|
||||
<Error Condition="!Exists('$(ReleasePackageBin)')" Text="File not found: $(ReleasePackageBin)" />
|
||||
<Error Condition="!Exists('$(ReleasePackageSyb)')" Text="File not found: $(ReleasePackageSyb)" />
|
||||
<Error Condition="'$(PublishDebug)' == 'true' And !Exists('$(DebugPackageBin)')" Text="File not found: $(DebugPackageBin)" />
|
||||
<Error Condition="'$(PublishDebug)' == 'true' And !Exists('$(DebugPackageSyb)')" Text="File not found: $(DebugPackageSyb)" />
|
||||
|
||||
<Exec WorkingDirectory="$(ProjectDirectory)"
|
||||
Command="$(UploadPackage) --labels Type-Source,Featured --summary "Version $(VersionLabel) source" $(SourcePackage)" />
|
||||
|
||||
<Exec WorkingDirectory="$(ProjectDirectory)"
|
||||
Command="$(UploadPackage) --labels Type-Executable,Featured --summary "Version $(VersionLabel) release binaries only" $(ReleasePackageBin)" />
|
||||
<Exec WorkingDirectory="$(ProjectDirectory)"
|
||||
Command="$(UploadPackage) --labels Type-Executable,Featured --summary "Version $(VersionLabel) release binaries and symbols" $(ReleasePackageSyb)" />
|
||||
|
||||
<Exec WorkingDirectory="$(ProjectDirectory)" Condition=" '$(PublishDebug)' == 'true' "
|
||||
Command="$(UploadPackage) --labels Type-Executable,Featured --summary "Version $(VersionLabel) all binaries" $(DebugPackageBin)" />
|
||||
<Exec WorkingDirectory="$(ProjectDirectory)" Condition=" '$(PublishDebug)' == 'true' "
|
||||
Command="$(UploadPackage) --labels Type-Executable,Featured --summary "Version $(VersionLabel) all binaries and symbols" $(DebugPackageSyb)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_NugetPack" DependsOnTargets="_Prerequisites">
|
||||
<Exec WorkingDirectory="$(MSBuildProjectDirectory)"
|
||||
Command="$(NuGet) update -self" />
|
||||
<Exec WorkingDirectory="$(MSBuildProjectDirectory)"
|
||||
Command="$(NuGet) pack Google.ProtocolBuffers.nuspec -Symbols -Version $(VersionLabel) -NoPackageAnalysis -OutputDirectory $(BuildTempDirectory)" />
|
||||
<Exec WorkingDirectory="$(MSBuildProjectDirectory)"
|
||||
Command="$(NuGet) pack Google.ProtocolBuffersLite.nuspec -Symbols -Version $(VersionLabel) -NoPackageAnalysis -OutputDirectory $(BuildTempDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_NugetPush" DependsOnTargets="_Prerequisites">
|
||||
<Exec WorkingDirectory="$(BuildTempDirectory)" Command="$(NuGet) push Google.ProtocolBuffers.$(VersionLabel).nupkg" ContinueOnError="true" />
|
||||
<Exec WorkingDirectory="$(BuildTempDirectory)" Command="$(NuGet) push Google.ProtocolBuffersLite.$(VersionLabel).nupkg" ContinueOnError="true" />
|
||||
|
||||
<Exec WorkingDirectory="$(BuildTempDirectory)" Command="$(NuGet) push Google.ProtocolBuffers.$(VersionLabel).symbols.nupkg" ContinueOnError="true" />
|
||||
<Exec WorkingDirectory="$(BuildTempDirectory)" Command="$(NuGet) push Google.ProtocolBuffersLite.$(VersionLabel).symbols.nupkg" ContinueOnError="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
@ -1,167 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
High-level Targets
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="Clean" DependsOnTargets="_Clean" />
|
||||
<Target Name="Build" DependsOnTargets="_Compile;_Test" />
|
||||
<Target Name="Test" DependsOnTargets="_Test" />
|
||||
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
|
||||
<Target Name="Publish" DependsOnTargets="Clean;Build;_Publish" />
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Properties
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">Any CPU</Platform>
|
||||
<TargetVersion Condition=" '$(TargetVersion)' == '' ">NET20</TargetVersion>
|
||||
<BuildParams></BuildParams>
|
||||
|
||||
<!--Directory Paths-->
|
||||
<ProjectDirectory>$(MSBuildProjectDirectory)\..</ProjectDirectory>
|
||||
<SourceDirectory>$(ProjectDirectory)\src</SourceDirectory>
|
||||
<LibDirectory>$(ProjectDirectory)\lib</LibDirectory>
|
||||
|
||||
<!--File Paths-->
|
||||
<BuildTempDirectory>$(ProjectDirectory)\build_temp\$(Configuration)\$(TargetVersion)</BuildTempDirectory>
|
||||
<BuildOutputDirectory>$(ProjectDirectory)\build_output\$(Configuration)\$(TargetVersion)</BuildOutputDirectory>
|
||||
<SolutionFile>$(SourceDirectory)\ProtocolBuffersLibrary.$(TargetVersion).sln</SolutionFile>
|
||||
|
||||
<!--Tool Paths-->
|
||||
<NUnitExePath>$(LibDirectory)\NUnit\tools\nunit-console.exe</NUnitExePath>
|
||||
<StatLightExePath>$(LibDirectory)\StatLight\tools\StatLight.exe</StatLightExePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Target Versions
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'NET20' ">
|
||||
<BuildTools>3.5</BuildTools>
|
||||
<TestFramework>NUNIT</TestFramework>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'NET35' ">
|
||||
<BuildTools>3.5</BuildTools>
|
||||
<TestFramework>NUNIT</TestFramework>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'NET40' ">
|
||||
<BuildTools>4.0</BuildTools>
|
||||
<TestFramework>NUNIT</TestFramework>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'CF20' ">
|
||||
<BuildTools>3.5</BuildTools>
|
||||
<TestFramework>NONE</TestFramework>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'CF35' ">
|
||||
<BuildTools>3.5</BuildTools>
|
||||
<TestFramework>NONE</TestFramework>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'SL20' ">
|
||||
<BuildTools>3.5</BuildTools>
|
||||
<TestFramework>SILVERLIGHT</TestFramework>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'SL30' ">
|
||||
<BuildTools>3.5</BuildTools>
|
||||
<TestFramework>SILVERLIGHT</TestFramework>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'SL40' ">
|
||||
<BuildTools>4.0</BuildTools>
|
||||
<TestFramework>SILVERLIGHT</TestFramework>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetVersion)' == 'PL40' ">
|
||||
<BuildTools>4.0</BuildTools>
|
||||
<TestFramework>SILVERLIGHT</TestFramework>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<BuildOutputDirectory>$(ProjectDirectory)\build_output\$(Configuration)\portable-net40+sl4+sl5+wp7+wp8+win8</BuildOutputDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
File Groups
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<ItemGroup>
|
||||
<WorkingDirectories Include="$(BuildTempDirectory)" />
|
||||
<WorkingDirectories Include="$(BuildOutputDirectory)" />
|
||||
|
||||
<TestContainer Include="$(SourceDirectory)\ProtocolBuffers.Test\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.Test.dll" />
|
||||
<TestContainer Include="$(SourceDirectory)\ProtocolBuffersLite.Test\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.Test.dll" />
|
||||
<TestContainer Include="$(SourceDirectory)\ProtocolBuffersLite.Test\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersMixedLite.Test.dll" />
|
||||
|
||||
<StatLightTestContainer Include="$(SourceDirectory)\ProtocolBuffers.Test\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.Test.xap" />
|
||||
<StatLightTestContainer Include="$(SourceDirectory)\ProtocolBuffersLite.Test\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.Test.xap" />
|
||||
<StatLightTestContainer Include="$(SourceDirectory)\ProtocolBuffersLite.Test\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersMixedLite.Test.xap" />
|
||||
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.dll" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.pdb" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.xml" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.dll" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.pdb" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.xml" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.Serialization.dll" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.Serialization.pdb" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffers.Serialization.xml" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.Serialization.dll" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.Serialization.pdb" />
|
||||
<PublishItem Include="$(SourceDirectory)\ProtocolBuffers.Serialization\bin\$(TargetVersion)\$(Configuration)\Google.ProtocolBuffersLite.Serialization.xml" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For Build
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_Configured">
|
||||
<Message Text="Building $(TargetVersion) for configuration $(Configuration), platform $(Platform)" Importance="normal" />
|
||||
<Error Text="Unknown or missing value for TargetVersion=[value]" Condition=" '$(BuildTools)' == '' " />
|
||||
</Target>
|
||||
|
||||
<Target Name="_Clean" DependsOnTargets="_Configured">
|
||||
<RemoveDir Directories="@(WorkingDirectories)" Condition="Exists(%(WorkingDirectories.Identity))" />
|
||||
<MSBuild Targets="Clean" Projects="$(SolutionFile)" ToolsVersion="$(BuildTools)"
|
||||
Properties="Configuration=$(Configuration);Platform=$(Platform);"
|
||||
/>
|
||||
</Target>
|
||||
|
||||
<Target Name="_Compile" DependsOnTargets="_Configured">
|
||||
<MSBuild Targets="Build" Projects="$(SolutionFile)" ToolsVersion="$(BuildTools)"
|
||||
Properties="Configuration=$(Configuration);Platform=$(Platform);$(BuildParams)"
|
||||
/>
|
||||
</Target>
|
||||
|
||||
<Target Name="_Publish" DependsOnTargets="_Configured">
|
||||
<MakeDir Directories="$(BuildOutputDirectory)" />
|
||||
<Copy SourceFiles="@(PublishItem)" DestinationFolder="$(BuildOutputDirectory)" />
|
||||
</Target>
|
||||
|
||||
<!-- **********************************************************************************************
|
||||
Targets For Test
|
||||
*********************************************************************************************** -->
|
||||
|
||||
<Target Name="_Test" DependsOnTargets="_Configured">
|
||||
<MakeDir Directories="$(BuildTempDirectory)" />
|
||||
<CallTarget Targets="_RunNunit" Condition=" '$(TestFramework)'=='NUNIT' " />
|
||||
<CallTarget Targets="_RunStatLight" Condition=" '$(TestFramework)'=='SILVERLIGHT' " />
|
||||
</Target>
|
||||
|
||||
<Target Name="_RunNunit">
|
||||
<Copy SourceFiles="$(LibDirectory)\NUnit-config\nunit-console.$(TargetFrameworkVersion).config" DestinationFiles="$(NUnitExePath).config" />
|
||||
<Exec Command=""$(NUnitExePath)" /nologo /noshadow "%(TestContainer.Identity)" /xml:"$(BuildTempDirectory)\%(TestContainer.Filename).xml"" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_RunStatLight">
|
||||
<Exec
|
||||
Command=""$(StatLightExePath)" -x %(StatLightTestContainer.Identity) --ReportOutputFileType=NUnit --ReportOutputFile=$(BuildTempDirectory)\%(StatLightTestContainer.Filename).xml" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
13
csharp/build_packages.bat
Normal file
13
csharp/build_packages.bat
Normal file
@ -0,0 +1,13 @@
|
||||
@rem Builds Google.Protobuf NuGet packages
|
||||
|
||||
@rem Adjust the location of nuget.exe
|
||||
set NUGET=C:\nuget\nuget.exe
|
||||
|
||||
@rem Build src/Google.Protobuf.sln solution in Release configuration first.
|
||||
%NUGET% pack src\Google.Protobuf\Google.Protobuf.nuspec -Symbols || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo Failed!
|
||||
exit /b %errorlevel%
|
@ -6,17 +6,12 @@ NUNIT_CONSOLE=nunit-console
|
||||
|
||||
# The rest you can leave intact
|
||||
CONFIG=Release
|
||||
KEYFILE=../keys/Google.ProtocolBuffers.snk # TODO(jtattermusch): signing!
|
||||
SRC=$(dirname $0)/src
|
||||
|
||||
set -ex
|
||||
|
||||
echo Building the solution.
|
||||
xbuild /p:Configuration=$CONFIG $SRC/ProtocolBuffers.sln
|
||||
xbuild /p:Configuration=$CONFIG $SRC/Google.Protobuf.sln
|
||||
|
||||
echo Running tests.
|
||||
$NUNIT_CONSOLE $SRC/ProtocolBuffers.Test/bin/$CONFIG/Google.ProtocolBuffers.Test.dll
|
||||
|
||||
$NUNIT_CONSOLE $SRC/ProtocolBuffersLite.Test/bin/$CONFIG/Google.ProtocolBuffersLite.Test.dll
|
||||
|
||||
$NUNIT_CONSOLE $SRC/ProtocolBuffersLite.Test/bin/$CONFIG/Google.ProtocolBuffersMixedLite.Test.dll
|
||||
$NUNIT_CONSOLE $SRC/Google.Protobuf.Test/bin/$CONFIG/Google.Protobuf.Test.dll
|
||||
|
@ -23,10 +23,10 @@ cd $(dirname $0)/..
|
||||
# Windows and Unix.
|
||||
if [ -z "$PROTOC" ]; then
|
||||
# TODO(jonskeet): Use an array and a for loop instead?
|
||||
if [ -x vsprojects/Debug/protoc.exe ]; then
|
||||
PROTOC=vsprojects/Debug/protoc.exe
|
||||
elif [ -x vsprojects/Release/protoc.exe ]; then
|
||||
PROTOC=vsprojects/Release/protoc.exe
|
||||
if [ -x cmake/build/Debug/protoc.exe ]; then
|
||||
PROTOC=cmake/build/Debug/protoc.exe
|
||||
elif [ -x cmake/build/Release/protoc.exe ]; then
|
||||
PROTOC=cmake/build/Release/protoc.exe
|
||||
elif [ -x src/protoc ]; then
|
||||
PROTOC=src/protoc
|
||||
else
|
||||
@ -38,55 +38,32 @@ fi
|
||||
# Descriptor proto
|
||||
# TODO(jonskeet): Remove fixup
|
||||
cp src/google/protobuf/descriptor.proto src/google/protobuf/descriptor_proto_file.proto
|
||||
$PROTOC -Isrc --csharp_out=csharp/src/ProtocolBuffers/DescriptorProtos \
|
||||
$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf/Reflection \
|
||||
src/google/protobuf/descriptor_proto_file.proto
|
||||
rm src/google/protobuf/descriptor_proto_file.proto
|
||||
|
||||
$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf/WellKnownTypes \
|
||||
src/google/protobuf/any.proto \
|
||||
src/google/protobuf/api.proto \
|
||||
src/google/protobuf/duration.proto \
|
||||
src/google/protobuf/empty.proto \
|
||||
src/google/protobuf/field_mask.proto \
|
||||
src/google/protobuf/source_context.proto \
|
||||
src/google/protobuf/struct.proto \
|
||||
src/google/protobuf/timestamp.proto \
|
||||
src/google/protobuf/type.proto \
|
||||
src/google/protobuf/wrappers.proto
|
||||
|
||||
# ProtocolBuffers.Test protos
|
||||
$PROTOC -Isrc --csharp_out=csharp/src/ProtocolBuffers.Test/TestProtos \
|
||||
src/google/protobuf/unittest.proto \
|
||||
src/google/protobuf/unittest_custom_options.proto \
|
||||
src/google/protobuf/unittest_drop_unknown_fields.proto \
|
||||
src/google/protobuf/unittest_enormous_descriptor.proto \
|
||||
src/google/protobuf/unittest_import.proto \
|
||||
src/google/protobuf/unittest_import_public.proto \
|
||||
src/google/protobuf/unittest_mset.proto \
|
||||
src/google/protobuf/unittest_optimize_for.proto \
|
||||
src/google/protobuf/unittest_no_field_presence.proto \
|
||||
src/google/protobuf/unknown_enum_test.proto
|
||||
$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \
|
||||
src/google/protobuf/map_unittest_proto3.proto \
|
||||
src/google/protobuf/unittest_proto3.proto \
|
||||
src/google/protobuf/unittest_import_proto3.proto \
|
||||
src/google/protobuf/unittest_import_public_proto3.proto \
|
||||
src/google/protobuf/unittest_well_known_types.proto
|
||||
|
||||
$PROTOC -Icsharp/protos/extest --csharp_out=csharp/src/ProtocolBuffers.Test/TestProtos \
|
||||
csharp/protos/extest/unittest_extras_xmltest.proto \
|
||||
csharp/protos/extest/unittest_issues.proto
|
||||
|
||||
$PROTOC -Ibenchmarks --csharp_out=csharp/src/ProtocolBuffers.Test/TestProtos \
|
||||
benchmarks/google_size.proto \
|
||||
benchmarks/google_speed.proto
|
||||
|
||||
# ProtocolBuffersLite.Test protos
|
||||
$PROTOC -Isrc --csharp_out=csharp/src/ProtocolBuffersLite.Test/TestProtos \
|
||||
src/google/protobuf/unittest.proto \
|
||||
src/google/protobuf/unittest_import.proto \
|
||||
src/google/protobuf/unittest_import_lite.proto \
|
||||
src/google/protobuf/unittest_import_public.proto \
|
||||
src/google/protobuf/unittest_import_public_lite.proto \
|
||||
src/google/protobuf/unittest_lite.proto \
|
||||
src/google/protobuf/unittest_lite_imports_nonlite.proto
|
||||
|
||||
$PROTOC -Icsharp/protos/extest --csharp_out=csharp/src/ProtocolBuffersLite.Test/TestProtos \
|
||||
csharp/protos/extest/unittest_extras_full.proto \
|
||||
csharp/protos/extest/unittest_extras_lite.proto
|
||||
|
||||
# TODO(jonskeet): Remove fixup; see issue #307
|
||||
sed -i -e 's/RepeatedFieldsGenerator\.Group/RepeatedFieldsGenerator.Types.Group/g' \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs \
|
||||
csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs
|
||||
|
||||
# TODO(jonskeet): Remove fixup
|
||||
sed -i -e 's/DescriptorProtos\.Descriptor\./DescriptorProtos.DescriptorProtoFile./g' \
|
||||
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestCustomOptions.cs
|
||||
$PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \
|
||||
csharp/protos/unittest_issues.proto
|
||||
|
||||
# AddressBook sample protos
|
||||
$PROTOC -Iexamples --csharp_out=csharp/src/AddressBook \
|
||||
|
BIN
csharp/keys/Google.Protobuf.public.snk
Normal file
BIN
csharp/keys/Google.Protobuf.public.snk
Normal file
Binary file not shown.
Binary file not shown.
5
csharp/keys/README.md
Normal file
5
csharp/keys/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
Contents
|
||||
--------
|
||||
|
||||
- Google.Protobuf.public.snk:
|
||||
Public key to verify strong name of Google.Protobuf assemblies.
|
@ -1,13 +0,0 @@
|
||||
@ECHO OFF
|
||||
IF EXIST "C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\sn.exe" GOTO FOUND
|
||||
goto USEPATH
|
||||
|
||||
:FOUND
|
||||
"C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\sn.exe" -k %~dp0\Google.ProtocolBuffers.snk
|
||||
GOTO EXIT
|
||||
|
||||
:USEPATH
|
||||
sn.exe -k %~dp0\Google.ProtocolBuffers.snk
|
||||
GOTO EXIT
|
||||
|
||||
:EXIT
|
@ -1,71 +0,0 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package protobuf_unittest_extra;
|
||||
|
||||
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
|
||||
option optimize_for = CODE_SIZE;
|
||||
option java_package = "com.google.protobuf";
|
||||
|
||||
message TestInteropPerson {
|
||||
required string name = 1;
|
||||
required int32 id = 2;
|
||||
optional string email = 3;
|
||||
repeated int32 codes = 10 [packed=true];
|
||||
|
||||
enum PhoneType {
|
||||
MOBILE = 0;
|
||||
HOME = 1;
|
||||
WORK = 2;
|
||||
}
|
||||
|
||||
message PhoneNumber {
|
||||
required string number = 1;
|
||||
optional PhoneType type = 2 [default = HOME];
|
||||
}
|
||||
|
||||
repeated PhoneNumber phone = 4;
|
||||
|
||||
repeated group Addresses = 5 {
|
||||
required string address = 1;
|
||||
optional string address2 = 2;
|
||||
required string city = 3;
|
||||
required string state = 4;
|
||||
required fixed32 zip = 5;
|
||||
}
|
||||
|
||||
extensions 100 to 199;
|
||||
}
|
||||
|
||||
message TestInteropEmployeeId {
|
||||
required string number = 1;
|
||||
}
|
||||
|
||||
extend TestInteropPerson {
|
||||
// Note: changed from required to optional, as required fields are not
|
||||
// permitted in extensions. (The fact that this was allowed in protogen
|
||||
// before was almost certainly a bug.)
|
||||
optional TestInteropEmployeeId employee_id = 126;
|
||||
}
|
||||
|
||||
message TestMissingFieldsA {
|
||||
required string name = 1;
|
||||
required int32 id = 2;
|
||||
optional string email = 3;
|
||||
|
||||
message SubA {
|
||||
required int32 count = 5;
|
||||
repeated string values = 6;
|
||||
}
|
||||
optional SubA testA = 11;
|
||||
}
|
||||
|
||||
message TestMissingFieldsB {
|
||||
required string name = 1;
|
||||
required int32 id = 2;
|
||||
optional string website = 4;
|
||||
|
||||
message SubB {
|
||||
repeated string values = 7;
|
||||
}
|
||||
optional SubB testB = 12;
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package protobuf_unittest_extra;
|
||||
|
||||
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_package = "com.google.protobuf";
|
||||
|
||||
message TestRequiredLite {
|
||||
required int32 d = 1;
|
||||
required ExtraEnum en = 2 [default = DEFAULT];
|
||||
}
|
||||
|
||||
enum ExtraEnum {
|
||||
DEFAULT = 10;
|
||||
EXLITE_FOO = 7;
|
||||
EXLITE_BAR = 8;
|
||||
EXLITE_BAZ = 9;
|
||||
}
|
||||
|
||||
message TestInteropPersonLite {
|
||||
required string name = 1;
|
||||
required int32 id = 2;
|
||||
optional string email = 3;
|
||||
repeated int32 codes = 10 [packed=true];
|
||||
|
||||
enum PhoneType {
|
||||
MOBILE = 0;
|
||||
HOME = 1;
|
||||
WORK = 2;
|
||||
}
|
||||
|
||||
message PhoneNumber {
|
||||
required string number = 1;
|
||||
optional PhoneType type = 2 [default = HOME];
|
||||
}
|
||||
|
||||
repeated PhoneNumber phone = 4;
|
||||
|
||||
repeated group Addresses = 5 {
|
||||
required string address = 1;
|
||||
optional string address2 = 2;
|
||||
required string city = 3;
|
||||
required string state = 4;
|
||||
required fixed32 zip = 5;
|
||||
}
|
||||
|
||||
extensions 100 to 199;
|
||||
}
|
||||
|
||||
message TestInteropEmployeeIdLite {
|
||||
required string number = 1;
|
||||
}
|
||||
|
||||
extend TestInteropPersonLite {
|
||||
// Note: changed from required to optional, as required fields are not
|
||||
// permitted in extensions. (The fact that this was allowed in protogen
|
||||
// before was almost certainly a bug.)
|
||||
optional TestInteropEmployeeIdLite employee_id_lite = 126;
|
||||
}
|
||||
|
||||
/* Removed from unittest_lite.proto and added back here */
|
||||
|
||||
message TestUnpackedExtensionsLite {
|
||||
extensions 1 to max;
|
||||
}
|
||||
|
||||
message TestUnpackedTypesLite {
|
||||
repeated int32 unpacked_int32 = 90;
|
||||
repeated int64 unpacked_int64 = 91;
|
||||
repeated uint32 unpacked_uint32 = 92;
|
||||
repeated uint64 unpacked_uint64 = 93;
|
||||
repeated sint32 unpacked_sint32 = 94;
|
||||
repeated sint64 unpacked_sint64 = 95;
|
||||
repeated fixed32 unpacked_fixed32 = 96;
|
||||
repeated fixed64 unpacked_fixed64 = 97;
|
||||
repeated sfixed32 unpacked_sfixed32 = 98;
|
||||
repeated sfixed64 unpacked_sfixed64 = 99;
|
||||
repeated float unpacked_float = 100;
|
||||
repeated double unpacked_double = 101;
|
||||
repeated bool unpacked_bool = 102;
|
||||
repeated UnpackedTypesForeignEnumLite unpacked_enum = 103;
|
||||
}
|
||||
|
||||
extend TestUnpackedExtensionsLite {
|
||||
repeated int32 unpacked_int32_extension_lite = 90;
|
||||
repeated int64 unpacked_int64_extension_lite = 91;
|
||||
repeated uint32 unpacked_uint32_extension_lite = 92;
|
||||
repeated uint64 unpacked_uint64_extension_lite = 93;
|
||||
repeated sint32 unpacked_sint32_extension_lite = 94;
|
||||
repeated sint64 unpacked_sint64_extension_lite = 95;
|
||||
repeated fixed32 unpacked_fixed32_extension_lite = 96;
|
||||
repeated fixed64 unpacked_fixed64_extension_lite = 97;
|
||||
repeated sfixed32 unpacked_sfixed32_extension_lite = 98;
|
||||
repeated sfixed64 unpacked_sfixed64_extension_lite = 99;
|
||||
repeated float unpacked_float_extension_lite = 100;
|
||||
repeated double unpacked_double_extension_lite = 101;
|
||||
repeated bool unpacked_bool_extension_lite = 102;
|
||||
repeated UnpackedTypesForeignEnumLite unpacked_enum_extension_lite = 103;
|
||||
}
|
||||
|
||||
enum UnpackedTypesForeignEnumLite {
|
||||
FOREIGN_LITE_FOO = 4;
|
||||
FOREIGN_LITE_BAR = 5;
|
||||
FOREIGN_LITE_BAZ = 6;
|
||||
}
|
||||
|
||||
message BucketOfBytes {
|
||||
optional bytes value = 1;
|
||||
|
||||
}
|
||||
message BucketOfBytesEx {
|
||||
optional bytes value = 1;
|
||||
optional bytes value2 = 255;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
|
||||
|
||||
package protobuf_unittest_extra;
|
||||
|
||||
option optimize_for = SPEED;
|
||||
|
||||
enum EnumOptions {
|
||||
ONE = 0;
|
||||
TWO = 1;
|
||||
THREE = 2;
|
||||
}
|
||||
|
||||
message TestXmlChild {
|
||||
repeated EnumOptions options = 3;
|
||||
optional bytes binary = 4;
|
||||
}
|
||||
|
||||
message TestXmlNoFields {
|
||||
}
|
||||
|
||||
message TestXmlRescursive {
|
||||
optional TestXmlRescursive child = 1;
|
||||
}
|
||||
|
||||
message TestXmlMessage {
|
||||
|
||||
optional int64 number = 6;
|
||||
repeated int32 numbers = 2;
|
||||
optional string text = 3;
|
||||
repeated string textlines = 700;
|
||||
optional bool valid = 5;
|
||||
|
||||
optional TestXmlChild child = 1;
|
||||
repeated group Children = 401 {
|
||||
repeated EnumOptions options = 3;
|
||||
optional bytes binary = 4;
|
||||
}
|
||||
|
||||
extensions 100 to 199;
|
||||
}
|
||||
|
||||
message TestXmlExtension {
|
||||
required int32 number = 1;
|
||||
}
|
||||
|
||||
extend TestXmlMessage {
|
||||
optional EnumOptions extension_enum = 101;
|
||||
optional string extension_text = 102;
|
||||
repeated int32 extension_number = 103 [packed = true];
|
||||
optional TestXmlExtension extension_message = 199;
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
syntax = "proto2";
|
||||
|
||||
// These proto descriptors have at one time been reported as an issue or defect.
|
||||
// They are kept here to replicate the issue, and continue to verify the fix.
|
||||
|
||||
// Issue: Non-"Google.Protobuffers" namespace will ensure that protobuffer library types are qualified
|
||||
option csharp_namespace = "UnitTest.Issues.TestProtos";
|
||||
|
||||
package unittest_issues;
|
||||
option optimize_for = SPEED;
|
||||
|
||||
// The following is a representative set of features
|
||||
/*
|
||||
enum EnumOptions {
|
||||
ONE = 0;
|
||||
TWO = 1;
|
||||
THREE = 2;
|
||||
}
|
||||
|
||||
message TestBasicChild
|
||||
{
|
||||
repeated EnumOptions options = 3;
|
||||
optional bytes binary = 4;
|
||||
}
|
||||
|
||||
message TestBasicNoFields {
|
||||
}
|
||||
|
||||
message TestBasicRescursive {
|
||||
optional TestBasicRescursive child = 1;
|
||||
}
|
||||
|
||||
message TestBasicMessage {
|
||||
|
||||
optional int64 number = 6;
|
||||
repeated int32 numbers = 2;
|
||||
optional string text = 3;
|
||||
repeated string textlines = 700;
|
||||
optional bool valid = 5;
|
||||
|
||||
optional TestBasicChild child = 1;
|
||||
repeated group Children = 401
|
||||
{
|
||||
repeated EnumOptions options = 3;
|
||||
optional bytes binary = 4;
|
||||
}
|
||||
|
||||
extensions 100 to 199;
|
||||
}
|
||||
|
||||
message TestBasicExtension {
|
||||
required int32 number = 1;
|
||||
}
|
||||
|
||||
extend TestBasicMessage {
|
||||
optional EnumOptions extension_enum = 101;
|
||||
optional string extension_text = 102;
|
||||
repeated int32 extension_number = 103 [packed = true];
|
||||
optional TestBasicExtension extension_message = 199;
|
||||
}
|
||||
|
||||
// Issue for non-qualified type reference in new services generation
|
||||
option (google.protobuf.csharp_file_options).service_generator_type = IRPCDISPATCH;
|
||||
|
||||
service TestGenericService {
|
||||
rpc Foo(TestBasicNoFields) returns (TestBasicMessage);
|
||||
rpc Bar(TestBasicNoFields) returns (TestBasicMessage);
|
||||
}
|
||||
*/
|
||||
|
||||
// Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13
|
||||
// New issue 309: https://github.com/google/protobuf/issues/309
|
||||
|
||||
// message A {
|
||||
// optional int32 _A = 1;
|
||||
// }
|
||||
|
||||
// message B {
|
||||
// optional int32 B_ = 1;
|
||||
// }
|
||||
|
||||
//message AB {
|
||||
// optional int32 a_b = 1;
|
||||
//}
|
||||
|
||||
// Similar issue with numeric names
|
||||
// Java code failed too, so probably best for this to be a restriction.
|
||||
// See https://github.com/google/protobuf/issues/308
|
||||
// message NumberField {
|
||||
// optional int32 _01 = 1;
|
||||
// }
|
||||
|
||||
// Issue 28: Circular message dependencies result in null defaults for DefaultInstance
|
||||
|
||||
message MyMessageAReferenceB {
|
||||
required MyMessageBReferenceA value = 1;
|
||||
}
|
||||
|
||||
message MyMessageBReferenceA {
|
||||
required MyMessageAReferenceB value = 1;
|
||||
}
|
||||
|
||||
// issue 19 - negative enum values
|
||||
|
||||
enum NegativeEnum {
|
||||
FiveBelow = -5;
|
||||
MinusOne = -1;
|
||||
Zero = 0;
|
||||
}
|
||||
|
||||
message NegativeEnumMessage {
|
||||
optional NegativeEnum value = 1;
|
||||
repeated NegativeEnum values = 2;
|
||||
repeated NegativeEnum packed_values = 3 [packed=true];
|
||||
}
|
||||
|
||||
// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21
|
||||
// Decorate fields with [deprecated=true] as [System.Obsolete]
|
||||
|
||||
message DeprecatedChild {
|
||||
}
|
||||
|
||||
enum DeprecatedEnum {
|
||||
one = 1;
|
||||
}
|
||||
|
||||
message DeprecatedFieldsMessage {
|
||||
optional int32 PrimitiveValue = 1 [deprecated = true];
|
||||
repeated int32 PrimitiveArray = 2 [deprecated = true];
|
||||
|
||||
optional DeprecatedChild MessageValue = 3 [deprecated = true];
|
||||
repeated DeprecatedChild MessageArray = 4 [deprecated = true];
|
||||
|
||||
optional DeprecatedEnum EnumValue = 5 [deprecated = true];
|
||||
repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
|
||||
}
|
||||
|
||||
// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
|
||||
message ItemField {
|
||||
optional int32 item = 1;
|
||||
}
|
119
csharp/protos/unittest_issues.proto
Normal file
119
csharp/protos/unittest_issues.proto
Normal file
@ -0,0 +1,119 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// These proto descriptors have at one time been reported as an issue or defect.
|
||||
// They are kept here to replicate the issue, and continue to verify the fix.
|
||||
|
||||
// Issue: Non-"Google.Protobuffers" namespace will ensure that protobuffer library types are qualified
|
||||
option csharp_namespace = "UnitTest.Issues.TestProtos";
|
||||
|
||||
package unittest_issues;
|
||||
option optimize_for = SPEED;
|
||||
|
||||
// Issue 307: when generating doubly-nested types, any references
|
||||
// should be of the form A.Types.B.Types.C.
|
||||
message Issue307 {
|
||||
message NestedOnce {
|
||||
message NestedTwice {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13
|
||||
// New issue 309: https://github.com/google/protobuf/issues/309
|
||||
|
||||
// message A {
|
||||
// optional int32 _A = 1;
|
||||
// }
|
||||
|
||||
// message B {
|
||||
// optional int32 B_ = 1;
|
||||
// }
|
||||
|
||||
//message AB {
|
||||
// optional int32 a_b = 1;
|
||||
//}
|
||||
|
||||
// Similar issue with numeric names
|
||||
// Java code failed too, so probably best for this to be a restriction.
|
||||
// See https://github.com/google/protobuf/issues/308
|
||||
// message NumberField {
|
||||
// optional int32 _01 = 1;
|
||||
// }
|
||||
|
||||
// issue 19 - negative enum values
|
||||
|
||||
enum NegativeEnum {
|
||||
NEGATIVE_ENUM_ZERO = 0;
|
||||
FiveBelow = -5;
|
||||
MinusOne = -1;
|
||||
}
|
||||
|
||||
message NegativeEnumMessage {
|
||||
NegativeEnum value = 1;
|
||||
repeated NegativeEnum values = 2 [packed = false];
|
||||
repeated NegativeEnum packed_values = 3 [packed=true];
|
||||
}
|
||||
|
||||
// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21
|
||||
// Decorate fields with [deprecated=true] as [System.Obsolete]
|
||||
|
||||
message DeprecatedChild {
|
||||
}
|
||||
|
||||
enum DeprecatedEnum {
|
||||
DEPRECATED_ZERO = 0;
|
||||
one = 1;
|
||||
}
|
||||
|
||||
message DeprecatedFieldsMessage {
|
||||
int32 PrimitiveValue = 1 [deprecated = true];
|
||||
repeated int32 PrimitiveArray = 2 [deprecated = true];
|
||||
|
||||
DeprecatedChild MessageValue = 3 [deprecated = true];
|
||||
repeated DeprecatedChild MessageArray = 4 [deprecated = true];
|
||||
|
||||
DeprecatedEnum EnumValue = 5 [deprecated = true];
|
||||
repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
|
||||
}
|
||||
|
||||
// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
|
||||
message ItemField {
|
||||
int32 item = 1;
|
||||
}
|
||||
|
||||
message ReservedNames {
|
||||
// Force a nested type called Types
|
||||
message SomeNestedType {
|
||||
}
|
||||
|
||||
int32 types = 1;
|
||||
int32 descriptor = 2;
|
||||
}
|
||||
|
||||
message TestJsonFieldOrdering {
|
||||
// These fields are deliberately not declared in numeric
|
||||
// order, and the oneof fields aren't contiguous either.
|
||||
// This allows for reasonably robust tests of JSON output
|
||||
// ordering.
|
||||
// TestFieldOrderings in unittest_proto3.proto is similar,
|
||||
// but doesn't include oneofs.
|
||||
// TODO: Consider adding oneofs to TestFieldOrderings, although
|
||||
// that will require fixing other tests in multiple platforms.
|
||||
// Alternatively, consider just adding this to
|
||||
// unittest_proto3.proto if multiple platforms want it.
|
||||
|
||||
int32 plain_int32 = 4;
|
||||
|
||||
oneof o1 {
|
||||
string o1_string = 2;
|
||||
int32 o1_int32 = 5;
|
||||
}
|
||||
|
||||
string plain_string = 1;
|
||||
|
||||
oneof o2 {
|
||||
int32 o2_int32 = 6;
|
||||
string o2_string = 3;
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,13 +28,12 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
namespace Google.Protobuf.Examples.AddressBook
|
||||
{
|
||||
internal class AddPerson
|
||||
{
|
||||
@ -46,7 +42,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
/// </summary>
|
||||
private static Person PromptForAddress(TextReader input, TextWriter output)
|
||||
{
|
||||
Person.Builder person = Person.CreateBuilder();
|
||||
Person person = new Person();
|
||||
|
||||
output.Write("Enter person ID: ");
|
||||
person.Id = int.Parse(input.ReadLine());
|
||||
@ -70,8 +66,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
break;
|
||||
}
|
||||
|
||||
Person.Types.PhoneNumber.Builder phoneNumber =
|
||||
Person.Types.PhoneNumber.CreateBuilder().SetNumber(number);
|
||||
Person.Types.PhoneNumber phoneNumber = new Person.Types.PhoneNumber { Number = number };
|
||||
|
||||
output.Write("Is this a mobile, home, or work phone? ");
|
||||
String type = input.ReadLine();
|
||||
@ -91,9 +86,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
break;
|
||||
}
|
||||
|
||||
person.AddPhone(phoneNumber);
|
||||
person.Phones.Add(phoneNumber);
|
||||
}
|
||||
return person.Build();
|
||||
return person;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -108,27 +103,28 @@ namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
return -1;
|
||||
}
|
||||
|
||||
AddressBook.Builder addressBook = AddressBook.CreateBuilder();
|
||||
AddressBook addressBook;
|
||||
|
||||
if (File.Exists(args[0]))
|
||||
{
|
||||
using (Stream file = File.OpenRead(args[0]))
|
||||
{
|
||||
addressBook.MergeFrom(file);
|
||||
addressBook = AddressBook.Parser.ParseFrom(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("{0}: File not found. Creating a new file.", args[0]);
|
||||
addressBook = new AddressBook();
|
||||
}
|
||||
|
||||
// Add an address.
|
||||
addressBook.AddPerson(PromptForAddress(Console.In, Console.Out));
|
||||
addressBook.People.Add(PromptForAddress(Console.In, Console.Out));
|
||||
|
||||
// Write the new address book back to disk.
|
||||
using (Stream output = File.OpenWrite(args[0]))
|
||||
{
|
||||
addressBook.Build().WriteTo(output);
|
||||
addressBook.WriteTo(output);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,12 +8,13 @@
|
||||
<ProjectGuid>{A31F5FB2-4FF3-432A-B35B-5CD203606311}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.ProtocolBuffers.Examples.AddressBook</RootNamespace>
|
||||
<RootNamespace>Google.Protobuf.Examples.AddressBook</RootNamespace>
|
||||
<AssemblyName>AddressBook</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<StartupObject>Google.ProtocolBuffers.Examples.AddressBook.Program</StartupObject>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<StartupObject>Google.Protobuf.Examples.AddressBook.Program</StartupObject>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -26,6 +27,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@ -37,6 +39,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
@ -53,9 +56,9 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">
|
||||
<ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
|
||||
<Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
|
||||
<Name>ProtocolBuffers</Name>
|
||||
<Name>Google.Protobuf</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,13 +28,12 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
namespace Google.Protobuf.Examples.AddressBook
|
||||
{
|
||||
internal class ListPeople
|
||||
{
|
||||
@ -46,16 +42,16 @@ namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
/// </summary>
|
||||
private static void Print(AddressBook addressBook)
|
||||
{
|
||||
foreach (Person person in addressBook.PersonList)
|
||||
foreach (Person person in addressBook.People)
|
||||
{
|
||||
Console.WriteLine("Person ID: {0}", person.Id);
|
||||
Console.WriteLine(" Name: {0}", person.Name);
|
||||
if (person.HasEmail)
|
||||
if (person.Email != "")
|
||||
{
|
||||
Console.WriteLine(" E-mail address: {0}", person.Email);
|
||||
}
|
||||
|
||||
foreach (Person.Types.PhoneNumber phoneNumber in person.PhoneList)
|
||||
foreach (Person.Types.PhoneNumber phoneNumber in person.Phones)
|
||||
{
|
||||
switch (phoneNumber.Type)
|
||||
{
|
||||
@ -94,7 +90,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
// Read the existing address book.
|
||||
using (Stream stream = File.OpenRead(args[0]))
|
||||
{
|
||||
AddressBook addressBook = AddressBook.ParseFrom(stream);
|
||||
AddressBook addressBook = AddressBook.Parser.ParseFrom(stream);
|
||||
Print(addressBook);
|
||||
}
|
||||
return 0;
|
||||
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,12 +28,11 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
namespace Google.Protobuf.Examples.AddressBook
|
||||
{
|
||||
/// <summary>
|
||||
/// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour
|
||||
|
@ -10,20 +10,9 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AddressBook")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2008")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 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("2.4.1.555")]
|
||||
|
||||
[assembly: AssemblyVersion("2.4.1.555")]
|
||||
[assembly: AssemblyFileVersion("2.4.1.555")]
|
||||
[assembly: AssemblyVersion("3.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("3.0.0.0")]
|
||||
|
@ -1,44 +1,70 @@
|
||||
using System;
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers.Examples.AddressBook
|
||||
namespace Google.Protobuf.Examples.AddressBook
|
||||
{
|
||||
internal class SampleUsage
|
||||
{
|
||||
private static void Main()
|
||||
{
|
||||
byte[] bytes;
|
||||
//Create a builder to start building a message
|
||||
Person.Builder newContact = Person.CreateBuilder();
|
||||
//Set the primitive properties
|
||||
newContact.SetId(1)
|
||||
.SetName("Foo")
|
||||
.SetEmail("foo@bar");
|
||||
//Now add an item to a list (repeating) field
|
||||
newContact.AddPhone(
|
||||
//Create the child message inline
|
||||
Person.Types.PhoneNumber.CreateBuilder().SetNumber("555-1212").Build()
|
||||
);
|
||||
//Now build the final message:
|
||||
Person person = newContact.Build();
|
||||
//The builder is no longer valid (at least not now, scheduled for 2.4):
|
||||
newContact = null;
|
||||
// Create a new person
|
||||
Person person = new Person
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Foo",
|
||||
Email = "foo@bar",
|
||||
Phones = { new Person.Types.PhoneNumber { Number = "555-1212" } }
|
||||
};
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
//Save the person to a stream
|
||||
// Save the person to a stream
|
||||
person.WriteTo(stream);
|
||||
bytes = stream.ToArray();
|
||||
}
|
||||
//Create another builder, merge the byte[], and build the message:
|
||||
Person copy = Person.CreateBuilder().MergeFrom(bytes).Build();
|
||||
Person copy = Person.Parser.ParseFrom(bytes);
|
||||
|
||||
//A more streamlined approach might look like this:
|
||||
bytes = AddressBook.CreateBuilder().AddPerson(copy).Build().ToByteArray();
|
||||
//And read the address book back again
|
||||
AddressBook restored = AddressBook.CreateBuilder().MergeFrom(bytes).Build();
|
||||
//The message performs a deep-comparison on equality:
|
||||
if (restored.PersonCount != 1 || !person.Equals(restored.PersonList[0]))
|
||||
// A more streamlined approach might look like this:
|
||||
bytes = copy.ToByteArray();
|
||||
// And read the address book back again
|
||||
AddressBook restored = AddressBook.Parser.ParseFrom(bytes);
|
||||
// The message performs a deep-comparison on equality:
|
||||
if (restored.People.Count != 1 || !person.Equals(restored.People[0]))
|
||||
{
|
||||
throw new ApplicationException("There is a bad person in here!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<EnvironmentFlavor>CLIENTPROFILE</EnvironmentFlavor>
|
||||
<EnvironmentTemplate>NET35</EnvironmentTemplate>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
@ -10,11 +8,12 @@
|
||||
<ProjectGuid>{D7282E99-2DC3-405B-946F-177DB2FD2AE2}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.ProtocolBuffers.ProtoDump</RootNamespace>
|
||||
<AssemblyName>ProtoDump</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<RootNamespace>Google.Protobuf.JsonDump</RootNamespace>
|
||||
<AssemblyName>Google.Protobuf.JsonDump</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -27,6 +26,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@ -38,6 +38,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
@ -48,9 +49,9 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">
|
||||
<ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
|
||||
<Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
|
||||
<Name>ProtocolBuffers</Name>
|
||||
<Name>Google.Protobuf</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,16 +28,15 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers.ProtoDump
|
||||
namespace Google.Protobuf.ProtoDump
|
||||
{
|
||||
/// <summary>
|
||||
/// Small utility to load a binary message and dump it in text form
|
||||
/// Small utility to load a binary message and dump it in JSON format.
|
||||
/// </summary>
|
||||
internal class Program
|
||||
{
|
||||
@ -48,41 +44,29 @@ namespace Google.ProtocolBuffers.ProtoDump
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
Console.Error.WriteLine("Usage: ProtoDump <descriptor type name> <input data>");
|
||||
Console.Error.WriteLine("Usage: Google.Protobuf.JsonDump <descriptor type name> <input data>");
|
||||
Console.Error.WriteLine("The descriptor type name is the fully-qualified message name,");
|
||||
Console.Error.WriteLine("including assembly e.g. ProjectNamespace.Message,Company.Project");
|
||||
return 1;
|
||||
}
|
||||
IMessage defaultMessage;
|
||||
try
|
||||
Type type = Type.GetType(args[0]);
|
||||
if (type == null)
|
||||
{
|
||||
defaultMessage = MessageUtil.GetDefaultMessage(args[0]);
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
Console.Error.WriteLine(e.Message);
|
||||
Console.Error.WriteLine("Unable to load type {0}.", args[0]);
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
if (!typeof(IMessage).IsAssignableFrom(type))
|
||||
{
|
||||
IBuilder builder = defaultMessage.WeakCreateBuilderForType();
|
||||
if (builder == null)
|
||||
{
|
||||
Console.Error.WriteLine("Unable to create builder");
|
||||
return 1;
|
||||
}
|
||||
byte[] inputData = File.ReadAllBytes(args[1]);
|
||||
builder.WeakMergeFrom(ByteString.CopyFrom(inputData));
|
||||
Console.WriteLine(TextFormat.PrintToString(builder.WeakBuild()));
|
||||
return 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine("Error: {0}", e.Message);
|
||||
Console.Error.WriteLine();
|
||||
Console.Error.WriteLine("Detailed exception information: {0}", e);
|
||||
Console.Error.WriteLine("Type {0} doesn't implement IMessage.", args[0]);
|
||||
return 1;
|
||||
}
|
||||
IMessage message = (IMessage) Activator.CreateInstance(type);
|
||||
using (var input = File.OpenRead(args[1]))
|
||||
{
|
||||
message.MergeFrom(input);
|
||||
}
|
||||
Console.WriteLine(message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,20 +11,9 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ProtoDump")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2009")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 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("2.4.1.555")]
|
||||
|
||||
[assembly: AssemblyVersion("2.4.1.555")]
|
||||
[assembly: AssemblyFileVersion("2.4.1.555")]
|
||||
[assembly: AssemblyVersion("3.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("3.0.0.0")]
|
@ -1,3 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,17 +28,44 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
public class ByteStringTest
|
||||
{
|
||||
[Test]
|
||||
public void Equality()
|
||||
{
|
||||
ByteString b1 = ByteString.CopyFrom(1, 2, 3);
|
||||
ByteString b2 = ByteString.CopyFrom(1, 2, 3);
|
||||
ByteString b3 = ByteString.CopyFrom(1, 2, 4);
|
||||
ByteString b4 = ByteString.CopyFrom(1, 2, 3, 4);
|
||||
EqualityTester.AssertEquality(b1, b1);
|
||||
EqualityTester.AssertEquality(b1, b2);
|
||||
EqualityTester.AssertInequality(b1, b3);
|
||||
EqualityTester.AssertInequality(b1, b4);
|
||||
EqualityTester.AssertInequality(b1, null);
|
||||
#pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1)
|
||||
Assert.IsTrue(b1 == b1);
|
||||
Assert.IsTrue(b1 == b2);
|
||||
Assert.IsFalse(b1 == b3);
|
||||
Assert.IsFalse(b1 == b4);
|
||||
Assert.IsFalse(b1 == null);
|
||||
Assert.IsTrue((ByteString) null == null);
|
||||
Assert.IsFalse(b1 != b1);
|
||||
Assert.IsFalse(b1 != b2);
|
||||
#pragma warning disable 1718
|
||||
Assert.IsTrue(b1 != b3);
|
||||
Assert.IsTrue(b1 != b4);
|
||||
Assert.IsTrue(b1 != null);
|
||||
Assert.IsFalse((ByteString) null != null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyByteStringHasZeroSize()
|
||||
{
|
@ -0,0 +1,54 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
internal static class CodedInputStreamExtensions
|
||||
{
|
||||
public static void AssertNextTag(this CodedInputStream input, uint expectedTag)
|
||||
{
|
||||
uint tag;
|
||||
Assert.IsTrue(input.ReadTag(out tag));
|
||||
Assert.AreEqual(expectedTag, tag);
|
||||
}
|
||||
|
||||
public static T ReadMessage<T>(this CodedInputStream stream, MessageParser<T> parser)
|
||||
where T : IMessage<T>
|
||||
{
|
||||
var message = parser.CreateTemplate();
|
||||
stream.ReadMessage(message);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,17 +28,14 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Google.ProtocolBuffers.Descriptors;
|
||||
using Google.ProtocolBuffers.TestProtos;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
public class CodedInputStreamTest
|
||||
{
|
||||
@ -61,24 +55,24 @@ namespace Google.ProtocolBuffers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
|
||||
/// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64()
|
||||
/// </summary>
|
||||
private static void AssertReadVarint(byte[] data, ulong value)
|
||||
{
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(data);
|
||||
CodedInputStream input = new CodedInputStream(data);
|
||||
Assert.AreEqual((uint) value, input.ReadRawVarint32());
|
||||
|
||||
input = CodedInputStream.CreateInstance(data);
|
||||
input = new CodedInputStream(data);
|
||||
Assert.AreEqual(value, input.ReadRawVarint64());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
|
||||
// Try different block sizes.
|
||||
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
|
||||
{
|
||||
input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
|
||||
input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
|
||||
Assert.AreEqual((uint) value, input.ReadRawVarint32());
|
||||
|
||||
input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
|
||||
input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
|
||||
Assert.AreEqual(value, input.ReadRawVarint64());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
@ -101,11 +95,11 @@ namespace Google.ProtocolBuffers
|
||||
/// </summary>
|
||||
private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
|
||||
{
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(data);
|
||||
CodedInputStream input = new CodedInputStream(data);
|
||||
var exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint32());
|
||||
Assert.AreEqual(expected.Message, exception.Message);
|
||||
|
||||
input = CodedInputStream.CreateInstance(data);
|
||||
input = new CodedInputStream(data);
|
||||
exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64());
|
||||
Assert.AreEqual(expected.Message, exception.Message);
|
||||
|
||||
@ -158,14 +152,14 @@ namespace Google.ProtocolBuffers
|
||||
/// </summary>
|
||||
private static void AssertReadLittleEndian32(byte[] data, uint value)
|
||||
{
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(data);
|
||||
CodedInputStream input = new CodedInputStream(data);
|
||||
Assert.AreEqual(value, input.ReadRawLittleEndian32());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
|
||||
// Try different block sizes.
|
||||
for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
|
||||
{
|
||||
input = CodedInputStream.CreateInstance(
|
||||
input = new CodedInputStream(
|
||||
new SmallBlockInputStream(data, blockSize));
|
||||
Assert.AreEqual(value, input.ReadRawLittleEndian32());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
@ -178,14 +172,14 @@ namespace Google.ProtocolBuffers
|
||||
/// </summary>
|
||||
private static void AssertReadLittleEndian64(byte[] data, ulong value)
|
||||
{
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(data);
|
||||
CodedInputStream input = new CodedInputStream(data);
|
||||
Assert.AreEqual(value, input.ReadRawLittleEndian64());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
|
||||
// Try different block sizes.
|
||||
for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
|
||||
{
|
||||
input = CodedInputStream.CreateInstance(
|
||||
input = new CodedInputStream(
|
||||
new SmallBlockInputStream(data, blockSize));
|
||||
Assert.AreEqual(value, input.ReadRawLittleEndian64());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
@ -231,66 +225,26 @@ namespace Google.ProtocolBuffers
|
||||
Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
|
||||
Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ReadWholeMessage()
|
||||
public void ReadWholeMessage_VaryingBlockSizes()
|
||||
{
|
||||
TestAllTypes message = TestUtil.GetAllSet();
|
||||
TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
|
||||
|
||||
byte[] rawBytes = message.ToByteArray();
|
||||
Assert.AreEqual(rawBytes.Length, message.SerializedSize);
|
||||
TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
|
||||
TestUtil.AssertAllFieldsSet(message2);
|
||||
Assert.AreEqual(rawBytes.Length, message.CalculateSize());
|
||||
TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes);
|
||||
Assert.AreEqual(message, message2);
|
||||
|
||||
// Try different block sizes.
|
||||
for (int blockSize = 1; blockSize < 256; blockSize *= 2)
|
||||
{
|
||||
message2 = TestAllTypes.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
|
||||
TestUtil.AssertAllFieldsSet(message2);
|
||||
message2 = TestAllTypes.Parser.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
|
||||
Assert.AreEqual(message, 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();
|
||||
|
||||
uint tag;
|
||||
string name;
|
||||
while (input1.ReadTag(out tag, out name))
|
||||
{
|
||||
uint tag2;
|
||||
Assert.IsTrue(input2.ReadTag(out tag2, out name));
|
||||
Assert.AreEqual(tag, tag2);
|
||||
|
||||
unknownFields.MergeFieldFrom(tag, input1);
|
||||
input2.SkipField();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that a bug in SkipRawBytes has been fixed: if the skip
|
||||
/// skips exactly up to a limit, this should bnot break things
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SkipRawBytesBug()
|
||||
{
|
||||
byte[] rawBytes = new byte[] {1, 2};
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(rawBytes);
|
||||
|
||||
int limit = input.PushLimit(1);
|
||||
input.SkipRawBytes(1);
|
||||
input.PopLimit(limit);
|
||||
Assert.AreEqual(2, input.ReadRawByte());
|
||||
}
|
||||
|
||||
public void ReadHugeBlob()
|
||||
{
|
||||
// Allocate and initialize a 1MB blob.
|
||||
@ -301,30 +255,21 @@ namespace Google.ProtocolBuffers
|
||||
}
|
||||
|
||||
// Make a message containing it.
|
||||
TestAllTypes.Builder builder = TestAllTypes.CreateBuilder();
|
||||
TestUtil.SetAllFields(builder);
|
||||
builder.SetOptionalBytes(ByteString.CopyFrom(blob));
|
||||
TestAllTypes message = builder.Build();
|
||||
var message = new TestAllTypes { SingleBytes = ByteString.CopyFrom(blob) };
|
||||
|
||||
// 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());
|
||||
TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(message.ToByteString());
|
||||
|
||||
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);
|
||||
Assert.AreEqual(message, message2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadMaliciouslyLargeBlob()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
|
||||
CodedOutputStream output = new CodedOutputStream(ms);
|
||||
|
||||
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteRawVarint32(tag);
|
||||
@ -333,27 +278,24 @@ namespace Google.ProtocolBuffers
|
||||
output.Flush();
|
||||
ms.Position = 0;
|
||||
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(ms);
|
||||
CodedInputStream input = new CodedInputStream(ms);
|
||||
uint testtag;
|
||||
string ignore;
|
||||
Assert.IsTrue(input.ReadTag(out testtag, out ignore));
|
||||
Assert.IsTrue(input.ReadTag(out testtag));
|
||||
Assert.AreEqual(tag, testtag);
|
||||
|
||||
ByteString bytes = null;
|
||||
// TODO(jonskeet): Should this be ArgumentNullException instead?
|
||||
Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes(ref bytes));
|
||||
Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());
|
||||
}
|
||||
|
||||
private static TestRecursiveMessage MakeRecursiveMessage(int depth)
|
||||
{
|
||||
if (depth == 0)
|
||||
{
|
||||
return TestRecursiveMessage.CreateBuilder().SetI(5).Build();
|
||||
return new TestRecursiveMessage { I = 5 };
|
||||
}
|
||||
else
|
||||
{
|
||||
return TestRecursiveMessage.CreateBuilder()
|
||||
.SetA(MakeRecursiveMessage(depth - 1)).Build();
|
||||
return new TestRecursiveMessage { A = MakeRecursiveMessage(depth - 1) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,12 +303,12 @@ namespace Google.ProtocolBuffers
|
||||
{
|
||||
if (depth == 0)
|
||||
{
|
||||
Assert.IsFalse(message.HasA);
|
||||
Assert.IsNull(message.A);
|
||||
Assert.AreEqual(5, message.I);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(message.HasA);
|
||||
Assert.IsNotNull(message.A);
|
||||
AssertMessageDepth(message.A, depth - 1);
|
||||
}
|
||||
}
|
||||
@ -377,31 +319,32 @@ namespace Google.ProtocolBuffers
|
||||
ByteString data64 = MakeRecursiveMessage(64).ToByteString();
|
||||
ByteString data65 = MakeRecursiveMessage(65).ToByteString();
|
||||
|
||||
AssertMessageDepth(TestRecursiveMessage.ParseFrom(data64), 64);
|
||||
AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64);
|
||||
|
||||
Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.ParseFrom(data65));
|
||||
Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(data65));
|
||||
|
||||
CodedInputStream input = data64.CreateCodedInput();
|
||||
input.SetRecursionLimit(8);
|
||||
Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.ParseFrom(input));
|
||||
Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(input));
|
||||
}
|
||||
|
||||
/*
|
||||
[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);
|
||||
CodedInputStream input = new CodedInputStream(ms);
|
||||
input.SetSizeLimit(16);
|
||||
|
||||
Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.ParseFrom(input));
|
||||
}
|
||||
}*/
|
||||
|
||||
[Test]
|
||||
public void ResetSizeCounter()
|
||||
{
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(
|
||||
CodedInputStream input = new CodedInputStream(
|
||||
new SmallBlockInputStream(new byte[256], 8));
|
||||
input.SetSizeLimit(16);
|
||||
input.ReadRawBytes(16);
|
||||
@ -423,7 +366,7 @@ namespace Google.ProtocolBuffers
|
||||
public void ReadInvalidUtf8()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
|
||||
CodedOutputStream output = new CodedOutputStream(ms);
|
||||
|
||||
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteRawVarint32(tag);
|
||||
@ -432,15 +375,12 @@ namespace Google.ProtocolBuffers
|
||||
output.Flush();
|
||||
ms.Position = 0;
|
||||
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(ms);
|
||||
CodedInputStream input = new CodedInputStream(ms);
|
||||
|
||||
uint testtag;
|
||||
string ignored;
|
||||
|
||||
Assert.IsTrue(input.ReadTag(out testtag, out ignored));
|
||||
Assert.AreEqual(tag, testtag);
|
||||
string text = null;
|
||||
input.ReadString(ref text);
|
||||
uint actualTag;
|
||||
Assert.IsTrue(input.ReadTag(out actualTag));
|
||||
Assert.AreEqual(tag, actualTag);
|
||||
string text = input.ReadString();
|
||||
Assert.AreEqual('\ufffd', text[0]);
|
||||
}
|
||||
|
||||
@ -465,75 +405,13 @@ namespace Google.ProtocolBuffers
|
||||
}
|
||||
}
|
||||
|
||||
enum TestNegEnum { None = 0, Value = -2 }
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnum()
|
||||
{
|
||||
byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
|
||||
object unk;
|
||||
TestNegEnum val = TestNegEnum.None;
|
||||
|
||||
Assert.IsTrue(input.ReadEnum(ref val, out unk));
|
||||
byte[] bytes = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
|
||||
CodedInputStream input = new CodedInputStream(bytes);
|
||||
Assert.AreEqual((int)SampleEnum.NegativeValue, input.ReadEnum());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
Assert.AreEqual(TestNegEnum.Value, val);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnumPackedArray()
|
||||
{
|
||||
int arraySize = 1 + (10 * 5);
|
||||
int msgSize = 1 + 1 + arraySize;
|
||||
byte[] bytes = new byte[msgSize];
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
|
||||
output.WritePackedInt32Array(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 });
|
||||
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
|
||||
uint tag;
|
||||
string name;
|
||||
Assert.IsTrue(input.ReadTag(out tag, out name));
|
||||
|
||||
List<TestNegEnum> values = new List<TestNegEnum>();
|
||||
ICollection<object> unk;
|
||||
input.ReadEnumArray(tag, name, values, out unk);
|
||||
|
||||
Assert.AreEqual(2, values.Count);
|
||||
Assert.AreEqual(TestNegEnum.None, values[0]);
|
||||
Assert.AreEqual(TestNegEnum.Value, values[1]);
|
||||
|
||||
Assert.NotNull(unk);
|
||||
Assert.AreEqual(4, unk.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnumArray()
|
||||
{
|
||||
int arraySize = 1 + 1 + (11 * 5);
|
||||
int msgSize = arraySize;
|
||||
byte[] bytes = new byte[msgSize];
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
|
||||
output.WriteInt32Array(8, "", new int[] { 0, -1, -2, -3, -4, -5 });
|
||||
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
|
||||
uint tag;
|
||||
string name;
|
||||
Assert.IsTrue(input.ReadTag(out tag, out name));
|
||||
|
||||
List<TestNegEnum> values = new List<TestNegEnum>();
|
||||
ICollection<object> unk;
|
||||
input.ReadEnumArray(tag, name, values, out unk);
|
||||
|
||||
Assert.AreEqual(2, values.Count);
|
||||
Assert.AreEqual(TestNegEnum.None, values[0]);
|
||||
Assert.AreEqual(TestNegEnum.Value, values[1]);
|
||||
|
||||
Assert.NotNull(unk);
|
||||
Assert.AreEqual(4, unk.Count);
|
||||
}
|
||||
|
||||
//Issue 71: CodedInputStream.ReadBytes go to slow path unnecessarily
|
||||
@ -542,27 +420,24 @@ namespace Google.ProtocolBuffers
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
|
||||
output.WriteField(FieldType.Bytes, 1, "bytes", ByteString.CopyFrom(new byte[100]));
|
||||
output.WriteField(FieldType.Bytes, 2, "bytes", ByteString.CopyFrom(new byte[100]));
|
||||
CodedOutputStream output = new CodedOutputStream(ms);
|
||||
output.WriteTag(1, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteBytes(ByteString.CopyFrom(new byte[100]));
|
||||
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteBytes(ByteString.CopyFrom(new byte[100]));
|
||||
output.Flush();
|
||||
|
||||
ms.Position = 0;
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(ms, new byte[ms.Length / 2]);
|
||||
CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2]);
|
||||
|
||||
uint tag;
|
||||
string ignore;
|
||||
ByteString value;
|
||||
|
||||
Assert.IsTrue(input.ReadTag(out tag, out ignore));
|
||||
Assert.IsTrue(input.ReadTag(out tag));
|
||||
Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));
|
||||
value = ByteString.Empty;
|
||||
Assert.IsTrue(input.ReadBytes(ref value) && value.Length == 100);
|
||||
Assert.AreEqual(100, input.ReadBytes().Length);
|
||||
|
||||
Assert.IsTrue(input.ReadTag(out tag, out ignore));
|
||||
Assert.IsTrue(input.ReadTag(out tag));
|
||||
Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag));
|
||||
value = ByteString.Empty;
|
||||
Assert.IsTrue(input.ReadBytes(ref value) && value.Length == 100);
|
||||
Assert.AreEqual(100, input.ReadBytes().Length);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,16 +28,14 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Google.ProtocolBuffers.TestProtos;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
public class CodedOutputStreamTest
|
||||
{
|
||||
@ -54,7 +49,7 @@ namespace Google.ProtocolBuffers
|
||||
if ((value >> 32) == 0)
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
CodedOutputStream output = new CodedOutputStream(rawOutput);
|
||||
output.WriteRawVarint32((uint) value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -64,7 +59,7 @@ namespace Google.ProtocolBuffers
|
||||
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
CodedOutputStream output = new CodedOutputStream(rawOutput);
|
||||
output.WriteRawVarint64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -81,7 +76,7 @@ namespace Google.ProtocolBuffers
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output =
|
||||
CodedOutputStream.CreateInstance(rawOutput, bufferSize);
|
||||
new CodedOutputStream(rawOutput, bufferSize);
|
||||
output.WriteRawVarint32((uint) value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -89,7 +84,7 @@ namespace Google.ProtocolBuffers
|
||||
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
|
||||
CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize);
|
||||
output.WriteRawVarint64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -139,7 +134,7 @@ namespace Google.ProtocolBuffers
|
||||
private static void AssertWriteLittleEndian32(byte[] data, uint value)
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
CodedOutputStream output = new CodedOutputStream(rawOutput);
|
||||
output.WriteRawLittleEndian32(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -148,7 +143,7 @@ namespace Google.ProtocolBuffers
|
||||
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
|
||||
{
|
||||
rawOutput = new MemoryStream();
|
||||
output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
|
||||
output = new CodedOutputStream(rawOutput, bufferSize);
|
||||
output.WriteRawLittleEndian32(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -162,7 +157,7 @@ namespace Google.ProtocolBuffers
|
||||
private static void AssertWriteLittleEndian64(byte[] data, ulong value)
|
||||
{
|
||||
MemoryStream rawOutput = new MemoryStream();
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
|
||||
CodedOutputStream output = new CodedOutputStream(rawOutput);
|
||||
output.WriteRawLittleEndian64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -171,7 +166,7 @@ namespace Google.ProtocolBuffers
|
||||
for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
|
||||
{
|
||||
rawOutput = new MemoryStream();
|
||||
output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
|
||||
output = new CodedOutputStream(rawOutput, blockSize);
|
||||
output.WriteRawLittleEndian64(value);
|
||||
output.Flush();
|
||||
Assert.AreEqual(data, rawOutput.ToArray());
|
||||
@ -196,39 +191,23 @@ namespace Google.ProtocolBuffers
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteWholeMessage()
|
||||
public void WriteWholeMessage_VaryingBlockSizes()
|
||||
{
|
||||
TestAllTypes message = TestUtil.GetAllSet();
|
||||
TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
|
||||
|
||||
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);
|
||||
CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize);
|
||||
message.WriteTo(output);
|
||||
output.Flush();
|
||||
TestUtil.AssertEqualBytes(rawBytes, rawOutput.ToArray());
|
||||
Assert.AreEqual(rawBytes, rawOutput.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests writing a whole message with every packed field type. Ensures the
|
||||
/// wire format of packed fields is compatible with C++.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WriteWholePackedFieldsMessage()
|
||||
{
|
||||
TestPackedTypes message = TestUtil.GetPackedSet();
|
||||
|
||||
byte[] rawBytes = message.ToByteArray();
|
||||
TestUtil.AssertEqualBytes(TestUtil.GetGoldenPackedFieldsMessage().ToByteArray(),
|
||||
rawBytes);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void EncodeZigZag32()
|
||||
{
|
||||
@ -293,80 +272,17 @@ namespace Google.ProtocolBuffers
|
||||
[Test]
|
||||
public void TestNegativeEnumNoTag()
|
||||
{
|
||||
Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2));
|
||||
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag(-2));
|
||||
Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
|
||||
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue));
|
||||
|
||||
byte[] bytes = new byte[10];
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
|
||||
output.WriteEnumNoTag(-2);
|
||||
CodedOutputStream output = new CodedOutputStream(bytes);
|
||||
output.WriteEnum((int) SampleEnum.NegativeValue);
|
||||
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnumWithTag()
|
||||
{
|
||||
Assert.AreEqual(11, CodedOutputStream.ComputeInt32Size(8, -2));
|
||||
Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, -2));
|
||||
|
||||
byte[] bytes = new byte[11];
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
|
||||
output.WriteEnum(8, "", -2, -2);
|
||||
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
//fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift
|
||||
Assert.AreEqual("40-FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnumArrayPacked()
|
||||
{
|
||||
int arraySize = 1 + (10 * 5);
|
||||
int msgSize = 1 + 1 + arraySize;
|
||||
byte[] bytes = new byte[msgSize];
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
|
||||
output.WritePackedEnumArray(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 });
|
||||
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
|
||||
uint tag;
|
||||
string name;
|
||||
Assert.IsTrue(input.ReadTag(out tag, out name));
|
||||
|
||||
List<int> values = new List<int>();
|
||||
input.ReadInt32Array(tag, name, values);
|
||||
|
||||
Assert.AreEqual(6, values.Count);
|
||||
for (int i = 0; i > -6; i--)
|
||||
Assert.AreEqual(i, values[Math.Abs(i)]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnumArray()
|
||||
{
|
||||
int arraySize = 1 + 1 + (11 * 5);
|
||||
int msgSize = arraySize;
|
||||
byte[] bytes = new byte[msgSize];
|
||||
CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
|
||||
output.WriteEnumArray(8, "", new int[] { 0, -1, -2, -3, -4, -5 });
|
||||
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
|
||||
CodedInputStream input = CodedInputStream.CreateInstance(bytes);
|
||||
uint tag;
|
||||
string name;
|
||||
Assert.IsTrue(input.ReadTag(out tag, out name));
|
||||
|
||||
List<int> values = new List<int>();
|
||||
input.ReadInt32Array(tag, name, values);
|
||||
|
||||
Assert.AreEqual(6, values.Count);
|
||||
for (int i = 0; i > -6; i--)
|
||||
Assert.AreEqual(i, values[Math.Abs(i)]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCodedInputOutputPosition()
|
||||
{
|
||||
@ -377,92 +293,91 @@ namespace Google.ProtocolBuffers
|
||||
byte[] child = new byte[120];
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(child);
|
||||
CodedOutputStream cout = CodedOutputStream.CreateInstance(ms, 20);
|
||||
CodedOutputStream cout = new CodedOutputStream(ms, 20);
|
||||
// Field 11: numeric value: 500
|
||||
cout.WriteTag(11, WireFormat.WireType.Varint);
|
||||
Assert.AreEqual(1, cout.Position);
|
||||
cout.WriteInt32NoTag(500);
|
||||
cout.WriteInt32(500);
|
||||
Assert.AreEqual(3, cout.Position);
|
||||
//Field 12: length delimited 120 bytes
|
||||
cout.WriteTag(12, WireFormat.WireType.LengthDelimited);
|
||||
Assert.AreEqual(4, cout.Position);
|
||||
cout.WriteBytesNoTag(ByteString.CopyFrom(content));
|
||||
cout.WriteBytes(ByteString.CopyFrom(content));
|
||||
Assert.AreEqual(115, cout.Position);
|
||||
// Field 13: fixed numeric value: 501
|
||||
cout.WriteTag(13, WireFormat.WireType.Fixed32);
|
||||
Assert.AreEqual(116, cout.Position);
|
||||
cout.WriteSFixed32NoTag(501);
|
||||
cout.WriteSFixed32(501);
|
||||
Assert.AreEqual(120, cout.Position);
|
||||
cout.Flush();
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[130];
|
||||
{
|
||||
CodedOutputStream cout = CodedOutputStream.CreateInstance(bytes);
|
||||
CodedOutputStream cout = new CodedOutputStream(bytes);
|
||||
// Field 1: numeric value: 500
|
||||
cout.WriteTag(1, WireFormat.WireType.Varint);
|
||||
Assert.AreEqual(1, cout.Position);
|
||||
cout.WriteInt32NoTag(500);
|
||||
cout.WriteInt32(500);
|
||||
Assert.AreEqual(3, cout.Position);
|
||||
//Field 2: length delimited 120 bytes
|
||||
cout.WriteTag(2, WireFormat.WireType.LengthDelimited);
|
||||
Assert.AreEqual(4, cout.Position);
|
||||
cout.WriteBytesNoTag(ByteString.CopyFrom(child));
|
||||
cout.WriteBytes(ByteString.CopyFrom(child));
|
||||
Assert.AreEqual(125, cout.Position);
|
||||
// Field 3: fixed numeric value: 500
|
||||
cout.WriteTag(3, WireFormat.WireType.Fixed32);
|
||||
Assert.AreEqual(126, cout.Position);
|
||||
cout.WriteSFixed32NoTag(501);
|
||||
cout.WriteSFixed32(501);
|
||||
Assert.AreEqual(130, cout.Position);
|
||||
cout.Flush();
|
||||
}
|
||||
//Now test Input stream:
|
||||
// Now test Input stream:
|
||||
{
|
||||
CodedInputStream cin = CodedInputStream.CreateInstance(new MemoryStream(bytes), new byte[50]);
|
||||
CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50]);
|
||||
uint tag;
|
||||
int intValue = 0;
|
||||
string ignore;
|
||||
Assert.AreEqual(0, cin.Position);
|
||||
// Field 1:
|
||||
Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 1);
|
||||
Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 1);
|
||||
Assert.AreEqual(1, cin.Position);
|
||||
Assert.IsTrue(cin.ReadInt32(ref intValue) && intValue == 500);
|
||||
Assert.AreEqual(500, cin.ReadInt32());
|
||||
Assert.AreEqual(3, cin.Position);
|
||||
//Field 2:
|
||||
Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 2);
|
||||
Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 2);
|
||||
Assert.AreEqual(4, cin.Position);
|
||||
uint childlen = cin.ReadRawVarint32();
|
||||
Assert.AreEqual(120u, childlen);
|
||||
int childlen = cin.ReadLength();
|
||||
Assert.AreEqual(120, childlen);
|
||||
Assert.AreEqual(5, cin.Position);
|
||||
int oldlimit = cin.PushLimit((int)childlen);
|
||||
Assert.AreEqual(5, cin.Position);
|
||||
// Now we are reading child message
|
||||
{
|
||||
// Field 11: numeric value: 500
|
||||
Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 11);
|
||||
Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 11);
|
||||
Assert.AreEqual(6, cin.Position);
|
||||
Assert.IsTrue(cin.ReadInt32(ref intValue) && intValue == 500);
|
||||
Assert.AreEqual(500, cin.ReadInt32());
|
||||
Assert.AreEqual(8, cin.Position);
|
||||
//Field 12: length delimited 120 bytes
|
||||
Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 12);
|
||||
Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 12);
|
||||
Assert.AreEqual(9, cin.Position);
|
||||
ByteString bstr = null;
|
||||
Assert.IsTrue(cin.ReadBytes(ref bstr) && bstr.Length == 110 && bstr.ToByteArray()[109] == 109);
|
||||
ByteString bstr = cin.ReadBytes();
|
||||
Assert.AreEqual(110, bstr.Length);
|
||||
Assert.AreEqual((byte) 109, bstr[109]);
|
||||
Assert.AreEqual(120, cin.Position);
|
||||
// Field 13: fixed numeric value: 501
|
||||
Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 13);
|
||||
Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 13);
|
||||
// ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit
|
||||
Assert.AreEqual(121, cin.Position);
|
||||
Assert.IsTrue(cin.ReadSFixed32(ref intValue) && intValue == 501);
|
||||
Assert.AreEqual(501, cin.ReadSFixed32());
|
||||
Assert.AreEqual(125, cin.Position);
|
||||
Assert.IsTrue(cin.IsAtEnd);
|
||||
}
|
||||
cin.PopLimit(oldlimit);
|
||||
Assert.AreEqual(125, cin.Position);
|
||||
// Field 3: fixed numeric value: 501
|
||||
Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 3);
|
||||
Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 3);
|
||||
Assert.AreEqual(126, cin.Position);
|
||||
Assert.IsTrue(cin.ReadSFixed32(ref intValue) && intValue == 501);
|
||||
Assert.AreEqual(501, cin.ReadSFixed32());
|
||||
Assert.AreEqual(130, cin.Position);
|
||||
Assert.IsTrue(cin.IsAtEnd);
|
||||
}
|
485
csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
Normal file
485
csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
Normal file
@ -0,0 +1,485 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
|
||||
namespace Google.Protobuf.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for MapField which aren't reliant on the encoded format -
|
||||
/// tests for serialization/deserialization are part of GeneratedMessageTest.
|
||||
/// </summary>
|
||||
public class MapFieldTest
|
||||
{
|
||||
[Test]
|
||||
public void Clone_ClonesMessages()
|
||||
{
|
||||
var message = new ForeignMessage { C = 20 };
|
||||
var map = new MapField<string, ForeignMessage> { { "x", message } };
|
||||
var clone = map.Clone();
|
||||
map["x"].C = 30;
|
||||
Assert.AreEqual(20, clone["x"].C);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NullValues()
|
||||
{
|
||||
TestNullValues<int?>(0);
|
||||
TestNullValues("");
|
||||
TestNullValues(new TestAllTypes());
|
||||
}
|
||||
|
||||
private void TestNullValues<T>(T nonNullValue)
|
||||
{
|
||||
var map = new MapField<int, T>(false);
|
||||
var nullValue = (T) (object) null;
|
||||
Assert.Throws<ArgumentNullException>(() => map.Add(0, nullValue));
|
||||
Assert.Throws<ArgumentNullException>(() => map[0] = nullValue);
|
||||
map.Add(1, nonNullValue);
|
||||
map[1] = nonNullValue;
|
||||
|
||||
// Doesn't throw...
|
||||
map = new MapField<int, T>(true);
|
||||
map.Add(0, nullValue);
|
||||
map[0] = nullValue;
|
||||
map.Add(1, nonNullValue);
|
||||
map[1] = nonNullValue;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_ForbidsNullKeys()
|
||||
{
|
||||
var map = new MapField<string, ForeignMessage>();
|
||||
Assert.Throws<ArgumentNullException>(() => map.Add(null, new ForeignMessage()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Indexer_ForbidsNullKeys()
|
||||
{
|
||||
var map = new MapField<string, ForeignMessage>();
|
||||
Assert.Throws<ArgumentNullException>(() => map[null] = new ForeignMessage());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddPreservesInsertionOrder()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
map.Add("a", "v1");
|
||||
map.Add("b", "v2");
|
||||
map.Add("c", "v3");
|
||||
map.Remove("b");
|
||||
map.Add("d", "v4");
|
||||
CollectionAssert.AreEqual(new[] { "a", "c", "d" }, map.Keys);
|
||||
CollectionAssert.AreEqual(new[] { "v1", "v3", "v4" }, map.Values);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EqualityIsOrderInsensitive()
|
||||
{
|
||||
var map1 = new MapField<string, string>();
|
||||
map1.Add("a", "v1");
|
||||
map1.Add("b", "v2");
|
||||
|
||||
var map2 = new MapField<string, string>();
|
||||
map2.Add("b", "v2");
|
||||
map2.Add("a", "v1");
|
||||
|
||||
EqualityTester.AssertEquality(map1, map2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EqualityIsKeySensitive()
|
||||
{
|
||||
var map1 = new MapField<string, string>();
|
||||
map1.Add("first key", "v1");
|
||||
map1.Add("second key", "v2");
|
||||
|
||||
var map2 = new MapField<string, string>();
|
||||
map2.Add("third key", "v1");
|
||||
map2.Add("fourth key", "v2");
|
||||
|
||||
EqualityTester.AssertInequality(map1, map2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Equality_Simple()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
EqualityTester.AssertEquality(map, map);
|
||||
EqualityTester.AssertInequality(map, null);
|
||||
Assert.IsFalse(map.Equals(new object()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EqualityIsValueSensitive()
|
||||
{
|
||||
// Note: Without some care, it's a little easier than one might
|
||||
// hope to see hash collisions, but only in some environments...
|
||||
var map1 = new MapField<string, string>();
|
||||
map1.Add("a", "first value");
|
||||
map1.Add("b", "second value");
|
||||
|
||||
var map2 = new MapField<string, string>();
|
||||
map2.Add("a", "third value");
|
||||
map2.Add("b", "fourth value");
|
||||
|
||||
EqualityTester.AssertInequality(map1, map2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EqualityHandlesNullValues()
|
||||
{
|
||||
var map1 = new MapField<string, ForeignMessage>();
|
||||
map1.Add("a", new ForeignMessage { C = 10 });
|
||||
map1.Add("b", null);
|
||||
|
||||
var map2 = new MapField<string, ForeignMessage>();
|
||||
map2.Add("a", new ForeignMessage { C = 10 });
|
||||
map2.Add("b", null);
|
||||
|
||||
EqualityTester.AssertEquality(map1, map2);
|
||||
// Check the null value isn't ignored entirely...
|
||||
Assert.IsTrue(map1.Remove("b"));
|
||||
EqualityTester.AssertInequality(map1, map2);
|
||||
map1.Add("b", new ForeignMessage());
|
||||
EqualityTester.AssertInequality(map1, map2);
|
||||
map1["b"] = null;
|
||||
EqualityTester.AssertEquality(map1, map2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_Dictionary()
|
||||
{
|
||||
var map1 = new MapField<string, string>
|
||||
{
|
||||
{ "x", "y" },
|
||||
{ "a", "b" }
|
||||
};
|
||||
var map2 = new MapField<string, string>
|
||||
{
|
||||
{ "before", "" },
|
||||
map1,
|
||||
{ "after", "" }
|
||||
};
|
||||
var expected = new MapField<string, string>
|
||||
{
|
||||
{ "before", "" },
|
||||
{ "x", "y" },
|
||||
{ "a", "b" },
|
||||
{ "after", "" }
|
||||
};
|
||||
Assert.AreEqual(expected, map2);
|
||||
CollectionAssert.AreEqual(new[] { "before", "x", "a", "after" }, map2.Keys);
|
||||
}
|
||||
|
||||
// General IDictionary<TKey, TValue> behavior tests
|
||||
[Test]
|
||||
public void Add_KeyAlreadyExists()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
map.Add("foo", "bar");
|
||||
Assert.Throws<ArgumentException>(() => map.Add("foo", "baz"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_Pair()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
ICollection<KeyValuePair<string, string>> collection = map;
|
||||
collection.Add(NewKeyValuePair("x", "y"));
|
||||
Assert.AreEqual("y", map["x"]);
|
||||
Assert.Throws<ArgumentException>(() => collection.Add(NewKeyValuePair("x", "z")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Contains_Pair()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
ICollection<KeyValuePair<string, string>> collection = map;
|
||||
Assert.IsTrue(collection.Contains(NewKeyValuePair("x", "y")));
|
||||
Assert.IsFalse(collection.Contains(NewKeyValuePair("x", "z")));
|
||||
Assert.IsFalse(collection.Contains(NewKeyValuePair("z", "y")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Remove_Key()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
map.Add("foo", "bar");
|
||||
Assert.AreEqual(1, map.Count);
|
||||
Assert.IsFalse(map.Remove("missing"));
|
||||
Assert.AreEqual(1, map.Count);
|
||||
Assert.IsTrue(map.Remove("foo"));
|
||||
Assert.AreEqual(0, map.Count);
|
||||
Assert.Throws<ArgumentNullException>(() => map.Remove(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Remove_Pair()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
map.Add("foo", "bar");
|
||||
ICollection<KeyValuePair<string, string>> collection = map;
|
||||
Assert.AreEqual(1, map.Count);
|
||||
Assert.IsFalse(collection.Remove(NewKeyValuePair("wrong key", "bar")));
|
||||
Assert.AreEqual(1, map.Count);
|
||||
Assert.IsFalse(collection.Remove(NewKeyValuePair("foo", "wrong value")));
|
||||
Assert.AreEqual(1, map.Count);
|
||||
Assert.IsTrue(collection.Remove(NewKeyValuePair("foo", "bar")));
|
||||
Assert.AreEqual(0, map.Count);
|
||||
Assert.Throws<ArgumentException>(() => collection.Remove(new KeyValuePair<string, string>(null, "")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyTo_Pair()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
map.Add("foo", "bar");
|
||||
ICollection<KeyValuePair<string, string>> collection = map;
|
||||
KeyValuePair<string, string>[] array = new KeyValuePair<string, string>[3];
|
||||
collection.CopyTo(array, 1);
|
||||
Assert.AreEqual(NewKeyValuePair("foo", "bar"), array[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Clear()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
Assert.AreEqual(1, map.Count);
|
||||
map.Clear();
|
||||
Assert.AreEqual(0, map.Count);
|
||||
map.Add("x", "y");
|
||||
Assert.AreEqual(1, map.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Indexer_Get()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
Assert.AreEqual("y", map["x"]);
|
||||
Assert.Throws<KeyNotFoundException>(() => { var ignored = map["z"]; });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Indexer_Set()
|
||||
{
|
||||
var map = new MapField<string, string>();
|
||||
map["x"] = "y";
|
||||
Assert.AreEqual("y", map["x"]);
|
||||
map["x"] = "z"; // This won't throw, unlike Add.
|
||||
Assert.AreEqual("z", map["x"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetEnumerator_NonGeneric()
|
||||
{
|
||||
IEnumerable map = new MapField<string, string> { { "x", "y" } };
|
||||
CollectionAssert.AreEqual(new[] { new KeyValuePair<string, string>("x", "y") },
|
||||
map.Cast<object>().ToList());
|
||||
}
|
||||
|
||||
// Test for the explicitly-implemented non-generic IDictionary interface
|
||||
[Test]
|
||||
public void IDictionary_GetEnumerator()
|
||||
{
|
||||
IDictionary map = new MapField<string, string> { { "x", "y" } };
|
||||
var enumerator = map.GetEnumerator();
|
||||
|
||||
// Commented assertions show an ideal situation - it looks like
|
||||
// the LinkedList enumerator doesn't throw when you ask for the current entry
|
||||
// at an inappropriate time; fixing this would be more work than it's worth.
|
||||
// Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
|
||||
Assert.IsTrue(enumerator.MoveNext());
|
||||
Assert.AreEqual("x", enumerator.Key);
|
||||
Assert.AreEqual("y", enumerator.Value);
|
||||
Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Current);
|
||||
Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Entry);
|
||||
Assert.IsFalse(enumerator.MoveNext());
|
||||
// Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
|
||||
enumerator.Reset();
|
||||
// Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
|
||||
Assert.IsTrue(enumerator.MoveNext());
|
||||
Assert.AreEqual("x", enumerator.Key); // Assume the rest are okay
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_Add()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
IDictionary dictionary = map;
|
||||
dictionary.Add("a", "b");
|
||||
Assert.AreEqual("b", map["a"]);
|
||||
Assert.Throws<ArgumentException>(() => dictionary.Add("a", "duplicate"));
|
||||
Assert.Throws<InvalidCastException>(() => dictionary.Add(new object(), "key is bad"));
|
||||
Assert.Throws<InvalidCastException>(() => dictionary.Add("value is bad", new object()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_Contains()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
IDictionary dictionary = map;
|
||||
|
||||
Assert.IsFalse(dictionary.Contains("a"));
|
||||
Assert.IsFalse(dictionary.Contains(5));
|
||||
// Surprising, but IDictionary.Contains is only about keys.
|
||||
Assert.IsFalse(dictionary.Contains(new DictionaryEntry("x", "y")));
|
||||
Assert.IsTrue(dictionary.Contains("x"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_Remove()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
IDictionary dictionary = map;
|
||||
dictionary.Remove("a");
|
||||
Assert.AreEqual(1, dictionary.Count);
|
||||
dictionary.Remove(5);
|
||||
Assert.AreEqual(1, dictionary.Count);
|
||||
dictionary.Remove(new DictionaryEntry("x", "y"));
|
||||
Assert.AreEqual(1, dictionary.Count);
|
||||
dictionary.Remove("x");
|
||||
Assert.AreEqual(0, dictionary.Count);
|
||||
Assert.Throws<ArgumentNullException>(() => dictionary.Remove(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_CopyTo()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
IDictionary dictionary = map;
|
||||
var array = new DictionaryEntry[3];
|
||||
dictionary.CopyTo(array, 1);
|
||||
CollectionAssert.AreEqual(new[] { default(DictionaryEntry), new DictionaryEntry("x", "y"), default(DictionaryEntry) },
|
||||
array);
|
||||
var objectArray = new object[3];
|
||||
dictionary.CopyTo(objectArray, 1);
|
||||
CollectionAssert.AreEqual(new object[] { null, new DictionaryEntry("x", "y"), null },
|
||||
objectArray);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_IsFixedSize()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
IDictionary dictionary = map;
|
||||
Assert.IsFalse(dictionary.IsFixedSize);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_Keys()
|
||||
{
|
||||
IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
|
||||
CollectionAssert.AreEqual(new[] { "x" }, dictionary.Keys);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_Values()
|
||||
{
|
||||
IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
|
||||
CollectionAssert.AreEqual(new[] { "y" }, dictionary.Values);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_IsSynchronized()
|
||||
{
|
||||
IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
|
||||
Assert.IsFalse(dictionary.IsSynchronized);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_SyncRoot()
|
||||
{
|
||||
IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
|
||||
Assert.AreSame(dictionary, dictionary.SyncRoot);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_Indexer_Get()
|
||||
{
|
||||
IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
|
||||
Assert.AreEqual("y", dictionary["x"]);
|
||||
Assert.IsNull(dictionary["a"]);
|
||||
Assert.IsNull(dictionary[5]);
|
||||
Assert.Throws<ArgumentNullException>(() => dictionary[null].GetHashCode());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IDictionary_Indexer_Set()
|
||||
{
|
||||
var map = new MapField<string, string> { { "x", "y" } };
|
||||
IDictionary dictionary = map;
|
||||
map["a"] = "b";
|
||||
Assert.AreEqual("b", map["a"]);
|
||||
map["a"] = "c";
|
||||
Assert.AreEqual("c", map["a"]);
|
||||
Assert.Throws<InvalidCastException>(() => dictionary[5] = "x");
|
||||
Assert.Throws<InvalidCastException>(() => dictionary["x"] = 5);
|
||||
Assert.Throws<ArgumentNullException>(() => dictionary[null] = "z");
|
||||
Assert.Throws<ArgumentNullException>(() => dictionary["x"] = null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllowNullValues_Property()
|
||||
{
|
||||
// Non-message reference type values are non-nullable by default, but can be overridden
|
||||
Assert.IsFalse(new MapField<int, string>().AllowsNullValues);
|
||||
Assert.IsFalse(new MapField<int, string>(false).AllowsNullValues);
|
||||
Assert.IsTrue(new MapField<int, string>(true).AllowsNullValues);
|
||||
|
||||
// Non-nullable value type values are never nullable
|
||||
Assert.IsFalse(new MapField<int, int>().AllowsNullValues);
|
||||
Assert.IsFalse(new MapField<int, int>(false).AllowsNullValues);
|
||||
Assert.Throws<ArgumentException>(() => new MapField<int, int>(true));
|
||||
|
||||
// Message type values are nullable by default, but can be overridden
|
||||
Assert.IsTrue(new MapField<int, TestAllTypes>().AllowsNullValues);
|
||||
Assert.IsFalse(new MapField<int, TestAllTypes>(false).AllowsNullValues);
|
||||
Assert.IsTrue(new MapField<int, TestAllTypes>(true).AllowsNullValues);
|
||||
|
||||
// Nullable value type values are nullable by default, but can be overridden
|
||||
Assert.IsTrue(new MapField<int, int?>().AllowsNullValues);
|
||||
Assert.IsFalse(new MapField<int, int?>(false).AllowsNullValues);
|
||||
Assert.IsTrue(new MapField<int, int?>(true).AllowsNullValues);
|
||||
}
|
||||
|
||||
private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
|
||||
{
|
||||
return new KeyValuePair<TKey, TValue>(key, value);
|
||||
}
|
||||
}
|
||||
}
|
603
csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
Normal file
603
csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
Normal file
@ -0,0 +1,603 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.Protobuf.Collections
|
||||
{
|
||||
public class RepeatedFieldTest
|
||||
{
|
||||
[Test]
|
||||
public void NullValuesRejected()
|
||||
{
|
||||
var list = new RepeatedField<string>();
|
||||
Assert.Throws<ArgumentNullException>(() => list.Add((string)null));
|
||||
Assert.Throws<ArgumentNullException>(() => list.Add((IEnumerable<string>)null));
|
||||
Assert.Throws<ArgumentNullException>(() => list.Add((RepeatedField<string>)null));
|
||||
Assert.Throws<ArgumentNullException>(() => list.Contains(null));
|
||||
Assert.Throws<ArgumentNullException>(() => list.IndexOf(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_SingleItem()
|
||||
{
|
||||
var list = new RepeatedField<string>();
|
||||
list.Add("foo");
|
||||
Assert.AreEqual(1, list.Count);
|
||||
Assert.AreEqual("foo", list[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_Sequence()
|
||||
{
|
||||
var list = new RepeatedField<string>();
|
||||
list.Add(new[] { "foo", "bar" });
|
||||
Assert.AreEqual(2, list.Count);
|
||||
Assert.AreEqual("foo", list[0]);
|
||||
Assert.AreEqual("bar", list[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_RepeatedField()
|
||||
{
|
||||
var list = new RepeatedField<string> { "original" };
|
||||
list.Add(new RepeatedField<string> { "foo", "bar" });
|
||||
Assert.AreEqual(3, list.Count);
|
||||
Assert.AreEqual("original", list[0]);
|
||||
Assert.AreEqual("foo", list[1]);
|
||||
Assert.AreEqual("bar", list[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveAt_Valid()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second", "third" };
|
||||
list.RemoveAt(1);
|
||||
CollectionAssert.AreEqual(new[] { "first", "third" }, list);
|
||||
// Just check that these don't throw...
|
||||
list.RemoveAt(list.Count - 1); // Now the count will be 1...
|
||||
list.RemoveAt(0);
|
||||
Assert.AreEqual(0, list.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveAt_Invalid()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second", "third" };
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(-1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Insert_Valid()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
list.Insert(1, "middle");
|
||||
CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
|
||||
list.Insert(3, "end");
|
||||
CollectionAssert.AreEqual(new[] { "first", "middle", "second", "end" }, list);
|
||||
list.Insert(0, "start");
|
||||
CollectionAssert.AreEqual(new[] { "start", "first", "middle", "second", "end" }, list);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Insert_Invalid()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(-1, "foo"));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(3, "foo"));
|
||||
Assert.Throws<ArgumentNullException>(() => list.Insert(0, null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Equals_RepeatedField()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.IsFalse(list.Equals((RepeatedField<string>) null));
|
||||
Assert.IsTrue(list.Equals(list));
|
||||
Assert.IsFalse(list.Equals(new RepeatedField<string> { "first", "third" }));
|
||||
Assert.IsFalse(list.Equals(new RepeatedField<string> { "first" }));
|
||||
Assert.IsTrue(list.Equals(new RepeatedField<string> { "first", "second" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Equals_Object()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.IsFalse(list.Equals((object) null));
|
||||
Assert.IsTrue(list.Equals((object) list));
|
||||
Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first", "third" }));
|
||||
Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first" }));
|
||||
Assert.IsTrue(list.Equals((object) new RepeatedField<string> { "first", "second" }));
|
||||
Assert.IsFalse(list.Equals(new object()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetEnumerator_GenericInterface()
|
||||
{
|
||||
IEnumerable<string> list = new RepeatedField<string> { "first", "second" };
|
||||
// Select gets rid of the optimizations in ToList...
|
||||
CollectionAssert.AreEqual(new[] { "first", "second" }, list.Select(x => x).ToList());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetEnumerator_NonGenericInterface()
|
||||
{
|
||||
IEnumerable list = new RepeatedField<string> { "first", "second" };
|
||||
CollectionAssert.AreEqual(new[] { "first", "second" }, list.Cast<object>().ToList());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyTo()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
string[] stringArray = new string[4];
|
||||
list.CopyTo(stringArray, 1);
|
||||
CollectionAssert.AreEqual(new[] { null, "first", "second", null }, stringArray);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Indexer_Get()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.AreEqual("first", list[0]);
|
||||
Assert.AreEqual("second", list[1]);
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list[-1].GetHashCode());
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list[2].GetHashCode());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Indexer_Set()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
list[0] = "changed";
|
||||
Assert.AreEqual("changed", list[0]);
|
||||
Assert.Throws<ArgumentNullException>(() => list[0] = null);
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list[-1] = "bad");
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list[2] = "bad");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Clone_ReturnsMutable()
|
||||
{
|
||||
var list = new RepeatedField<int> { 0 };
|
||||
var clone = list.Clone();
|
||||
clone[0] = 1;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Enumerator()
|
||||
{
|
||||
var list = new RepeatedField<string> { "first", "second" };
|
||||
using (var enumerator = list.GetEnumerator())
|
||||
{
|
||||
Assert.IsTrue(enumerator.MoveNext());
|
||||
Assert.AreEqual("first", enumerator.Current);
|
||||
Assert.IsTrue(enumerator.MoveNext());
|
||||
Assert.AreEqual("second", enumerator.Current);
|
||||
Assert.IsFalse(enumerator.MoveNext());
|
||||
Assert.IsFalse(enumerator.MoveNext());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddEntriesFrom_PackedInt32()
|
||||
{
|
||||
uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
var length = CodedOutputStream.ComputeInt32Size(10)
|
||||
+ CodedOutputStream.ComputeInt32Size(999)
|
||||
+ CodedOutputStream.ComputeInt32Size(-1000);
|
||||
output.WriteTag(packedTag);
|
||||
output.WriteRawVarint32((uint) length);
|
||||
output.WriteInt32(10);
|
||||
output.WriteInt32(999);
|
||||
output.WriteInt32(-1000);
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
// Deliberately "expecting" a non-packed tag, but we detect that the data is
|
||||
// actually packed.
|
||||
uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var field = new RepeatedField<int>();
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(packedTag);
|
||||
field.AddEntriesFrom(input, FieldCodec.ForInt32(nonPackedTag));
|
||||
CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddEntriesFrom_NonPackedInt32()
|
||||
{
|
||||
uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
output.WriteTag(nonPackedTag);
|
||||
output.WriteInt32(10);
|
||||
output.WriteTag(nonPackedTag);
|
||||
output.WriteInt32(999);
|
||||
output.WriteTag(nonPackedTag);
|
||||
output.WriteInt32(-1000); // Just for variety...
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
// Deliberately "expecting" a packed tag, but we detect that the data is
|
||||
// actually not packed.
|
||||
uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var field = new RepeatedField<int>();
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(nonPackedTag);
|
||||
field.AddEntriesFrom(input, FieldCodec.ForInt32(packedTag));
|
||||
CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddEntriesFrom_String()
|
||||
{
|
||||
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
output.WriteTag(tag);
|
||||
output.WriteString("Foo");
|
||||
output.WriteTag(tag);
|
||||
output.WriteString("");
|
||||
output.WriteTag(tag);
|
||||
output.WriteString("Bar");
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
var field = new RepeatedField<string>();
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(tag);
|
||||
field.AddEntriesFrom(input, FieldCodec.ForString(tag));
|
||||
CollectionAssert.AreEqual(new[] { "Foo", "", "Bar" }, field);
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddEntriesFrom_Message()
|
||||
{
|
||||
var message1 = new ForeignMessage { C = 2000 };
|
||||
var message2 = new ForeignMessage { C = -250 };
|
||||
|
||||
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
output.WriteTag(tag);
|
||||
output.WriteMessage(message1);
|
||||
output.WriteTag(tag);
|
||||
output.WriteMessage(message2);
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
var field = new RepeatedField<ForeignMessage>();
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(tag);
|
||||
field.AddEntriesFrom(input, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
|
||||
CollectionAssert.AreEqual(new[] { message1, message2}, field);
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteTo_PackedInt32()
|
||||
{
|
||||
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var field = new RepeatedField<int> { 10, 1000, 1000000 };
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
field.WriteTo(output, FieldCodec.ForInt32(tag));
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(tag);
|
||||
var length = input.ReadLength();
|
||||
Assert.AreEqual(10, input.ReadInt32());
|
||||
Assert.AreEqual(1000, input.ReadInt32());
|
||||
Assert.AreEqual(1000000, input.ReadInt32());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
Assert.AreEqual(1 + CodedOutputStream.ComputeLengthSize(length) + length, stream.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteTo_NonPackedInt32()
|
||||
{
|
||||
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
|
||||
var field = new RepeatedField<int> { 10, 1000, 1000000};
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
field.WriteTo(output, FieldCodec.ForInt32(tag));
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual(10, input.ReadInt32());
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual(1000, input.ReadInt32());
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual(1000000, input.ReadInt32());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteTo_String()
|
||||
{
|
||||
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var field = new RepeatedField<string> { "Foo", "", "Bar" };
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
field.WriteTo(output, FieldCodec.ForString(tag));
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual("Foo", input.ReadString());
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual("", input.ReadString());
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual("Bar", input.ReadString());
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteTo_Message()
|
||||
{
|
||||
var message1 = new ForeignMessage { C = 20 };
|
||||
var message2 = new ForeignMessage { C = 25 };
|
||||
uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
|
||||
var field = new RepeatedField<ForeignMessage> { message1, message2 };
|
||||
var stream = new MemoryStream();
|
||||
var output = new CodedOutputStream(stream);
|
||||
field.WriteTo(output, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
|
||||
output.Flush();
|
||||
stream.Position = 0;
|
||||
|
||||
var input = new CodedInputStream(stream);
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual(message1, input.ReadMessage(ForeignMessage.Parser));
|
||||
input.AssertNextTag(tag);
|
||||
Assert.AreEqual(message2, input.ReadMessage(ForeignMessage.Parser));
|
||||
Assert.IsTrue(input.IsAtEnd);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateSize_VariableSizeNonPacked()
|
||||
{
|
||||
var list = new RepeatedField<int> { 1, 500, 1 };
|
||||
var tag = WireFormat.MakeTag(1, WireFormat.WireType.Varint);
|
||||
// 2 bytes for the first entry, 3 bytes for the second, 2 bytes for the third
|
||||
Assert.AreEqual(7, list.CalculateSize(FieldCodec.ForInt32(tag)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateSize_FixedSizeNonPacked()
|
||||
{
|
||||
var list = new RepeatedField<int> { 1, 500, 1 };
|
||||
var tag = WireFormat.MakeTag(1, WireFormat.WireType.Fixed32);
|
||||
// 5 bytes for the each entry
|
||||
Assert.AreEqual(15, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateSize_VariableSizePacked()
|
||||
{
|
||||
var list = new RepeatedField<int> { 1, 500, 1};
|
||||
var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
|
||||
// 1 byte for the tag, 1 byte for the length,
|
||||
// 1 byte for the first entry, 2 bytes for the second, 1 byte for the third
|
||||
Assert.AreEqual(6, list.CalculateSize(FieldCodec.ForInt32(tag)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateSize_FixedSizePacked()
|
||||
{
|
||||
var list = new RepeatedField<int> { 1, 500, 1 };
|
||||
var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
|
||||
// 1 byte for the tag, 1 byte for the length, 4 bytes per entry
|
||||
Assert.AreEqual(14, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnumArray()
|
||||
{
|
||||
int arraySize = 1 + 1 + (11 * 5);
|
||||
int msgSize = arraySize;
|
||||
byte[] bytes = new byte[msgSize];
|
||||
CodedOutputStream output = new CodedOutputStream(bytes);
|
||||
uint tag = WireFormat.MakeTag(8, WireFormat.WireType.Varint);
|
||||
for (int i = 0; i >= -5; i--)
|
||||
{
|
||||
output.WriteTag(tag);
|
||||
output.WriteEnum(i);
|
||||
}
|
||||
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
|
||||
CodedInputStream input = new CodedInputStream(bytes);
|
||||
Assert.IsTrue(input.ReadTag(out tag));
|
||||
|
||||
RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
|
||||
values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
|
||||
|
||||
Assert.AreEqual(6, values.Count);
|
||||
Assert.AreEqual(SampleEnum.None, values[0]);
|
||||
Assert.AreEqual(((SampleEnum)(-1)), values[1]);
|
||||
Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
|
||||
Assert.AreEqual(((SampleEnum)(-3)), values[3]);
|
||||
Assert.AreEqual(((SampleEnum)(-4)), values[4]);
|
||||
Assert.AreEqual(((SampleEnum)(-5)), values[5]);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestNegativeEnumPackedArray()
|
||||
{
|
||||
int arraySize = 1 + (10 * 5);
|
||||
int msgSize = 1 + 1 + arraySize;
|
||||
byte[] bytes = new byte[msgSize];
|
||||
CodedOutputStream output = new CodedOutputStream(bytes);
|
||||
// Length-delimited to show we want the packed representation
|
||||
uint tag = WireFormat.MakeTag(8, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteTag(tag);
|
||||
int size = 0;
|
||||
for (int i = 0; i >= -5; i--)
|
||||
{
|
||||
size += CodedOutputStream.ComputeEnumSize(i);
|
||||
}
|
||||
output.WriteRawVarint32((uint)size);
|
||||
for (int i = 0; i >= -5; i--)
|
||||
{
|
||||
output.WriteEnum(i);
|
||||
}
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
|
||||
CodedInputStream input = new CodedInputStream(bytes);
|
||||
Assert.IsTrue(input.ReadTag(out tag));
|
||||
|
||||
RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
|
||||
values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
|
||||
|
||||
Assert.AreEqual(6, values.Count);
|
||||
Assert.AreEqual(SampleEnum.None, values[0]);
|
||||
Assert.AreEqual(((SampleEnum)(-1)), values[1]);
|
||||
Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
|
||||
Assert.AreEqual(((SampleEnum)(-3)), values[3]);
|
||||
Assert.AreEqual(((SampleEnum)(-4)), values[4]);
|
||||
Assert.AreEqual(((SampleEnum)(-5)), values[5]);
|
||||
}
|
||||
|
||||
// Fairly perfunctory tests for the non-generic IList implementation
|
||||
[Test]
|
||||
public void IList_Indexer()
|
||||
{
|
||||
var field = new RepeatedField<string> { "first", "second" };
|
||||
IList list = field;
|
||||
Assert.AreEqual("first", list[0]);
|
||||
list[1] = "changed";
|
||||
Assert.AreEqual("changed", field[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_Contains()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.IsTrue(list.Contains("second"));
|
||||
Assert.IsFalse(list.Contains("third"));
|
||||
Assert.IsFalse(list.Contains(new object()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_Add()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
list.Add("third");
|
||||
CollectionAssert.AreEqual(new[] { "first", "second", "third" }, list);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_Remove()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
list.Remove("third"); // No-op, no exception
|
||||
list.Remove(new object()); // No-op, no exception
|
||||
list.Remove("first");
|
||||
CollectionAssert.AreEqual(new[] { "second" }, list);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_IsFixedSize()
|
||||
{
|
||||
var field = new RepeatedField<string> { "first", "second" };
|
||||
IList list = field;
|
||||
Assert.IsFalse(list.IsFixedSize);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_IndexOf()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.AreEqual(1, list.IndexOf("second"));
|
||||
Assert.AreEqual(-1, list.IndexOf("third"));
|
||||
Assert.AreEqual(-1, list.IndexOf(new object()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_SyncRoot()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.AreSame(list, list.SyncRoot);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_CopyTo()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
string[] stringArray = new string[4];
|
||||
list.CopyTo(stringArray, 1);
|
||||
CollectionAssert.AreEqual(new[] { null, "first", "second", null }, stringArray);
|
||||
|
||||
object[] objectArray = new object[4];
|
||||
list.CopyTo(objectArray, 1);
|
||||
CollectionAssert.AreEqual(new[] { null, "first", "second", null }, objectArray);
|
||||
|
||||
Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new StringBuilder[4], 1));
|
||||
Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new int[4], 1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_IsSynchronized()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
Assert.IsFalse(list.IsSynchronized);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IList_Insert()
|
||||
{
|
||||
IList list = new RepeatedField<string> { "first", "second" };
|
||||
list.Insert(1, "middle");
|
||||
CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using NUnit.Framework;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Google.Protobuf.Compatibility
|
||||
{
|
||||
public class PropertyInfoExtensionsTest
|
||||
{
|
||||
public string PublicReadWrite { get; set; }
|
||||
private string PrivateReadWrite { get; set; }
|
||||
public string PublicReadPrivateWrite { get; private set; }
|
||||
public string PrivateReadPublicWrite { private get; set; }
|
||||
public string PublicReadOnly { get { return null; } }
|
||||
private string PrivateReadOnly { get { return null; } }
|
||||
public string PublicWriteOnly { set { } }
|
||||
private string PrivateWriteOnly { set { } }
|
||||
|
||||
[Test]
|
||||
[TestCase("PublicReadWrite")]
|
||||
[TestCase("PublicReadPrivateWrite")]
|
||||
[TestCase("PublicReadOnly")]
|
||||
public void GetGetMethod_Success(string name)
|
||||
{
|
||||
var propertyInfo = typeof(PropertyInfoExtensionsTest)
|
||||
.GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
Assert.IsNotNull(PropertyInfoExtensions.GetGetMethod(propertyInfo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("PrivateReadWrite")]
|
||||
[TestCase("PrivateReadPublicWrite")]
|
||||
[TestCase("PrivateReadOnly")]
|
||||
[TestCase("PublicWriteOnly")]
|
||||
[TestCase("PrivateWriteOnly")]
|
||||
public void GetGetMethod_NoAccessibleGetter(string name)
|
||||
{
|
||||
var propertyInfo = typeof(PropertyInfoExtensionsTest)
|
||||
.GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
Assert.IsNull(PropertyInfoExtensions.GetGetMethod(propertyInfo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("PublicReadWrite")]
|
||||
[TestCase("PrivateReadPublicWrite")]
|
||||
[TestCase("PublicWriteOnly")]
|
||||
public void GetSetMethod_Success(string name)
|
||||
{
|
||||
var propertyInfo = typeof(PropertyInfoExtensionsTest)
|
||||
.GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
Assert.IsNotNull(PropertyInfoExtensions.GetSetMethod(propertyInfo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("PublicReadPrivateWrite")]
|
||||
[TestCase("PrivateReadWrite")]
|
||||
[TestCase("PrivateReadOnly")]
|
||||
[TestCase("PublicReadOnly")]
|
||||
[TestCase("PrivateWriteOnly")]
|
||||
public void GetSetMethod_NoAccessibleGetter(string name)
|
||||
{
|
||||
var propertyInfo = typeof(PropertyInfoExtensionsTest)
|
||||
.GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
Assert.IsNull(PropertyInfoExtensions.GetSetMethod(propertyInfo));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Google.Protobuf.Compatibility
|
||||
{
|
||||
public class TypeExtensionsTest
|
||||
{
|
||||
public class DerivedList : List<string> { }
|
||||
public string PublicProperty { get; set; }
|
||||
private string PrivateProperty { get; set; }
|
||||
|
||||
public void PublicMethod()
|
||||
{
|
||||
}
|
||||
|
||||
private void PrivateMethod()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(int), true)]
|
||||
[TestCase(typeof(int?), true)]
|
||||
[TestCase(typeof(Nullable<>), true)]
|
||||
[TestCase(typeof(WireFormat.WireType), true)]
|
||||
[TestCase(typeof(string), false)]
|
||||
[TestCase(typeof(object), false)]
|
||||
[TestCase(typeof(Enum), false)]
|
||||
[TestCase(typeof(ValueType), false)]
|
||||
[TestCase(typeof(TypeExtensionsTest), false)]
|
||||
[TestCase(typeof(Action), false)]
|
||||
[TestCase(typeof(Action<>), false)]
|
||||
[TestCase(typeof(IDisposable), false)]
|
||||
public void IsValueType(Type type, bool expected)
|
||||
{
|
||||
Assert.AreEqual(expected, TypeExtensions.IsValueType(type));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(object), typeof(string), true)]
|
||||
[TestCase(typeof(object), typeof(int), true)]
|
||||
[TestCase(typeof(string), typeof(string), true)]
|
||||
[TestCase(typeof(string), typeof(object), false)]
|
||||
[TestCase(typeof(string), typeof(int), false)]
|
||||
[TestCase(typeof(int), typeof(int), true)]
|
||||
[TestCase(typeof(ValueType), typeof(int), true)]
|
||||
[TestCase(typeof(long), typeof(int), false)] //
|
||||
public void IsAssignableFrom(Type target, Type argument, bool expected)
|
||||
{
|
||||
Assert.AreEqual(expected, TypeExtensions.IsAssignableFrom(target, argument));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(DerivedList), "Count")] // Go up the type hierarchy
|
||||
[TestCase(typeof(List<string>), "Count")]
|
||||
[TestCase(typeof(List<>), "Count")]
|
||||
[TestCase(typeof(TypeExtensionsTest), "PublicProperty")]
|
||||
public void GetProperty_Success(Type type, string name)
|
||||
{
|
||||
var property = TypeExtensions.GetProperty(type, name);
|
||||
Assert.IsNotNull(property);
|
||||
Assert.AreEqual(name, property.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(TypeExtensionsTest), "PrivateProperty")]
|
||||
[TestCase(typeof(TypeExtensionsTest), "Garbage")]
|
||||
public void GetProperty_NoSuchProperty(Type type, string name)
|
||||
{
|
||||
var property = TypeExtensions.GetProperty(type, name);
|
||||
Assert.IsNull(property);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(DerivedList), "RemoveAt")] // Go up the type hierarchy
|
||||
[TestCase(typeof(List<>), "RemoveAt")]
|
||||
[TestCase(typeof(TypeExtensionsTest), "PublicMethod")]
|
||||
public void GetMethod_Success(Type type, string name)
|
||||
{
|
||||
var method = TypeExtensions.GetMethod(type, name);
|
||||
Assert.IsNotNull(method);
|
||||
Assert.AreEqual(name, method.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(TypeExtensionsTest), "PrivateMethod")]
|
||||
[TestCase(typeof(TypeExtensionsTest), "GarbageMethod")]
|
||||
public void GetMethod_NoSuchMethod(Type type, string name)
|
||||
{
|
||||
var method = TypeExtensions.GetMethod(type, name);
|
||||
Assert.IsNull(method);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(List<string>), "IndexOf")]
|
||||
public void GetMethod_Ambiguous(Type type, string name)
|
||||
{
|
||||
Assert.Throws<AmbiguousMatchException>(() => TypeExtensions.GetMethod(type, name));
|
||||
}
|
||||
}
|
||||
}
|
55
csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
Normal file
55
csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
Normal file
@ -0,0 +1,55 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
public class DeprecatedMemberTest
|
||||
{
|
||||
private static void AssertIsDeprecated(MemberInfo member)
|
||||
{
|
||||
Assert.NotNull(member);
|
||||
Assert.IsTrue(member.IsDefined(typeof(ObsoleteAttribute), false), "Member not obsolete: " + member);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDepreatedPrimitiveValue()
|
||||
{
|
||||
AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty("DeprecatedInt32"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
64
csharp/src/Google.Protobuf.Test/EqualityTester.cs
Normal file
64
csharp/src/Google.Protobuf.Test/EqualityTester.cs
Normal file
@ -0,0 +1,64 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper methods when testing equality. NUnit's Assert.AreEqual and
|
||||
/// Assert.AreNotEqual methods try to be clever with collections, which can
|
||||
/// be annoying...
|
||||
/// </summary>
|
||||
internal static class EqualityTester
|
||||
{
|
||||
public static void AssertEquality<T>(T first, T second) where T : IEquatable<T>
|
||||
{
|
||||
Assert.IsTrue(first.Equals(second));
|
||||
Assert.IsTrue(first.Equals((object) second));
|
||||
Assert.AreEqual(first.GetHashCode(), second.GetHashCode());
|
||||
}
|
||||
|
||||
public static void AssertInequality<T>(T first, T second) where T : IEquatable<T>
|
||||
{
|
||||
Assert.IsFalse(first.Equals(second));
|
||||
Assert.IsFalse(first.Equals((object) second));
|
||||
// While this isn't a requirement, the chances of this test failing due to
|
||||
// coincidence rather than a bug are very small.
|
||||
if (first != null && second != null)
|
||||
{
|
||||
Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
193
csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
Normal file
193
csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
Normal file
@ -0,0 +1,193 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
public class FieldCodecTest
|
||||
{
|
||||
private static readonly List<ICodecTestData> Codecs = new List<ICodecTestData>
|
||||
{
|
||||
new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "Bool"),
|
||||
new FieldCodecTestData<string>(FieldCodec.ForString(100), "sample", "String"),
|
||||
new FieldCodecTestData<ByteString>(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"),
|
||||
new FieldCodecTestData<int>(FieldCodec.ForInt32(100), -1000, "Int32"),
|
||||
new FieldCodecTestData<int>(FieldCodec.ForSInt32(100), -1000, "SInt32"),
|
||||
new FieldCodecTestData<int>(FieldCodec.ForSFixed32(100), -1000, "SFixed32"),
|
||||
new FieldCodecTestData<uint>(FieldCodec.ForUInt32(100), 1234, "UInt32"),
|
||||
new FieldCodecTestData<uint>(FieldCodec.ForFixed32(100), 1234, "Fixed32"),
|
||||
new FieldCodecTestData<long>(FieldCodec.ForInt64(100), -1000, "Int64"),
|
||||
new FieldCodecTestData<long>(FieldCodec.ForSInt64(100), -1000, "SInt64"),
|
||||
new FieldCodecTestData<long>(FieldCodec.ForSFixed64(100), -1000, "SFixed64"),
|
||||
new FieldCodecTestData<ulong>(FieldCodec.ForUInt64(100), 1234, "UInt64"),
|
||||
new FieldCodecTestData<ulong>(FieldCodec.ForFixed64(100), 1234, "Fixed64"),
|
||||
new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "Float"),
|
||||
new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "Double"),
|
||||
new FieldCodecTestData<ForeignEnum>(
|
||||
FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.FOREIGN_BAZ, "Enum"),
|
||||
new FieldCodecTestData<ForeignMessage>(
|
||||
FieldCodec.ForMessage(100, ForeignMessage.Parser), new ForeignMessage { C = 10 }, "Message"),
|
||||
};
|
||||
|
||||
[Test, TestCaseSource("Codecs")]
|
||||
public void RoundTripWithTag(ICodecTestData codec)
|
||||
{
|
||||
codec.TestRoundTripWithTag();
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Codecs")]
|
||||
public void RoundTripRaw(ICodecTestData codec)
|
||||
{
|
||||
codec.TestRoundTripRaw();
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Codecs")]
|
||||
public void CalculateSize(ICodecTestData codec)
|
||||
{
|
||||
codec.TestCalculateSizeWithTag();
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Codecs")]
|
||||
public void DefaultValue(ICodecTestData codec)
|
||||
{
|
||||
codec.TestDefaultValue();
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Codecs")]
|
||||
public void FixedSize(ICodecTestData codec)
|
||||
{
|
||||
codec.TestFixedSize();
|
||||
}
|
||||
|
||||
// This is ugly, but it means we can have a non-generic interface.
|
||||
// It feels like NUnit should support this better, but I don't know
|
||||
// of any better ways right now.
|
||||
public interface ICodecTestData
|
||||
{
|
||||
void TestRoundTripRaw();
|
||||
void TestRoundTripWithTag();
|
||||
void TestCalculateSizeWithTag();
|
||||
void TestDefaultValue();
|
||||
void TestFixedSize();
|
||||
}
|
||||
|
||||
public class FieldCodecTestData<T> : ICodecTestData
|
||||
{
|
||||
private readonly FieldCodec<T> codec;
|
||||
private readonly T sampleValue;
|
||||
private readonly string name;
|
||||
|
||||
public FieldCodecTestData(FieldCodec<T> codec, T sampleValue, string name)
|
||||
{
|
||||
this.codec = codec;
|
||||
this.sampleValue = sampleValue;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void TestRoundTripRaw()
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
var codedOutput = new CodedOutputStream(stream);
|
||||
codec.ValueWriter(codedOutput, sampleValue);
|
||||
codedOutput.Flush();
|
||||
stream.Position = 0;
|
||||
var codedInput = new CodedInputStream(stream);
|
||||
Assert.AreEqual(sampleValue, codec.ValueReader(codedInput));
|
||||
Assert.IsTrue(codedInput.IsAtEnd);
|
||||
}
|
||||
|
||||
public void TestRoundTripWithTag()
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
var codedOutput = new CodedOutputStream(stream);
|
||||
codec.WriteTagAndValue(codedOutput, sampleValue);
|
||||
codedOutput.Flush();
|
||||
stream.Position = 0;
|
||||
var codedInput = new CodedInputStream(stream);
|
||||
codedInput.AssertNextTag(codec.Tag);
|
||||
Assert.AreEqual(sampleValue, codec.Read(codedInput));
|
||||
Assert.IsTrue(codedInput.IsAtEnd);
|
||||
}
|
||||
|
||||
public void TestCalculateSizeWithTag()
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
var codedOutput = new CodedOutputStream(stream);
|
||||
codec.WriteTagAndValue(codedOutput, sampleValue);
|
||||
codedOutput.Flush();
|
||||
Assert.AreEqual(stream.Position, codec.CalculateSizeWithTag(sampleValue));
|
||||
}
|
||||
|
||||
public void TestDefaultValue()
|
||||
{
|
||||
// WriteTagAndValue ignores default values
|
||||
var stream = new MemoryStream();
|
||||
var codedOutput = new CodedOutputStream(stream);
|
||||
codec.WriteTagAndValue(codedOutput, codec.DefaultValue);
|
||||
codedOutput.Flush();
|
||||
Assert.AreEqual(0, stream.Position);
|
||||
Assert.AreEqual(0, codec.CalculateSizeWithTag(codec.DefaultValue));
|
||||
if (typeof(T).IsValueType)
|
||||
{
|
||||
Assert.AreEqual(default(T), codec.DefaultValue);
|
||||
}
|
||||
|
||||
// The plain ValueWriter/ValueReader delegates don't.
|
||||
if (codec.DefaultValue != null) // This part isn't appropriate for message types.
|
||||
{
|
||||
codedOutput = new CodedOutputStream(stream);
|
||||
codec.ValueWriter(codedOutput, codec.DefaultValue);
|
||||
codedOutput.Flush();
|
||||
Assert.AreNotEqual(0, stream.Position);
|
||||
Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
|
||||
stream.Position = 0;
|
||||
var codedInput = new CodedInputStream(stream);
|
||||
Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput));
|
||||
}
|
||||
}
|
||||
|
||||
public void TestFixedSize()
|
||||
{
|
||||
Assert.AreEqual(name.Contains("Fixed"), codec.FixedSize != 0);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
594
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
Normal file
594
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
Normal file
@ -0,0 +1,594 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests around the generated TestAllTypes message.
|
||||
/// </summary>
|
||||
public class GeneratedMessageTest
|
||||
{
|
||||
[Test]
|
||||
public void EmptyMessageFieldDistinctFromMissingMessageField()
|
||||
{
|
||||
// This demonstrates what we're really interested in...
|
||||
var message1 = new TestAllTypes { SingleForeignMessage = new ForeignMessage() };
|
||||
var message2 = new TestAllTypes(); // SingleForeignMessage is null
|
||||
EqualityTester.AssertInequality(message1, message2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultValues()
|
||||
{
|
||||
// Single fields
|
||||
var message = new TestAllTypes();
|
||||
Assert.AreEqual(false, message.SingleBool);
|
||||
Assert.AreEqual(ByteString.Empty, message.SingleBytes);
|
||||
Assert.AreEqual(0.0, message.SingleDouble);
|
||||
Assert.AreEqual(0, message.SingleFixed32);
|
||||
Assert.AreEqual(0L, message.SingleFixed64);
|
||||
Assert.AreEqual(0.0f, message.SingleFloat);
|
||||
Assert.AreEqual(ForeignEnum.FOREIGN_UNSPECIFIED, message.SingleForeignEnum);
|
||||
Assert.IsNull(message.SingleForeignMessage);
|
||||
Assert.AreEqual(ImportEnum.IMPORT_ENUM_UNSPECIFIED, message.SingleImportEnum);
|
||||
Assert.IsNull(message.SingleImportMessage);
|
||||
Assert.AreEqual(0, message.SingleInt32);
|
||||
Assert.AreEqual(0L, message.SingleInt64);
|
||||
Assert.AreEqual(TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED, message.SingleNestedEnum);
|
||||
Assert.IsNull(message.SingleNestedMessage);
|
||||
Assert.IsNull(message.SinglePublicImportMessage);
|
||||
Assert.AreEqual(0, message.SingleSfixed32);
|
||||
Assert.AreEqual(0L, message.SingleSfixed64);
|
||||
Assert.AreEqual(0, message.SingleSint32);
|
||||
Assert.AreEqual(0L, message.SingleSint64);
|
||||
Assert.AreEqual("", message.SingleString);
|
||||
Assert.AreEqual(0U, message.SingleUint32);
|
||||
Assert.AreEqual(0UL, message.SingleUint64);
|
||||
|
||||
// Repeated fields
|
||||
Assert.AreEqual(0, message.RepeatedBool.Count);
|
||||
Assert.AreEqual(0, message.RepeatedBytes.Count);
|
||||
Assert.AreEqual(0, message.RepeatedDouble.Count);
|
||||
Assert.AreEqual(0, message.RepeatedFixed32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedFixed64.Count);
|
||||
Assert.AreEqual(0, message.RepeatedFloat.Count);
|
||||
Assert.AreEqual(0, message.RepeatedForeignEnum.Count);
|
||||
Assert.AreEqual(0, message.RepeatedForeignMessage.Count);
|
||||
Assert.AreEqual(0, message.RepeatedImportEnum.Count);
|
||||
Assert.AreEqual(0, message.RepeatedImportMessage.Count);
|
||||
Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
|
||||
Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
|
||||
Assert.AreEqual(0, message.RepeatedPublicImportMessage.Count);
|
||||
Assert.AreEqual(0, message.RepeatedSfixed32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedSfixed64.Count);
|
||||
Assert.AreEqual(0, message.RepeatedSint32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedSint64.Count);
|
||||
Assert.AreEqual(0, message.RepeatedString.Count);
|
||||
Assert.AreEqual(0, message.RepeatedUint32.Count);
|
||||
Assert.AreEqual(0, message.RepeatedUint64.Count);
|
||||
|
||||
// Oneof fields
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
|
||||
Assert.AreEqual(0, message.OneofUint32);
|
||||
Assert.AreEqual("", message.OneofString);
|
||||
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
|
||||
Assert.IsNull(message.OneofNestedMessage);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NullStringAndBytesRejected()
|
||||
{
|
||||
var message = new TestAllTypes();
|
||||
Assert.Throws<ArgumentNullException>(() => message.SingleString = null);
|
||||
Assert.Throws<ArgumentNullException>(() => message.OneofString = null);
|
||||
Assert.Throws<ArgumentNullException>(() => message.SingleBytes = null);
|
||||
Assert.Throws<ArgumentNullException>(() => message.OneofBytes = null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RoundTrip_Empty()
|
||||
{
|
||||
var message = new TestAllTypes();
|
||||
// Without setting any values, there's nothing to write.
|
||||
byte[] bytes = message.ToByteArray();
|
||||
Assert.AreEqual(0, bytes.Length);
|
||||
TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(message, parsed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RoundTrip_SingleValues()
|
||||
{
|
||||
var message = new TestAllTypes
|
||||
{
|
||||
SingleBool = true,
|
||||
SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
|
||||
SingleDouble = 23.5,
|
||||
SingleFixed32 = 23,
|
||||
SingleFixed64 = 1234567890123,
|
||||
SingleFloat = 12.25f,
|
||||
SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
|
||||
SingleForeignMessage = new ForeignMessage { C = 10 },
|
||||
SingleImportEnum = ImportEnum.IMPORT_BAZ,
|
||||
SingleImportMessage = new ImportMessage { D = 20 },
|
||||
SingleInt32 = 100,
|
||||
SingleInt64 = 3210987654321,
|
||||
SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
|
||||
SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
|
||||
SinglePublicImportMessage = new PublicImportMessage { E = 54 },
|
||||
SingleSfixed32 = -123,
|
||||
SingleSfixed64 = -12345678901234,
|
||||
SingleSint32 = -456,
|
||||
SingleSint64 = -12345678901235,
|
||||
SingleString = "test",
|
||||
SingleUint32 = uint.MaxValue,
|
||||
SingleUint64 = ulong.MaxValue
|
||||
};
|
||||
|
||||
byte[] bytes = message.ToByteArray();
|
||||
TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(message, parsed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RoundTrip_RepeatedValues()
|
||||
{
|
||||
var message = new TestAllTypes
|
||||
{
|
||||
RepeatedBool = { true, false },
|
||||
RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
|
||||
RepeatedDouble = { -12.25, 23.5 },
|
||||
RepeatedFixed32 = { uint.MaxValue, 23 },
|
||||
RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
|
||||
RepeatedFloat = { 100f, 12.25f },
|
||||
RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR },
|
||||
RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
|
||||
RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED },
|
||||
RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
|
||||
RepeatedInt32 = { 100, 200 },
|
||||
RepeatedInt64 = { 3210987654321, long.MaxValue },
|
||||
RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
|
||||
RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
|
||||
RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
|
||||
RepeatedSfixed32 = { -123, 123 },
|
||||
RepeatedSfixed64 = { -12345678901234, 12345678901234 },
|
||||
RepeatedSint32 = { -456, 100 },
|
||||
RepeatedSint64 = { -12345678901235, 123 },
|
||||
RepeatedString = { "foo", "bar" },
|
||||
RepeatedUint32 = { uint.MaxValue, uint.MinValue },
|
||||
RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
|
||||
};
|
||||
|
||||
byte[] bytes = message.ToByteArray();
|
||||
TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(message, parsed);
|
||||
}
|
||||
|
||||
// Note that not every map within map_unittest_proto3 is used. They all go through very
|
||||
// similar code paths. The fact that all maps are present is validation that we have codecs
|
||||
// for every type.
|
||||
[Test]
|
||||
public void RoundTrip_Maps()
|
||||
{
|
||||
var message = new TestMap
|
||||
{
|
||||
MapBoolBool = {
|
||||
{ false, true },
|
||||
{ true, false }
|
||||
},
|
||||
MapInt32Bytes = {
|
||||
{ 5, ByteString.CopyFrom(6, 7, 8) },
|
||||
{ 25, ByteString.CopyFrom(1, 2, 3, 4, 5) },
|
||||
{ 10, ByteString.Empty }
|
||||
},
|
||||
MapInt32ForeignMessage = {
|
||||
{ 0, new ForeignMessage { C = 10 } },
|
||||
{ 5, null },
|
||||
},
|
||||
MapInt32Enum = {
|
||||
{ 1, MapEnum.MAP_ENUM_BAR },
|
||||
{ 2000, MapEnum.MAP_ENUM_FOO }
|
||||
}
|
||||
};
|
||||
|
||||
byte[] bytes = message.ToByteArray();
|
||||
TestMap parsed = TestMap.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(message, parsed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapWithEmptyEntry()
|
||||
{
|
||||
var message = new TestMap
|
||||
{
|
||||
MapInt32Bytes = { { 0, ByteString.Empty } }
|
||||
};
|
||||
|
||||
byte[] bytes = message.ToByteArray();
|
||||
Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte)
|
||||
|
||||
var parsed = TestMap.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(1, parsed.MapInt32Bytes.Count);
|
||||
Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapWithOnlyValue()
|
||||
{
|
||||
// Hand-craft the stream to contain a single entry with just a value.
|
||||
var memoryStream = new MemoryStream();
|
||||
var output = new CodedOutputStream(memoryStream);
|
||||
output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
var nestedMessage = new ForeignMessage { C = 20 };
|
||||
// Size of the entry (tag, size written by WriteMessage, data written by WriteMessage)
|
||||
output.WriteRawVarint32((uint)(nestedMessage.CalculateSize() + 3));
|
||||
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteMessage(nestedMessage);
|
||||
output.Flush();
|
||||
|
||||
var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
|
||||
Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapIgnoresExtraFieldsWithinEntryMessages()
|
||||
{
|
||||
// Hand-craft the stream to contain a single entry with three fields
|
||||
var memoryStream = new MemoryStream();
|
||||
var output = new CodedOutputStream(memoryStream);
|
||||
|
||||
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
|
||||
var key = 10; // Field 1
|
||||
var value = 20; // Field 2
|
||||
var extra = 30; // Field 3
|
||||
|
||||
// Each field can be represented in a single byte, with a single byte tag.
|
||||
// Total message size: 6 bytes.
|
||||
output.WriteRawVarint32(6);
|
||||
output.WriteTag(1, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(key);
|
||||
output.WriteTag(2, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(value);
|
||||
output.WriteTag(3, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(extra);
|
||||
output.Flush();
|
||||
|
||||
var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
|
||||
Assert.AreEqual(value, parsed.MapInt32Int32[key]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapFieldOrderIsIrrelevant()
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
var output = new CodedOutputStream(memoryStream);
|
||||
|
||||
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
|
||||
var key = 10;
|
||||
var value = 20;
|
||||
|
||||
// Each field can be represented in a single byte, with a single byte tag.
|
||||
// Total message size: 4 bytes.
|
||||
output.WriteRawVarint32(4);
|
||||
output.WriteTag(2, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(value);
|
||||
output.WriteTag(1, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(key);
|
||||
output.Flush();
|
||||
|
||||
var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
|
||||
Assert.AreEqual(value, parsed.MapInt32Int32[key]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapNonContiguousEntries()
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
var output = new CodedOutputStream(memoryStream);
|
||||
|
||||
// Message structure:
|
||||
// Entry for MapInt32Int32
|
||||
// Entry for MapStringString
|
||||
// Entry for MapInt32Int32
|
||||
|
||||
// First entry
|
||||
var key1 = 10;
|
||||
var value1 = 20;
|
||||
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteRawVarint32(4);
|
||||
output.WriteTag(1, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(key1);
|
||||
output.WriteTag(2, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(value1);
|
||||
|
||||
// Second entry
|
||||
var key2 = "a";
|
||||
var value2 = "b";
|
||||
output.WriteTag(TestMap.MapStringStringFieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteRawVarint32(6); // 3 bytes per entry: tag, size, character
|
||||
output.WriteTag(1, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteString(key2);
|
||||
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteString(value2);
|
||||
|
||||
// Third entry
|
||||
var key3 = 15;
|
||||
var value3 = 25;
|
||||
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteRawVarint32(4);
|
||||
output.WriteTag(1, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(key3);
|
||||
output.WriteTag(2, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(value3);
|
||||
|
||||
output.Flush();
|
||||
var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
|
||||
var expected = new TestMap
|
||||
{
|
||||
MapInt32Int32 = { { key1, value1 }, { key3, value3 } },
|
||||
MapStringString = { { key2, value2 } }
|
||||
};
|
||||
Assert.AreEqual(expected, parsed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DuplicateKeys_LastEntryWins()
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
var output = new CodedOutputStream(memoryStream);
|
||||
|
||||
var key = 10;
|
||||
var value1 = 20;
|
||||
var value2 = 30;
|
||||
|
||||
// First entry
|
||||
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteRawVarint32(4);
|
||||
output.WriteTag(1, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(key);
|
||||
output.WriteTag(2, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(value1);
|
||||
|
||||
// Second entry - same key, different value
|
||||
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
output.WriteRawVarint32(4);
|
||||
output.WriteTag(1, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(key);
|
||||
output.WriteTag(2, WireFormat.WireType.Varint);
|
||||
output.WriteInt32(value2);
|
||||
output.Flush();
|
||||
|
||||
var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
|
||||
Assert.AreEqual(value2, parsed.MapInt32Int32[key]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloneSingleNonMessageValues()
|
||||
{
|
||||
var original = new TestAllTypes
|
||||
{
|
||||
SingleBool = true,
|
||||
SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
|
||||
SingleDouble = 23.5,
|
||||
SingleFixed32 = 23,
|
||||
SingleFixed64 = 1234567890123,
|
||||
SingleFloat = 12.25f,
|
||||
SingleInt32 = 100,
|
||||
SingleInt64 = 3210987654321,
|
||||
SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
|
||||
SingleSfixed32 = -123,
|
||||
SingleSfixed64 = -12345678901234,
|
||||
SingleSint32 = -456,
|
||||
SingleSint64 = -12345678901235,
|
||||
SingleString = "test",
|
||||
SingleUint32 = uint.MaxValue,
|
||||
SingleUint64 = ulong.MaxValue
|
||||
};
|
||||
var clone = original.Clone();
|
||||
Assert.AreNotSame(original, clone);
|
||||
Assert.AreEqual(original, clone);
|
||||
// Just as a single example
|
||||
clone.SingleInt32 = 150;
|
||||
Assert.AreNotEqual(original, clone);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloneRepeatedNonMessageValues()
|
||||
{
|
||||
var original = new TestAllTypes
|
||||
{
|
||||
RepeatedBool = { true, false },
|
||||
RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
|
||||
RepeatedDouble = { -12.25, 23.5 },
|
||||
RepeatedFixed32 = { uint.MaxValue, 23 },
|
||||
RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
|
||||
RepeatedFloat = { 100f, 12.25f },
|
||||
RepeatedInt32 = { 100, 200 },
|
||||
RepeatedInt64 = { 3210987654321, long.MaxValue },
|
||||
RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
|
||||
RepeatedSfixed32 = { -123, 123 },
|
||||
RepeatedSfixed64 = { -12345678901234, 12345678901234 },
|
||||
RepeatedSint32 = { -456, 100 },
|
||||
RepeatedSint64 = { -12345678901235, 123 },
|
||||
RepeatedString = { "foo", "bar" },
|
||||
RepeatedUint32 = { uint.MaxValue, uint.MinValue },
|
||||
RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
|
||||
};
|
||||
|
||||
var clone = original.Clone();
|
||||
Assert.AreNotSame(original, clone);
|
||||
Assert.AreEqual(original, clone);
|
||||
// Just as a single example
|
||||
clone.RepeatedDouble.Add(25.5);
|
||||
Assert.AreNotEqual(original, clone);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloneSingleMessageField()
|
||||
{
|
||||
var original = new TestAllTypes
|
||||
{
|
||||
SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
|
||||
};
|
||||
|
||||
var clone = original.Clone();
|
||||
Assert.AreNotSame(original, clone);
|
||||
Assert.AreNotSame(original.SingleNestedMessage, clone.SingleNestedMessage);
|
||||
Assert.AreEqual(original, clone);
|
||||
|
||||
clone.SingleNestedMessage.Bb = 30;
|
||||
Assert.AreNotEqual(original, clone);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloneRepeatedMessageField()
|
||||
{
|
||||
var original = new TestAllTypes
|
||||
{
|
||||
RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 20 } }
|
||||
};
|
||||
|
||||
var clone = original.Clone();
|
||||
Assert.AreNotSame(original, clone);
|
||||
Assert.AreNotSame(original.RepeatedNestedMessage, clone.RepeatedNestedMessage);
|
||||
Assert.AreNotSame(original.RepeatedNestedMessage[0], clone.RepeatedNestedMessage[0]);
|
||||
Assert.AreEqual(original, clone);
|
||||
|
||||
clone.RepeatedNestedMessage[0].Bb = 30;
|
||||
Assert.AreNotEqual(original, clone);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CloneOneofField()
|
||||
{
|
||||
var original = new TestAllTypes
|
||||
{
|
||||
OneofNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
|
||||
};
|
||||
|
||||
var clone = original.Clone();
|
||||
Assert.AreNotSame(original, clone);
|
||||
Assert.AreEqual(original, clone);
|
||||
|
||||
// We should have cloned the message
|
||||
original.OneofNestedMessage.Bb = 30;
|
||||
Assert.AreNotEqual(original, clone);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OneofProperties()
|
||||
{
|
||||
// Switch the oneof case between each of the different options, and check everything behaves
|
||||
// as expected in each case.
|
||||
var message = new TestAllTypes();
|
||||
Assert.AreEqual("", message.OneofString);
|
||||
Assert.AreEqual(0, message.OneofUint32);
|
||||
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
|
||||
Assert.IsNull(message.OneofNestedMessage);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
|
||||
|
||||
message.OneofString = "sample";
|
||||
Assert.AreEqual("sample", message.OneofString);
|
||||
Assert.AreEqual(0, message.OneofUint32);
|
||||
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
|
||||
Assert.IsNull(message.OneofNestedMessage);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
|
||||
|
||||
var bytes = ByteString.CopyFrom(1, 2, 3);
|
||||
message.OneofBytes = bytes;
|
||||
Assert.AreEqual("", message.OneofString);
|
||||
Assert.AreEqual(0, message.OneofUint32);
|
||||
Assert.AreEqual(bytes, message.OneofBytes);
|
||||
Assert.IsNull(message.OneofNestedMessage);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofBytes, message.OneofFieldCase);
|
||||
|
||||
message.OneofUint32 = 20;
|
||||
Assert.AreEqual("", message.OneofString);
|
||||
Assert.AreEqual(20, message.OneofUint32);
|
||||
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
|
||||
Assert.IsNull(message.OneofNestedMessage);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
|
||||
|
||||
var nestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 25 };
|
||||
message.OneofNestedMessage = nestedMessage;
|
||||
Assert.AreEqual("", message.OneofString);
|
||||
Assert.AreEqual(0, message.OneofUint32);
|
||||
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
|
||||
Assert.AreEqual(nestedMessage, message.OneofNestedMessage);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofNestedMessage, message.OneofFieldCase);
|
||||
|
||||
message.ClearOneofField();
|
||||
Assert.AreEqual("", message.OneofString);
|
||||
Assert.AreEqual(0, message.OneofUint32);
|
||||
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
|
||||
Assert.IsNull(message.OneofNestedMessage);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OneofSerialization_NonDefaultValue()
|
||||
{
|
||||
var message = new TestAllTypes();
|
||||
message.OneofString = "this would take a bit of space";
|
||||
message.OneofUint32 = 10;
|
||||
var bytes = message.ToByteArray();
|
||||
Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!
|
||||
|
||||
var message2 = TestAllTypes.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(message, message2);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OneofSerialization_DefaultValue()
|
||||
{
|
||||
var message = new TestAllTypes();
|
||||
message.OneofString = "this would take a bit of space";
|
||||
message.OneofUint32 = 0; // This is the default value for UInt32; normally wouldn't be serialized
|
||||
var bytes = message.ToByteArray();
|
||||
Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized
|
||||
|
||||
var message2 = TestAllTypes.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(message, message2);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,15 +5,13 @@
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{EE01ED24-3750-4567-9A23-1DB676A15610}</ProjectGuid>
|
||||
<ProjectGuid>{DD01ED24-3750-4567-9A23-1DB676A15610}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.ProtocolBuffers</RootNamespace>
|
||||
<AssemblyName>Google.ProtocolBuffersLite.Test</AssemblyName>
|
||||
<RootNamespace>Google.Protobuf</RootNamespace>
|
||||
<AssemblyName>Google.Protobuf.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>..\..\keys\Google.ProtocolBuffers.snk</AssemblyOriginatorKeyFile>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
@ -45,6 +43,20 @@
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\ReleaseSigned</OutputPath>
|
||||
<IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
|
||||
<DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<SignAssembly>True</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
@ -71,37 +83,49 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\ProtocolBuffers.Test\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AbstractBuilderLiteTest.cs" />
|
||||
<Compile Include="AbstractMessageLiteTest.cs" />
|
||||
<Compile Include="ExtendableBuilderLiteTest.cs" />
|
||||
<Compile Include="ExtendableMessageLiteTest.cs" />
|
||||
<Compile Include="LiteTest.cs" />
|
||||
<Compile Include="TestLiteByApi.cs" />
|
||||
<Compile Include="TestProtos\UnittestExtrasLite.cs" />
|
||||
<Compile Include="TestProtos\UnittestImportLite.cs" />
|
||||
<Compile Include="TestProtos\UnittestImportPublicLite.cs" />
|
||||
<Compile Include="TestProtos\UnittestLite.cs" />
|
||||
<Compile Include="ByteStringTest.cs" />
|
||||
<Compile Include="CodedInputStreamExtensions.cs" />
|
||||
<Compile Include="CodedInputStreamTest.cs" />
|
||||
<Compile Include="CodedOutputStreamTest.cs" />
|
||||
<Compile Include="Compatibility\PropertyInfoExtensionsTest.cs" />
|
||||
<Compile Include="Compatibility\TypeExtensionsTest.cs" />
|
||||
<Compile Include="EqualityTester.cs" />
|
||||
<Compile Include="FieldCodecTest.cs" />
|
||||
<Compile Include="GeneratedMessageTest.cs" />
|
||||
<Compile Include="Collections\MapFieldTest.cs" />
|
||||
<Compile Include="Collections\RepeatedFieldTest.cs" />
|
||||
<Compile Include="JsonFormatterTest.cs" />
|
||||
<Compile Include="Reflection\DescriptorsTest.cs" />
|
||||
<Compile Include="Reflection\FieldAccessTest.cs" />
|
||||
<Compile Include="SampleEnum.cs" />
|
||||
<Compile Include="SampleMessages.cs" />
|
||||
<Compile Include="TestProtos\MapUnittestProto3.cs" />
|
||||
<Compile Include="TestProtos\UnittestImportProto3.cs" />
|
||||
<Compile Include="TestProtos\UnittestImportPublicProto3.cs" />
|
||||
<Compile Include="TestProtos\UnittestIssues.cs" />
|
||||
<Compile Include="TestProtos\UnittestProto3.cs" />
|
||||
<Compile Include="DeprecatedMemberTest.cs" />
|
||||
<Compile Include="IssuesTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TestCornerCases.cs" />
|
||||
<Compile Include="TestProtos\UnittestWellKnownTypes.cs" />
|
||||
<Compile Include="WellKnownTypes\DurationTest.cs" />
|
||||
<Compile Include="WellKnownTypes\TimestampTest.cs" />
|
||||
<Compile Include="WellKnownTypes\WrappersTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ProtocolBuffers.Serialization\ProtocolBuffersLite.Serialization.csproj">
|
||||
<Project>{E067A59D-9D0A-4A1F-92B1-38E4457241D1}</Project>
|
||||
<Name>ProtocolBuffersLite.Serialization</Name>
|
||||
<ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
|
||||
<Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
|
||||
<Name>Google.Protobuf</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffersLite.csproj">
|
||||
<Project>{6969BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
|
||||
<Name>ProtocolBuffersLite</Name>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<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.
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,16 +28,14 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
using Google.ProtocolBuffers.Descriptors;
|
||||
using Google.Protobuf.Reflection;
|
||||
using UnitTest.Issues.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for issues which aren't easily compartmentalized into other unit tests.
|
||||
@ -51,10 +46,19 @@ namespace Google.ProtocolBuffers
|
||||
[Test]
|
||||
public void FieldCalledItem()
|
||||
{
|
||||
ItemField message = new ItemField.Builder { Item = 3 }.Build();
|
||||
ItemField message = new ItemField { Item = 3 };
|
||||
FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
|
||||
Assert.NotNull(field);
|
||||
Assert.AreEqual(3, (int)message[field]);
|
||||
// TODO(jonskeet): Reflection...
|
||||
// Assert.AreEqual(3, (int)message[field]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReservedNames()
|
||||
{
|
||||
var message = new ReservedNames { Types_ = 10, Descriptor_ = 20 };
|
||||
// Underscores aren't reflected in the JSON.
|
||||
Assert.AreEqual("{ \"types\": 10, \"descriptor\": 20 }", message.ToString());
|
||||
}
|
||||
}
|
||||
}
|
420
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
Normal file
420
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
Normal file
@ -0,0 +1,420 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
using UnitTest.Issues.TestProtos;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for the JSON formatter. Note that in these tests, double quotes are replaced with apostrophes
|
||||
/// for the sake of readability (embedding \" everywhere is painful). See the AssertJson method for details.
|
||||
/// </summary>
|
||||
public class JsonFormatterTest
|
||||
{
|
||||
[Test]
|
||||
public void DefaultValues_WhenOmitted()
|
||||
{
|
||||
var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: false));
|
||||
|
||||
AssertJson("{ }", formatter.Format(new ForeignMessage()));
|
||||
AssertJson("{ }", formatter.Format(new TestAllTypes()));
|
||||
AssertJson("{ }", formatter.Format(new TestMap()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultValues_WhenIncluded()
|
||||
{
|
||||
var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: true));
|
||||
AssertJson("{ 'c': 0 }", formatter.Format(new ForeignMessage()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllSingleFields()
|
||||
{
|
||||
var message = new TestAllTypes
|
||||
{
|
||||
SingleBool = true,
|
||||
SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
|
||||
SingleDouble = 23.5,
|
||||
SingleFixed32 = 23,
|
||||
SingleFixed64 = 1234567890123,
|
||||
SingleFloat = 12.25f,
|
||||
SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
|
||||
SingleForeignMessage = new ForeignMessage { C = 10 },
|
||||
SingleImportEnum = ImportEnum.IMPORT_BAZ,
|
||||
SingleImportMessage = new ImportMessage { D = 20 },
|
||||
SingleInt32 = 100,
|
||||
SingleInt64 = 3210987654321,
|
||||
SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
|
||||
SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
|
||||
SinglePublicImportMessage = new PublicImportMessage { E = 54 },
|
||||
SingleSfixed32 = -123,
|
||||
SingleSfixed64 = -12345678901234,
|
||||
SingleSint32 = -456,
|
||||
SingleSint64 = -12345678901235,
|
||||
SingleString = "test\twith\ttabs",
|
||||
SingleUint32 = uint.MaxValue,
|
||||
SingleUint64 = ulong.MaxValue,
|
||||
};
|
||||
var actualText = JsonFormatter.Default.Format(message);
|
||||
|
||||
// Fields in numeric order
|
||||
var expectedText = "{ " +
|
||||
"'singleInt32': 100, " +
|
||||
"'singleInt64': '3210987654321', " +
|
||||
"'singleUint32': 4294967295, " +
|
||||
"'singleUint64': '18446744073709551615', " +
|
||||
"'singleSint32': -456, " +
|
||||
"'singleSint64': '-12345678901235', " +
|
||||
"'singleFixed32': 23, " +
|
||||
"'singleFixed64': '1234567890123', " +
|
||||
"'singleSfixed32': -123, " +
|
||||
"'singleSfixed64': '-12345678901234', " +
|
||||
"'singleFloat': 12.25, " +
|
||||
"'singleDouble': 23.5, " +
|
||||
"'singleBool': true, " +
|
||||
"'singleString': 'test\\twith\\ttabs', " +
|
||||
"'singleBytes': 'AQIDBA==', " +
|
||||
"'singleNestedMessage': { 'bb': 35 }, " +
|
||||
"'singleForeignMessage': { 'c': 10 }, " +
|
||||
"'singleImportMessage': { 'd': 20 }, " +
|
||||
"'singleNestedEnum': 'FOO', " +
|
||||
"'singleForeignEnum': 'FOREIGN_BAR', " +
|
||||
"'singleImportEnum': 'IMPORT_BAZ', " +
|
||||
"'singlePublicImportMessage': { 'e': 54 }" +
|
||||
" }";
|
||||
AssertJson(expectedText, actualText);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RepeatedField()
|
||||
{
|
||||
AssertJson("{ 'repeatedInt32': [ 1, 2, 3, 4, 5 ] }",
|
||||
JsonFormatter.Default.Format(new TestAllTypes { RepeatedInt32 = { 1, 2, 3, 4, 5 } }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapField_StringString()
|
||||
{
|
||||
AssertJson("{ 'mapStringString': { 'with spaces': 'bar', 'a': 'b' } }",
|
||||
JsonFormatter.Default.Format(new TestMap { MapStringString = { { "with spaces", "bar" }, { "a", "b" } } }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapField_Int32Int32()
|
||||
{
|
||||
// The keys are quoted, but the values aren't.
|
||||
AssertJson("{ 'mapInt32Int32': { '0': 1, '2': 3 } }",
|
||||
JsonFormatter.Default.Format(new TestMap { MapInt32Int32 = { { 0, 1 }, { 2, 3 } } }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapField_BoolBool()
|
||||
{
|
||||
// The keys are quoted, but the values aren't.
|
||||
AssertJson("{ 'mapBoolBool': { 'false': true, 'true': false } }",
|
||||
JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } }));
|
||||
}
|
||||
|
||||
[TestCase(1.0, "1")]
|
||||
[TestCase(double.NaN, "'NaN'")]
|
||||
[TestCase(double.PositiveInfinity, "'Infinity'")]
|
||||
[TestCase(double.NegativeInfinity, "'-Infinity'")]
|
||||
public void DoubleRepresentations(double value, string expectedValueText)
|
||||
{
|
||||
var message = new TestAllTypes { SingleDouble = value };
|
||||
string actualText = JsonFormatter.Default.Format(message);
|
||||
string expectedText = "{ 'singleDouble': " + expectedValueText + " }";
|
||||
AssertJson(expectedText, actualText);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnknownEnumValueOmitted_SingleField()
|
||||
{
|
||||
var message = new TestAllTypes { SingleForeignEnum = (ForeignEnum) 100 };
|
||||
AssertJson("{ }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnknownEnumValueOmitted_RepeatedField()
|
||||
{
|
||||
var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.FOREIGN_BAZ, (ForeignEnum) 100, ForeignEnum.FOREIGN_FOO } };
|
||||
AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnknownEnumValueOmitted_MapField()
|
||||
{
|
||||
// This matches the C++ behaviour.
|
||||
var message = new TestMap { MapInt32Enum = { { 1, MapEnum.MAP_ENUM_FOO }, { 2, (MapEnum) 100 }, { 3, MapEnum.MAP_ENUM_BAR } } };
|
||||
AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnknownEnumValueOmitted_RepeatedField_AllEntriesUnknown()
|
||||
{
|
||||
// *Maybe* we should hold off on writing the "[" until we find that we've got at least one value to write...
|
||||
// but this is what happens at the moment, and it doesn't seem too awful.
|
||||
var message = new TestAllTypes { RepeatedForeignEnum = { (ForeignEnum) 200, (ForeignEnum) 100 } };
|
||||
AssertJson("{ 'repeatedForeignEnum': [ ] }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NullValueForMessage()
|
||||
{
|
||||
var message = new TestMap { MapInt32ForeignMessage = { { 10, null } } };
|
||||
AssertJson("{ 'mapInt32ForeignMessage': { '10': null } }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("a\u17b4b", "a\\u17b4b")] // Explicit
|
||||
[TestCase("a\u0601b", "a\\u0601b")] // Ranged
|
||||
[TestCase("a\u0605b", "a\u0605b")] // Passthrough (note lack of double backslash...)
|
||||
public void SimpleNonAscii(string text, string encoded)
|
||||
{
|
||||
var message = new TestAllTypes { SingleString = text };
|
||||
AssertJson("{ 'singleString': '" + encoded + "' }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SurrogatePairEscaping()
|
||||
{
|
||||
var message = new TestAllTypes { SingleString = "a\uD801\uDC01b" };
|
||||
AssertJson("{ 'singleString': 'a\\ud801\\udc01b' }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InvalidSurrogatePairsFail()
|
||||
{
|
||||
// Note: don't use TestCase for these, as the strings can't be reliably represented
|
||||
// See http://codeblog.jonskeet.uk/2014/11/07/when-is-a-string-not-a-string/
|
||||
|
||||
// Lone low surrogate
|
||||
var message = new TestAllTypes { SingleString = "a\uDC01b" };
|
||||
Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message));
|
||||
|
||||
// Lone high surrogate
|
||||
message = new TestAllTypes { SingleString = "a\uD801b" };
|
||||
Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("foo_bar", "fooBar")]
|
||||
[TestCase("bananaBanana", "bananaBanana")]
|
||||
[TestCase("BANANABanana", "bananaBanana")]
|
||||
public void ToCamelCase(string original, string expected)
|
||||
{
|
||||
Assert.AreEqual(expected, JsonFormatter.ToCamelCase(original));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(null, "{ }")]
|
||||
[TestCase("x", "{ 'fooString': 'x' }")]
|
||||
[TestCase("", "{ 'fooString': '' }")]
|
||||
[TestCase(null, "{ }")]
|
||||
public void Oneof(string fooStringValue, string expectedJson)
|
||||
{
|
||||
var message = new TestOneof();
|
||||
if (fooStringValue != null)
|
||||
{
|
||||
message.FooString = fooStringValue;
|
||||
}
|
||||
|
||||
// We should get the same result both with and without "format default values".
|
||||
var formatter = new JsonFormatter(new JsonFormatter.Settings(false));
|
||||
AssertJson(expectedJson, formatter.Format(message));
|
||||
formatter = new JsonFormatter(new JsonFormatter.Settings(true));
|
||||
AssertJson(expectedJson, formatter.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WrapperFormatting_Single()
|
||||
{
|
||||
// Just a few examples, handling both classes and value types, and
|
||||
// default vs non-default values
|
||||
var message = new TestWellKnownTypes
|
||||
{
|
||||
Int64Field = 10,
|
||||
Int32Field = 0,
|
||||
BytesField = ByteString.FromBase64("ABCD"),
|
||||
StringField = ""
|
||||
};
|
||||
var expectedJson = "{ 'int64Field': '10', 'int32Field': 0, 'stringField': '', 'bytesField': 'ABCD' }";
|
||||
AssertJson(expectedJson, JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WrapperFormatting_IncludeNull()
|
||||
{
|
||||
// The actual JSON here is very large because there are lots of fields. Just test a couple of them.
|
||||
var message = new TestWellKnownTypes { Int32Field = 10 };
|
||||
var formatter = new JsonFormatter(new JsonFormatter.Settings(true));
|
||||
var actualJson = formatter.Format(message);
|
||||
Assert.IsTrue(actualJson.Contains("\"int64Field\": null"));
|
||||
Assert.IsFalse(actualJson.Contains("\"int32Field\": null"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputIsInNumericFieldOrder_NoDefaults()
|
||||
{
|
||||
var formatter = new JsonFormatter(new JsonFormatter.Settings(false));
|
||||
var message = new TestJsonFieldOrdering { PlainString = "p1", PlainInt32 = 2 };
|
||||
AssertJson("{ 'plainString': 'p1', 'plainInt32': 2 }", formatter.Format(message));
|
||||
message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" };
|
||||
AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message));
|
||||
message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" };
|
||||
AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputIsInNumericFieldOrder_WithDefaults()
|
||||
{
|
||||
var formatter = new JsonFormatter(new JsonFormatter.Settings(true));
|
||||
var message = new TestJsonFieldOrdering();
|
||||
AssertJson("{ 'plainString': '', 'plainInt32': 0 }", formatter.Format(message));
|
||||
message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" };
|
||||
AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message));
|
||||
message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" };
|
||||
AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TimestampStandalone()
|
||||
{
|
||||
Assert.AreEqual("1970-01-01T00:00:00Z", new Timestamp().ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.100Z", new Timestamp { Nanos = 100000000 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.120Z", new Timestamp { Nanos = 120000000 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.123Z", new Timestamp { Nanos = 123000000 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.123400Z", new Timestamp { Nanos = 123400000 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.123450Z", new Timestamp { Nanos = 123450000 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.123456Z", new Timestamp { Nanos = 123456000 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.123456700Z", new Timestamp { Nanos = 123456700 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.123456780Z", new Timestamp { Nanos = 123456780 }.ToString());
|
||||
Assert.AreEqual("1970-01-01T00:00:00.123456789Z", new Timestamp { Nanos = 123456789 }.ToString());
|
||||
|
||||
// One before and one after the Unix epoch
|
||||
Assert.AreEqual("1673-06-19T12:34:56Z",
|
||||
new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp().ToString());
|
||||
Assert.AreEqual("2015-07-31T10:29:34Z",
|
||||
new DateTime(2015, 7, 31, 10, 29, 34, DateTimeKind.Utc).ToTimestamp().ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TimestampField()
|
||||
{
|
||||
var message = new TestWellKnownTypes { TimestampField = new Timestamp() };
|
||||
AssertJson("{ 'timestampField': '1970-01-01T00:00:00Z' }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(0, 0, "0s")]
|
||||
[TestCase(1, 0, "1s")]
|
||||
[TestCase(-1, 0, "-1s")]
|
||||
[TestCase(0, 100000000, "0.100s")]
|
||||
[TestCase(0, 120000000, "0.120s")]
|
||||
[TestCase(0, 123000000, "0.123s")]
|
||||
[TestCase(0, 123400000, "0.123400s")]
|
||||
[TestCase(0, 123450000, "0.123450s")]
|
||||
[TestCase(0, 123456000, "0.123456s")]
|
||||
[TestCase(0, 123456700, "0.123456700s")]
|
||||
[TestCase(0, 123456780, "0.123456780s")]
|
||||
[TestCase(0, 123456789, "0.123456789s")]
|
||||
[TestCase(0, -100000000, "-0.100s")]
|
||||
[TestCase(1, 100000000, "1.100s")]
|
||||
[TestCase(-1, -100000000, "-1.100s")]
|
||||
// Non-normalized examples
|
||||
[TestCase(1, 2123456789, "3.123456789s")]
|
||||
[TestCase(1, -100000000, "0.900s")]
|
||||
public void DurationStandalone(long seconds, int nanoseconds, string expected)
|
||||
{
|
||||
Assert.AreEqual(expected, new Duration { Seconds = seconds, Nanos = nanoseconds }.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DurationField()
|
||||
{
|
||||
var message = new TestWellKnownTypes { DurationField = new Duration() };
|
||||
AssertJson("{ 'durationField': '0s' }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StructSample()
|
||||
{
|
||||
var message = new Struct
|
||||
{
|
||||
Fields =
|
||||
{
|
||||
{ "a", new Value { NullValue = new NullValue() } },
|
||||
{ "b", new Value { BoolValue = false } },
|
||||
{ "c", new Value { NumberValue = 10.5 } },
|
||||
{ "d", new Value { StringValue = "text" } },
|
||||
{ "e", new Value { ListValue = new ListValue { Values = { new Value { StringValue = "t1" }, new Value { NumberValue = 5 } } } } },
|
||||
{ "f", new Value { StructValue = new Struct { Fields = { { "nested", new Value { StringValue = "value" } } } } } }
|
||||
}
|
||||
};
|
||||
AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FieldMaskStandalone()
|
||||
{
|
||||
var fieldMask = new FieldMask { Paths = { "", "single", "with_underscore", "nested.field.name", "nested..double_dot" } };
|
||||
Assert.AreEqual(",single,withUnderscore,nested.field.name,nested..doubleDot", fieldMask.ToString());
|
||||
|
||||
// Invalid, but we shouldn't create broken JSON...
|
||||
fieldMask = new FieldMask { Paths = { "x\\y" } };
|
||||
Assert.AreEqual(@"x\\y", fieldMask.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FieldMaskField()
|
||||
{
|
||||
var message = new TestWellKnownTypes { FieldMaskField = new FieldMask { Paths = { "user.display_name", "photo" } } };
|
||||
AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks that the actual JSON is the same as the expected JSON - but after replacing
|
||||
/// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier
|
||||
/// to read.
|
||||
/// </summary>
|
||||
private static void AssertJson(string expectedJsonWithApostrophes, string actualJson)
|
||||
{
|
||||
var expectedJson = expectedJsonWithApostrophes.Replace("'", "\"");
|
||||
Assert.AreEqual(expectedJson, actualJson);
|
||||
}
|
||||
}
|
||||
}
|
20
csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs
Normal file
20
csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
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("Google.Protobuf.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Google.Protobuf.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: AssemblyVersion("3.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("3.0.0.0")]
|
@ -1,286 +1,255 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using Google.ProtocolBuffers.Descriptors;
|
||||
using Google.ProtocolBuffers.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
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>
|
||||
public class DescriptorsTest
|
||||
{
|
||||
[Test]
|
||||
public void FileDescriptor()
|
||||
{
|
||||
FileDescriptor file = Unittest.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);
|
||||
|
||||
// unittest.proto doesn't have any public imports, but unittest_import.proto does.
|
||||
Assert.AreEqual(0, file.PublicDependencies.Count);
|
||||
Assert.AreEqual(1, UnittestImport.Descriptor.PublicDependencies.Count);
|
||||
Assert.AreEqual(UnittestImportPublic.Descriptor, UnittestImport.Descriptor.PublicDependencies[0]);
|
||||
|
||||
Assert.AreEqual(1, file.Dependencies.Count);
|
||||
Assert.AreEqual(UnittestImport.Descriptor, file.Dependencies[0]);
|
||||
|
||||
MessageDescriptor messageType = TestAllTypes.Descriptor;
|
||||
Assert.AreEqual(messageType, file.MessageTypes[0]);
|
||||
Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
|
||||
Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
|
||||
Assert.Null(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.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
|
||||
Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum"));
|
||||
Assert.AreEqual(1, UnittestImport.Descriptor.EnumTypes.Count);
|
||||
Assert.AreEqual("ImportEnum", UnittestImport.Descriptor.EnumTypes[0].Name);
|
||||
for (int i = 0; i < file.EnumTypes.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(i, file.EnumTypes[i].Index);
|
||||
}
|
||||
|
||||
FieldDescriptor extension = Unittest.OptionalInt32Extension.Descriptor;
|
||||
Assert.AreEqual(extension, file.Extensions[0]);
|
||||
Assert.AreEqual(extension, file.FindTypeByName<FieldDescriptor>("optional_int32_extension"));
|
||||
Assert.Null(file.FindTypeByName<FieldDescriptor>("no_such_ext"));
|
||||
Assert.Null(file.FindTypeByName<FieldDescriptor>("protobuf_unittest.optional_int32_extension"));
|
||||
Assert.AreEqual(0, UnittestImport.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(Unittest.Descriptor, messageType.File);
|
||||
Assert.Null(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(Unittest.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.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field"));
|
||||
Assert.AreEqual(field, messageType.FindFieldByNumber(1));
|
||||
Assert.Null(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.Null(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.Null(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 = Unittest.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(Unittest.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.DescriptorProtoFile, 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(Unittest.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(TestExtremeDefaultValues.DefaultInstance.EscapedBytes,
|
||||
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 = Unittest.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(Unittest.Descriptor, enumType.File);
|
||||
Assert.Null(enumType.ContainingType);
|
||||
Assert.AreEqual(DescriptorProtos.EnumOptions.DefaultInstance,
|
||||
enumType.Options);
|
||||
|
||||
Assert.AreEqual("NestedEnum", nestedType.Name);
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum",
|
||||
nestedType.FullName);
|
||||
Assert.AreEqual(Unittest.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.Null(enumType.FindValueByName("NO_SUCH_VALUE"));
|
||||
for (int i = 0; i < enumType.Values.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(i, enumType.Values[i].Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CustomOptions()
|
||||
{
|
||||
MessageDescriptor descriptor = TestMessageWithCustomOptions.Descriptor;
|
||||
Assert.IsTrue(descriptor.Options.HasExtension(UnittestCustomOptions.MessageOpt1));
|
||||
Assert.AreEqual(-56, descriptor.Options.GetExtension(UnittestCustomOptions.MessageOpt1));
|
||||
|
||||
|
||||
FieldDescriptor field = descriptor.FindFieldByName("field1");
|
||||
Assert.NotNull(field);
|
||||
|
||||
Assert.IsTrue(field.Options.HasExtension(UnittestCustomOptions.FieldOpt1));
|
||||
Assert.AreEqual(8765432109uL, field.Options.GetExtension(UnittestCustomOptions.FieldOpt1));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
using UnitTest.Issues.TestProtos;
|
||||
|
||||
namespace Google.Protobuf.Reflection
|
||||
{
|
||||
/// <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>
|
||||
public class DescriptorsTest
|
||||
{
|
||||
[Test]
|
||||
public void FileDescriptor()
|
||||
{
|
||||
FileDescriptor file = UnittestProto3.Descriptor;
|
||||
|
||||
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name);
|
||||
Assert.AreEqual("protobuf_unittest", file.Package);
|
||||
|
||||
Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname);
|
||||
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name);
|
||||
|
||||
// unittest.proto doesn't have any public imports, but unittest_import.proto does.
|
||||
Assert.AreEqual(0, file.PublicDependencies.Count);
|
||||
Assert.AreEqual(1, UnittestImportProto3.Descriptor.PublicDependencies.Count);
|
||||
Assert.AreEqual(UnittestImportPublicProto3.Descriptor, UnittestImportProto3.Descriptor.PublicDependencies[0]);
|
||||
|
||||
Assert.AreEqual(1, file.Dependencies.Count);
|
||||
Assert.AreEqual(UnittestImportProto3.Descriptor, file.Dependencies[0]);
|
||||
|
||||
MessageDescriptor messageType = TestAllTypes.Descriptor;
|
||||
Assert.AreSame(typeof(TestAllTypes), messageType.GeneratedType);
|
||||
Assert.AreEqual(messageType, file.MessageTypes[0]);
|
||||
Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
|
||||
Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
|
||||
Assert.Null(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.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
|
||||
Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum"));
|
||||
Assert.AreEqual(1, UnittestImportProto3.Descriptor.EnumTypes.Count);
|
||||
Assert.AreEqual("ImportEnum", UnittestImportProto3.Descriptor.EnumTypes[0].Name);
|
||||
for (int i = 0; i < file.EnumTypes.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(i, file.EnumTypes[i].Index);
|
||||
}
|
||||
|
||||
Assert.AreEqual(10, file.SerializedData[0]);
|
||||
}
|
||||
|
||||
[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(UnittestProto3.Descriptor, messageType.File);
|
||||
Assert.IsNull(messageType.ContainingType);
|
||||
Assert.IsNull(messageType.Proto.Options);
|
||||
|
||||
Assert.AreEqual("TestAllTypes", messageType.Name);
|
||||
|
||||
Assert.AreEqual("NestedMessage", nestedType.Name);
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName);
|
||||
Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File);
|
||||
Assert.AreEqual(messageType, nestedType.ContainingType);
|
||||
|
||||
FieldDescriptor field = messageType.Fields.InDeclarationOrder()[0];
|
||||
Assert.AreEqual("single_int32", field.Name);
|
||||
Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32"));
|
||||
Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field"));
|
||||
Assert.AreEqual(field, messageType.FindFieldByNumber(1));
|
||||
Assert.Null(messageType.FindFieldByNumber(571283));
|
||||
var fieldsInDeclarationOrder = messageType.Fields.InDeclarationOrder();
|
||||
for (int i = 0; i < fieldsInDeclarationOrder.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(i, fieldsInDeclarationOrder[i].Index);
|
||||
}
|
||||
|
||||
Assert.AreEqual(nestedType, messageType.NestedTypes[0]);
|
||||
Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage"));
|
||||
Assert.Null(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.Null(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>("single_int32");
|
||||
FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum");
|
||||
FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message");
|
||||
|
||||
Assert.AreEqual("single_int32", primitiveField.Name);
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32",
|
||||
primitiveField.FullName);
|
||||
Assert.AreEqual(1, primitiveField.FieldNumber);
|
||||
Assert.AreEqual(messageType, primitiveField.ContainingType);
|
||||
Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File);
|
||||
Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
|
||||
Assert.IsNull(primitiveField.Proto.Options);
|
||||
|
||||
Assert.AreEqual("single_nested_enum", enumField.Name);
|
||||
Assert.AreEqual(FieldType.Enum, enumField.FieldType);
|
||||
// Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType);
|
||||
|
||||
Assert.AreEqual("single_foreign_message", messageField.Name);
|
||||
Assert.AreEqual(FieldType.Message, messageField.FieldType);
|
||||
Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FieldDescriptorLabel()
|
||||
{
|
||||
FieldDescriptor singleField =
|
||||
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32");
|
||||
FieldDescriptor repeatedField =
|
||||
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32");
|
||||
|
||||
Assert.IsFalse(singleField.IsRepeated);
|
||||
Assert.IsTrue(repeatedField.IsRepeated);
|
||||
}
|
||||
|
||||
[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 = UnittestProto3.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(UnittestProto3.Descriptor, enumType.File);
|
||||
Assert.Null(enumType.ContainingType);
|
||||
Assert.Null(enumType.Proto.Options);
|
||||
|
||||
Assert.AreEqual("NestedEnum", nestedType.Name);
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum",
|
||||
nestedType.FullName);
|
||||
Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File);
|
||||
Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType);
|
||||
|
||||
EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO");
|
||||
Assert.AreEqual(value, enumType.Values[1]);
|
||||
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.Null(enumType.FindValueByName("NO_SUCH_VALUE"));
|
||||
for (int i = 0; i < enumType.Values.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(i, enumType.Values[i].Index);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OneofDescriptor()
|
||||
{
|
||||
OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
|
||||
Assert.AreEqual("oneof_field", descriptor.Name);
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName);
|
||||
|
||||
var expectedFields = new[] {
|
||||
TestAllTypes.OneofBytesFieldNumber,
|
||||
TestAllTypes.OneofNestedMessageFieldNumber,
|
||||
TestAllTypes.OneofStringFieldNumber,
|
||||
TestAllTypes.OneofUint32FieldNumber }
|
||||
.Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber))
|
||||
.ToList();
|
||||
foreach (var field in expectedFields)
|
||||
{
|
||||
Assert.AreSame(descriptor, field.ContainingOneof);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConstructionWithoutGeneratedCodeInfo()
|
||||
{
|
||||
var data = UnittestIssues.Descriptor.Proto.ToByteArray();
|
||||
var newDescriptor = Google.Protobuf.Reflection.FileDescriptor.InternalBuildGeneratedFileFrom(data, new Reflection.FileDescriptor[] { }, null);
|
||||
|
||||
// We should still be able to get at a field...
|
||||
var messageDescriptor = newDescriptor.FindTypeByName<MessageDescriptor>("ItemField");
|
||||
var fieldDescriptor = messageDescriptor.FindFieldByName("item");
|
||||
// But there shouldn't be an accessor (or a generated type for the message)
|
||||
Assert.IsNull(fieldDescriptor.Accessor);
|
||||
Assert.IsNull(messageDescriptor.GeneratedType);
|
||||
}
|
||||
|
||||
// From TestFieldOrdering:
|
||||
// string my_string = 11;
|
||||
// int64 my_int = 1;
|
||||
// float my_float = 101;
|
||||
// NestedMessage single_nested_message = 200;
|
||||
[Test]
|
||||
public void FieldListOrderings()
|
||||
{
|
||||
var fields = TestFieldOrderings.Descriptor.Fields;
|
||||
Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber));
|
||||
Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber));
|
||||
}
|
||||
}
|
||||
}
|
218
csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
Normal file
218
csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
Normal file
@ -0,0 +1,218 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Google.Protobuf.Reflection
|
||||
{
|
||||
public class FieldAccessTest
|
||||
{
|
||||
[Test]
|
||||
public void GetValue()
|
||||
{
|
||||
var message = SampleMessages.CreateFullTestAllTypes();
|
||||
var fields = TestAllTypes.Descriptor.Fields;
|
||||
Assert.AreEqual(message.SingleBool, fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleBytes, fields[TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleDouble, fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleFixed32, fields[TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleFixed64, fields[TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleFloat, fields[TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleForeignEnum, fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleForeignMessage, fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleImportEnum, fields[TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleImportMessage, fields[TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleInt32, fields[TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleInt64, fields[TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleNestedEnum, fields[TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleNestedMessage, fields[TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SinglePublicImportMessage, fields[TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleSint32, fields[TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleSint64, fields[TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleString, fields[TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleSfixed32, fields[TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleSfixed64, fields[TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleUint32, fields[TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.SingleUint64, fields[TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.OneofBytes, fields[TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.OneofString, fields[TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.OneofNestedMessage, fields[TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(message.OneofUint32, fields[TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message));
|
||||
|
||||
// Just one example for repeated fields - they're all just returning the list
|
||||
var list = (IList) fields[TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message);
|
||||
Assert.AreEqual(message.RepeatedInt32, list);
|
||||
Assert.AreEqual(message.RepeatedInt32[0], list[0]); // Just in case there was any doubt...
|
||||
|
||||
// Just a single map field, for the same reason
|
||||
var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
|
||||
fields = TestMap.Descriptor.Fields;
|
||||
var dictionary = (IDictionary) fields[TestMap.MapStringStringFieldNumber].Accessor.GetValue(mapMessage);
|
||||
Assert.AreEqual(mapMessage.MapStringString, dictionary);
|
||||
Assert.AreEqual("value1", dictionary["key1"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Clear()
|
||||
{
|
||||
var message = SampleMessages.CreateFullTestAllTypes();
|
||||
var fields = TestAllTypes.Descriptor.Fields;
|
||||
fields[TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message);
|
||||
fields[TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message);
|
||||
fields[TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message);
|
||||
fields[TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message);
|
||||
fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message);
|
||||
fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message);
|
||||
fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message);
|
||||
|
||||
var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
|
||||
{
|
||||
SingleBool = false,
|
||||
SingleInt32 = 0,
|
||||
SingleString = "",
|
||||
SingleBytes = ByteString.Empty,
|
||||
SingleForeignEnum = 0,
|
||||
SingleForeignMessage = null,
|
||||
};
|
||||
expected.RepeatedDouble.Clear();
|
||||
|
||||
Assert.AreEqual(expected, message);
|
||||
|
||||
// Separately, maps.
|
||||
var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
|
||||
fields = TestMap.Descriptor.Fields;
|
||||
fields[TestMap.MapStringStringFieldNumber].Accessor.Clear(mapMessage);
|
||||
Assert.AreEqual(0, mapMessage.MapStringString.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetValue_SingleFields()
|
||||
{
|
||||
// Just a sample (primitives, messages, enums, strings, byte strings)
|
||||
var message = SampleMessages.CreateFullTestAllTypes();
|
||||
var fields = TestAllTypes.Descriptor.Fields;
|
||||
fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false);
|
||||
fields[TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500);
|
||||
fields[TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string");
|
||||
fields[TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97));
|
||||
fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.FOREIGN_FOO);
|
||||
fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 });
|
||||
fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5);
|
||||
|
||||
var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
|
||||
{
|
||||
SingleBool = false,
|
||||
SingleInt32 = 500,
|
||||
SingleString = "It's a string",
|
||||
SingleBytes = ByteString.CopyFrom(99, 98, 97),
|
||||
SingleForeignEnum = ForeignEnum.FOREIGN_FOO,
|
||||
SingleForeignMessage = new ForeignMessage { C = 12345 },
|
||||
SingleDouble = 20150701.5
|
||||
};
|
||||
|
||||
Assert.AreEqual(expected, message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetValue_SingleFields_WrongType()
|
||||
{
|
||||
IMessage message = SampleMessages.CreateFullTestAllTypes();
|
||||
var fields = message.Descriptor.Fields;
|
||||
Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetValue_MapFields()
|
||||
{
|
||||
IMessage message = new TestMap();
|
||||
var fields = message.Descriptor.Fields;
|
||||
Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].Accessor.SetValue(message, new Dictionary<string, string>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetValue_RepeatedFields()
|
||||
{
|
||||
IMessage message = SampleMessages.CreateFullTestAllTypes();
|
||||
var fields = message.Descriptor.Fields;
|
||||
Assert.Throws<InvalidOperationException>(() => fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetValue_IncorrectType()
|
||||
{
|
||||
IMessage message = SampleMessages.CreateFullTestAllTypes();
|
||||
var fields = message.Descriptor.Fields;
|
||||
Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Oneof()
|
||||
{
|
||||
var message = new TestAllTypes();
|
||||
var descriptor = TestAllTypes.Descriptor;
|
||||
Assert.AreEqual(1, descriptor.Oneofs.Count);
|
||||
var oneof = descriptor.Oneofs[0];
|
||||
Assert.AreEqual("oneof_field", oneof.Name);
|
||||
Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message));
|
||||
|
||||
message.OneofString = "foo";
|
||||
Assert.AreSame(descriptor.Fields[TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
|
||||
|
||||
message.OneofUint32 = 10;
|
||||
Assert.AreSame(descriptor.Fields[TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
|
||||
|
||||
oneof.Accessor.Clear(message);
|
||||
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FieldDescriptor_ByName()
|
||||
{
|
||||
var descriptor = TestAllTypes.Descriptor;
|
||||
Assert.AreSame(
|
||||
descriptor.Fields[TestAllTypes.SingleBoolFieldNumber],
|
||||
descriptor.Fields["single_bool"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FieldDescriptor_NotFound()
|
||||
{
|
||||
var descriptor = TestAllTypes.Descriptor;
|
||||
Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
|
||||
Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
|
||||
}
|
||||
}
|
||||
}
|
42
csharp/src/Google.Protobuf.Test/SampleEnum.cs
Normal file
42
csharp/src/Google.Protobuf.Test/SampleEnum.cs
Normal file
@ -0,0 +1,42 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
// Just a sample enum with positive and negative values to be used in tests.
|
||||
internal enum SampleEnum
|
||||
{
|
||||
NegativeValue = -2,
|
||||
None = 0,
|
||||
PositiveValue = 3
|
||||
}
|
||||
}
|
99
csharp/src/Google.Protobuf.Test/SampleMessages.cs
Normal file
99
csharp/src/Google.Protobuf.Test/SampleMessages.cs
Normal file
@ -0,0 +1,99 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Google.Protobuf.TestProtos;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper methods to create sample instances of types generated from unit test messages.
|
||||
/// </summary>
|
||||
public class SampleMessages
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new sample TestAllTypes message with all fields populated.
|
||||
/// The "oneof" field is populated with the string property (OneofString).
|
||||
/// </summary>
|
||||
public static TestAllTypes CreateFullTestAllTypes()
|
||||
{
|
||||
return new TestAllTypes
|
||||
{
|
||||
SingleBool = true,
|
||||
SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
|
||||
SingleDouble = 23.5,
|
||||
SingleFixed32 = 23,
|
||||
SingleFixed64 = 1234567890123,
|
||||
SingleFloat = 12.25f,
|
||||
SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
|
||||
SingleForeignMessage = new ForeignMessage { C = 10 },
|
||||
SingleImportEnum = ImportEnum.IMPORT_BAZ,
|
||||
SingleImportMessage = new ImportMessage { D = 20 },
|
||||
SingleInt32 = 100,
|
||||
SingleInt64 = 3210987654321,
|
||||
SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
|
||||
SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
|
||||
SinglePublicImportMessage = new PublicImportMessage { E = 54 },
|
||||
SingleSfixed32 = -123,
|
||||
SingleSfixed64 = -12345678901234,
|
||||
SingleSint32 = -456,
|
||||
SingleSint64 = -12345678901235,
|
||||
SingleString = "test",
|
||||
SingleUint32 = UInt32.MaxValue,
|
||||
SingleUint64 = UInt64.MaxValue,
|
||||
RepeatedBool = { true, false },
|
||||
RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) },
|
||||
RepeatedDouble = { -12.25, 23.5 },
|
||||
RepeatedFixed32 = { UInt32.MaxValue, 23 },
|
||||
RepeatedFixed64 = { UInt64.MaxValue, 1234567890123 },
|
||||
RepeatedFloat = { 100f, 12.25f },
|
||||
RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR },
|
||||
RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
|
||||
RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED },
|
||||
RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
|
||||
RepeatedInt32 = { 100, 200 },
|
||||
RepeatedInt64 = { 3210987654321, Int64.MaxValue },
|
||||
RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
|
||||
RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
|
||||
RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
|
||||
RepeatedSfixed32 = { -123, 123 },
|
||||
RepeatedSfixed64 = { -12345678901234, 12345678901234 },
|
||||
RepeatedSint32 = { -456, 100 },
|
||||
RepeatedSint64 = { -12345678901235, 123 },
|
||||
RepeatedString = { "foo", "bar" },
|
||||
RepeatedUint32 = { UInt32.MaxValue, UInt32.MinValue },
|
||||
RepeatedUint64 = { UInt64.MaxValue, UInt32.MinValue },
|
||||
OneofString = "Oneof string"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,35 +28,35 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using UnitTest.Issues.TestProtos;
|
||||
using NUnit.Framework;
|
||||
|
||||
using System;
|
||||
using Google.ProtocolBuffers.Descriptors;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Generated extension for a singular field.
|
||||
/// </remarks>
|
||||
public sealed class GeneratedSingleExtension<TExtension> : GeneratedExtensionBase<TExtension>
|
||||
public class TestCornerCases
|
||||
{
|
||||
internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor, typeof(TExtension))
|
||||
[Test]
|
||||
public void TestRoundTripNegativeEnums()
|
||||
{
|
||||
}
|
||||
|
||||
public static GeneratedSingleExtension<TExtension> CreateInstance(FieldDescriptor descriptor)
|
||||
{
|
||||
if (descriptor.IsRepeated)
|
||||
NegativeEnumMessage msg = new NegativeEnumMessage
|
||||
{
|
||||
throw new ArgumentException("Must call GeneratedRepeateExtension.CreateInstance() for repeated types.");
|
||||
}
|
||||
return new GeneratedSingleExtension<TExtension>(descriptor);
|
||||
}
|
||||
Value = NegativeEnum.MinusOne,
|
||||
Values = { NegativeEnum.NEGATIVE_ENUM_ZERO, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
|
||||
PackedValues = { NegativeEnum.NEGATIVE_ENUM_ZERO, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
|
||||
};
|
||||
|
||||
public override object FromReflectionType(object value)
|
||||
{
|
||||
return base.SingularFromReflectionType(value);
|
||||
Assert.AreEqual(58, msg.CalculateSize());
|
||||
|
||||
byte[] bytes = new byte[58];
|
||||
CodedOutputStream output = new CodedOutputStream(bytes);
|
||||
|
||||
msg.WriteTo(output);
|
||||
Assert.AreEqual(0, output.SpaceLeft);
|
||||
|
||||
NegativeEnumMessage copy = NegativeEnumMessage.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(msg, copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1445
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
Normal file
1445
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,162 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/unittest_import_proto3.proto
|
||||
#pragma warning disable 1591, 0612, 3021
|
||||
#region Designer generated code
|
||||
|
||||
using pb = global::Google.Protobuf;
|
||||
using pbc = global::Google.Protobuf.Collections;
|
||||
using pbr = global::Google.Protobuf.Reflection;
|
||||
using scg = global::System.Collections.Generic;
|
||||
namespace Google.Protobuf.TestProtos {
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public static partial class UnittestImportProto3 {
|
||||
|
||||
#region Descriptor
|
||||
public static pbr::FileDescriptor Descriptor {
|
||||
get { return descriptor; }
|
||||
}
|
||||
private static pbr::FileDescriptor descriptor;
|
||||
|
||||
static UnittestImportProto3() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"Cixnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90",
|
||||
"bxIYcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0GjNnb29nbGUvcHJvdG9idWYv",
|
||||
"dW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90bzMucHJvdG8iGgoNSW1wb3J0",
|
||||
"TWVzc2FnZRIJCgFkGAEgASgFKlkKCkltcG9ydEVudW0SGwoXSU1QT1JUX0VO",
|
||||
"VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB",
|
||||
"UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl",
|
||||
"c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv",
|
||||
"Mw=="));
|
||||
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
|
||||
new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor, },
|
||||
new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedCodeInfo[] {
|
||||
new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), new[]{ "D" }, null, null, null)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
#region Enums
|
||||
public enum ImportEnum {
|
||||
IMPORT_ENUM_UNSPECIFIED = 0,
|
||||
IMPORT_FOO = 7,
|
||||
IMPORT_BAR = 8,
|
||||
IMPORT_BAZ = 9,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Messages
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
|
||||
private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
|
||||
public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
|
||||
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor.MessageTypes[0]; }
|
||||
}
|
||||
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
public ImportMessage() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
public ImportMessage(ImportMessage other) : this() {
|
||||
d_ = other.d_;
|
||||
}
|
||||
|
||||
public ImportMessage Clone() {
|
||||
return new ImportMessage(this);
|
||||
}
|
||||
|
||||
public const int DFieldNumber = 1;
|
||||
private int d_;
|
||||
public int D {
|
||||
get { return d_; }
|
||||
set {
|
||||
d_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as ImportMessage);
|
||||
}
|
||||
|
||||
public bool Equals(ImportMessage other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (D != other.D) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (D != 0) hash ^= D.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.Default.Format(this);
|
||||
}
|
||||
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
if (D != 0) {
|
||||
output.WriteRawTag(8);
|
||||
output.WriteInt32(D);
|
||||
}
|
||||
}
|
||||
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (D != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public void MergeFrom(ImportMessage other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.D != 0) {
|
||||
D = other.D;
|
||||
}
|
||||
}
|
||||
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
uint tag;
|
||||
while (input.ReadTag(out tag)) {
|
||||
switch(tag) {
|
||||
case 0:
|
||||
throw pb::InvalidProtocolBufferException.InvalidTag();
|
||||
default:
|
||||
if (pb::WireFormat.IsEndGroupTag(tag)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 8: {
|
||||
D = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
#endregion Designer generated code
|
@ -0,0 +1,148 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/unittest_import_public_proto3.proto
|
||||
#pragma warning disable 1591, 0612, 3021
|
||||
#region Designer generated code
|
||||
|
||||
using pb = global::Google.Protobuf;
|
||||
using pbc = global::Google.Protobuf.Collections;
|
||||
using pbr = global::Google.Protobuf.Reflection;
|
||||
using scg = global::System.Collections.Generic;
|
||||
namespace Google.Protobuf.TestProtos {
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public static partial class UnittestImportPublicProto3 {
|
||||
|
||||
#region Descriptor
|
||||
public static pbr::FileDescriptor Descriptor {
|
||||
get { return descriptor; }
|
||||
}
|
||||
private static pbr::FileDescriptor descriptor;
|
||||
|
||||
static UnittestImportPublicProto3() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90",
|
||||
"bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ",
|
||||
"bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1",
|
||||
"Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
|
||||
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
|
||||
new pbr::FileDescriptor[] { },
|
||||
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
|
||||
new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), new[]{ "E" }, null, null, null)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
#region Messages
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
|
||||
private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
|
||||
public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
|
||||
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor.MessageTypes[0]; }
|
||||
}
|
||||
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
public PublicImportMessage() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
public PublicImportMessage(PublicImportMessage other) : this() {
|
||||
e_ = other.e_;
|
||||
}
|
||||
|
||||
public PublicImportMessage Clone() {
|
||||
return new PublicImportMessage(this);
|
||||
}
|
||||
|
||||
public const int EFieldNumber = 1;
|
||||
private int e_;
|
||||
public int E {
|
||||
get { return e_; }
|
||||
set {
|
||||
e_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as PublicImportMessage);
|
||||
}
|
||||
|
||||
public bool Equals(PublicImportMessage other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (E != other.E) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (E != 0) hash ^= E.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.Default.Format(this);
|
||||
}
|
||||
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
if (E != 0) {
|
||||
output.WriteRawTag(8);
|
||||
output.WriteInt32(E);
|
||||
}
|
||||
}
|
||||
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (E != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public void MergeFrom(PublicImportMessage other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.E != 0) {
|
||||
E = other.E;
|
||||
}
|
||||
}
|
||||
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
uint tag;
|
||||
while (input.ReadTag(out tag)) {
|
||||
switch(tag) {
|
||||
case 0:
|
||||
throw pb::InvalidProtocolBufferException.InvalidTag();
|
||||
default:
|
||||
if (pb::WireFormat.IsEndGroupTag(tag)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 8: {
|
||||
E = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
#endregion Designer generated code
|
1395
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
Normal file
1395
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
Normal file
File diff suppressed because it is too large
Load Diff
5970
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
Normal file
5970
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
Normal file
File diff suppressed because it is too large
Load Diff
2299
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
Normal file
2299
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
Normal file
File diff suppressed because it is too large
Load Diff
104
csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
Normal file
104
csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
Normal file
@ -0,0 +1,104 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
|
||||
namespace Google.Protobuf.WellKnownTypes
|
||||
{
|
||||
public class DurationTest
|
||||
{
|
||||
[Test]
|
||||
public void ToTimeSpan()
|
||||
{
|
||||
Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 1 }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = -1 }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromMilliseconds(1), new Duration { Nanos = 1000000 }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromMilliseconds(-1), new Duration { Nanos = -1000000 }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromTicks(1), new Duration { Nanos = 100 }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromTicks(-1), new Duration { Nanos = -100 }.ToTimeSpan());
|
||||
|
||||
// Rounding is towards 0
|
||||
Assert.AreEqual(TimeSpan.FromTicks(2), new Duration { Nanos = 250 }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromTicks(-2), new Duration { Nanos = -250 }.ToTimeSpan());
|
||||
|
||||
// Non-normalized durations
|
||||
Assert.AreEqual(TimeSpan.FromSeconds(3), new Duration { Seconds = 1, Nanos = 2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 3, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
|
||||
Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = 1, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Addition()
|
||||
{
|
||||
Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
|
||||
new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = 500000000 });
|
||||
Assert.AreEqual(new Duration { Seconds = -2, Nanos = -100000000 },
|
||||
new Duration { Seconds = -1, Nanos = -600000000 } + new Duration { Nanos = -500000000 });
|
||||
Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
|
||||
new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = -500000000 });
|
||||
|
||||
// Non-normalized durations, or non-normalized intermediate results
|
||||
Assert.AreEqual(new Duration { Seconds = 1 },
|
||||
new Duration { Seconds = 1, Nanos = -500000000 } + new Duration { Nanos = 500000000 });
|
||||
|
||||
Assert.AreEqual(new Duration { Nanos = -900000000 },
|
||||
new Duration { Seconds = -1, Nanos = -100000000 } + new Duration { Nanos = 200000000 });
|
||||
Assert.AreEqual(new Duration { Nanos = 900000000 },
|
||||
new Duration { Seconds = 1, Nanos = 100000000 } + new Duration { Nanos = -200000000 });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Subtraction()
|
||||
{
|
||||
Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
|
||||
new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = 500000000 });
|
||||
Assert.AreEqual(new Duration { Seconds = -1, Nanos = -100000000 },
|
||||
new Duration { Seconds = -1, Nanos = -600000000 } - new Duration { Nanos = -500000000 });
|
||||
Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
|
||||
new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = -500000000 });
|
||||
|
||||
// Non-normalized durations
|
||||
Assert.AreEqual(new Duration(),
|
||||
new Duration { Seconds = 1, Nanos = -500000000 } - new Duration { Nanos = 500000000 });
|
||||
Assert.AreEqual(new Duration { Seconds = 1 },
|
||||
new Duration { Nanos = 2000000000 } - new Duration { Nanos = 1000000000 });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FromTimeSpan()
|
||||
{
|
||||
Assert.AreEqual(new Duration { Seconds = 1 }, Duration.FromTimeSpan(TimeSpan.FromSeconds(1)));
|
||||
Assert.AreEqual(new Duration { Nanos = Duration.NanosecondsPerTick }, Duration.FromTimeSpan(TimeSpan.FromTicks(1)));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
|
||||
namespace Google.Protobuf.WellKnownTypes
|
||||
{
|
||||
public class TimestampTest
|
||||
{
|
||||
[Test]
|
||||
public void FromAndToDateTime()
|
||||
{
|
||||
DateTime utcMin = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
|
||||
DateTime utcMax = DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
|
||||
AssertRoundtrip(new Timestamp { Seconds = -62135596800 }, utcMin);
|
||||
AssertRoundtrip(new Timestamp { Seconds = 253402300799, Nanos = 999999900 }, utcMax);
|
||||
AssertRoundtrip(new Timestamp(), new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
||||
AssertRoundtrip(new Timestamp { Nanos = 1000000}, new DateTime(1970, 1, 1, 0, 0, 0, 1, DateTimeKind.Utc));
|
||||
AssertRoundtrip(new Timestamp { Seconds = -1, Nanos = 999000000 }, new DateTime(1969, 12, 31, 23, 59, 59, 999, DateTimeKind.Utc));
|
||||
AssertRoundtrip(new Timestamp { Seconds = 3600 }, new DateTime(1970, 1, 1, 1, 0, 0, DateTimeKind.Utc));
|
||||
AssertRoundtrip(new Timestamp { Seconds = -3600 }, new DateTime(1969, 12, 31, 23, 0, 0, DateTimeKind.Utc));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToDateTimeTruncation()
|
||||
{
|
||||
var t1 = new Timestamp { Seconds = 1, Nanos = 1000000 + Duration.NanosecondsPerTick - 1 };
|
||||
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc).AddMilliseconds(1), t1.ToDateTime());
|
||||
|
||||
var t2 = new Timestamp { Seconds = -1, Nanos = 1000000 + Duration.NanosecondsPerTick - 1 };
|
||||
Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 59).AddMilliseconds(1), t2.ToDateTime());
|
||||
}
|
||||
|
||||
private static void AssertRoundtrip(Timestamp timestamp, DateTime dateTime)
|
||||
{
|
||||
Assert.AreEqual(timestamp, Timestamp.FromDateTime(dateTime));
|
||||
Assert.AreEqual(dateTime, timestamp.ToDateTime());
|
||||
Assert.AreEqual(DateTimeKind.Utc, timestamp.ToDateTime().Kind);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Arithmetic()
|
||||
{
|
||||
Timestamp t1 = new Timestamp { Seconds = 10000, Nanos = 5000 };
|
||||
Timestamp t2 = new Timestamp { Seconds = 8000, Nanos = 10000 };
|
||||
Duration difference = new Duration { Seconds = 1999, Nanos = Duration.NanosecondsPerSecond - 5000 };
|
||||
Assert.AreEqual(difference, t1 - t2);
|
||||
Assert.AreEqual(-difference, t2 - t1);
|
||||
|
||||
Assert.AreEqual(t1, t2 + difference);
|
||||
Assert.AreEqual(t2, t1 - difference);
|
||||
}
|
||||
}
|
||||
}
|
326
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
Normal file
326
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
Normal file
@ -0,0 +1,326 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.Protobuf.WellKnownTypes
|
||||
{
|
||||
public class WrappersTest
|
||||
{
|
||||
[Test]
|
||||
public void NullIsDefault()
|
||||
{
|
||||
var message = new TestWellKnownTypes();
|
||||
Assert.IsNull(message.StringField);
|
||||
Assert.IsNull(message.BytesField);
|
||||
Assert.IsNull(message.BoolField);
|
||||
Assert.IsNull(message.FloatField);
|
||||
Assert.IsNull(message.DoubleField);
|
||||
Assert.IsNull(message.Int32Field);
|
||||
Assert.IsNull(message.Int64Field);
|
||||
Assert.IsNull(message.Uint32Field);
|
||||
Assert.IsNull(message.Uint64Field);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NonDefaultSingleValues()
|
||||
{
|
||||
var message = new TestWellKnownTypes
|
||||
{
|
||||
StringField = "x",
|
||||
BytesField = ByteString.CopyFrom(1, 2, 3),
|
||||
BoolField = true,
|
||||
FloatField = 12.5f,
|
||||
DoubleField = 12.25d,
|
||||
Int32Field = 1,
|
||||
Int64Field = 2,
|
||||
Uint32Field = 3,
|
||||
Uint64Field = 4
|
||||
};
|
||||
|
||||
var bytes = message.ToByteArray();
|
||||
var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
|
||||
|
||||
Assert.AreEqual("x", parsed.StringField);
|
||||
Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField);
|
||||
Assert.AreEqual(true, parsed.BoolField);
|
||||
Assert.AreEqual(12.5f, parsed.FloatField);
|
||||
Assert.AreEqual(12.25d, parsed.DoubleField);
|
||||
Assert.AreEqual(1, parsed.Int32Field);
|
||||
Assert.AreEqual(2L, parsed.Int64Field);
|
||||
Assert.AreEqual(3U, parsed.Uint32Field);
|
||||
Assert.AreEqual(4UL, parsed.Uint64Field);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NonNullDefaultIsPreservedThroughSerialization()
|
||||
{
|
||||
var message = new TestWellKnownTypes
|
||||
{
|
||||
StringField = "",
|
||||
BytesField = ByteString.Empty,
|
||||
BoolField = false,
|
||||
FloatField = 0f,
|
||||
DoubleField = 0d,
|
||||
Int32Field = 0,
|
||||
Int64Field = 0,
|
||||
Uint32Field = 0,
|
||||
Uint64Field = 0
|
||||
};
|
||||
|
||||
var bytes = message.ToByteArray();
|
||||
var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
|
||||
|
||||
Assert.AreEqual("", parsed.StringField);
|
||||
Assert.AreEqual(ByteString.Empty, parsed.BytesField);
|
||||
Assert.AreEqual(false, parsed.BoolField);
|
||||
Assert.AreEqual(0f, parsed.FloatField);
|
||||
Assert.AreEqual(0d, parsed.DoubleField);
|
||||
Assert.AreEqual(0, parsed.Int32Field);
|
||||
Assert.AreEqual(0L, parsed.Int64Field);
|
||||
Assert.AreEqual(0U, parsed.Uint32Field);
|
||||
Assert.AreEqual(0UL, parsed.Uint64Field);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RepeatedWrappersProhibitNullItems()
|
||||
{
|
||||
var message = new RepeatedWellKnownTypes();
|
||||
Assert.Throws<ArgumentNullException>(() => message.BoolField.Add((bool?) null));
|
||||
Assert.Throws<ArgumentNullException>(() => message.Int32Field.Add((int?) null));
|
||||
Assert.Throws<ArgumentNullException>(() => message.StringField.Add((string) null));
|
||||
Assert.Throws<ArgumentNullException>(() => message.BytesField.Add((ByteString) null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RepeatedWrappersSerializeDeserialize()
|
||||
{
|
||||
var message = new RepeatedWellKnownTypes
|
||||
{
|
||||
BoolField = { true, false },
|
||||
BytesField = { ByteString.CopyFrom(1, 2, 3), ByteString.CopyFrom(4, 5, 6), ByteString.Empty },
|
||||
DoubleField = { 12.5, -1.5, 0d },
|
||||
FloatField = { 123.25f, -20f, 0f },
|
||||
Int32Field = { int.MaxValue, int.MinValue, 0 },
|
||||
Int64Field = { long.MaxValue, long.MinValue, 0L },
|
||||
StringField = { "First", "Second", "" },
|
||||
Uint32Field = { uint.MaxValue, uint.MinValue, 0U },
|
||||
Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL },
|
||||
};
|
||||
var bytes = message.ToByteArray();
|
||||
var parsed = RepeatedWellKnownTypes.Parser.ParseFrom(bytes);
|
||||
|
||||
Assert.AreEqual(message, parsed);
|
||||
// Just to test a single value for sanity...
|
||||
Assert.AreEqual("Second", message.StringField[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MapWrappersSerializeDeserialize()
|
||||
{
|
||||
var message = new MapWellKnownTypes
|
||||
{
|
||||
BoolField = { { 10, false }, { 20, true } },
|
||||
BytesField = {
|
||||
{ -1, ByteString.CopyFrom(1, 2, 3) },
|
||||
{ 10, ByteString.CopyFrom(4, 5, 6) },
|
||||
{ 1000, ByteString.Empty },
|
||||
{ 10000, null }
|
||||
},
|
||||
DoubleField = { { 1, 12.5 }, { 10, -1.5 }, { 20, 0d } },
|
||||
FloatField = { { 2, 123.25f }, { 3, -20f }, { 4, 0f } },
|
||||
Int32Field = { { 5, int.MaxValue }, { 6, int.MinValue }, { 7, 0 } },
|
||||
Int64Field = { { 8, long.MaxValue }, { 9, long.MinValue }, { 10, 0L } },
|
||||
StringField = { { 11, "First" }, { 12, "Second" }, { 13, "" }, { 14, null } },
|
||||
Uint32Field = { { 15, uint.MaxValue }, { 16, uint.MinValue }, { 17, 0U } },
|
||||
Uint64Field = { { 18, ulong.MaxValue }, { 19, ulong.MinValue }, { 20, 0UL } },
|
||||
};
|
||||
|
||||
var bytes = message.ToByteArray();
|
||||
var parsed = MapWellKnownTypes.Parser.ParseFrom(bytes);
|
||||
|
||||
Assert.AreEqual(message, parsed);
|
||||
// Just to test a single value for sanity...
|
||||
Assert.AreEqual("Second", message.StringField[12]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Reflection_SingleValues()
|
||||
{
|
||||
var message = new TestWellKnownTypes
|
||||
{
|
||||
StringField = "x",
|
||||
BytesField = ByteString.CopyFrom(1, 2, 3),
|
||||
BoolField = true,
|
||||
FloatField = 12.5f,
|
||||
DoubleField = 12.25d,
|
||||
Int32Field = 1,
|
||||
Int64Field = 2,
|
||||
Uint32Field = 3,
|
||||
Uint64Field = 4
|
||||
};
|
||||
var fields = TestWellKnownTypes.Descriptor.Fields;
|
||||
|
||||
Assert.AreEqual("x", fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), fields[TestWellKnownTypes.BytesFieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(true, fields[TestWellKnownTypes.BoolFieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(12.5f, fields[TestWellKnownTypes.FloatFieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(12.25d, fields[TestWellKnownTypes.DoubleFieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(1, fields[TestWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(2L, fields[TestWellKnownTypes.Int64FieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(3U, fields[TestWellKnownTypes.Uint32FieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.AreEqual(4UL, fields[TestWellKnownTypes.Uint64FieldFieldNumber].Accessor.GetValue(message));
|
||||
|
||||
// And a couple of null fields...
|
||||
message.StringField = null;
|
||||
message.FloatField = null;
|
||||
Assert.IsNull(fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.GetValue(message));
|
||||
Assert.IsNull(fields[TestWellKnownTypes.FloatFieldFieldNumber].Accessor.GetValue(message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Reflection_RepeatedFields()
|
||||
{
|
||||
// Just a single example... note that we can't have a null value here
|
||||
var message = new RepeatedWellKnownTypes { Int32Field = { 1, 2 } };
|
||||
var fields = RepeatedWellKnownTypes.Descriptor.Fields;
|
||||
var list = (IList) fields[RepeatedWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message);
|
||||
CollectionAssert.AreEqual(new[] { 1, 2 }, list);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Reflection_MapFields()
|
||||
{
|
||||
// Just a single example... note that we can't have a null value here
|
||||
var message = new MapWellKnownTypes { Int32Field = { { 1, 2 }, { 3, null } } };
|
||||
var fields = MapWellKnownTypes.Descriptor.Fields;
|
||||
var dictionary = (IDictionary) fields[MapWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message);
|
||||
Assert.AreEqual(2, dictionary[1]);
|
||||
Assert.IsNull(dictionary[3]);
|
||||
Assert.IsTrue(dictionary.Contains(3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Oneof()
|
||||
{
|
||||
var message = new OneofWellKnownTypes { EmptyField = new Empty() };
|
||||
// Start off with a non-wrapper
|
||||
Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.EmptyField, message.OneofFieldCase);
|
||||
AssertOneofRoundTrip(message);
|
||||
|
||||
message.StringField = "foo";
|
||||
Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.StringField, message.OneofFieldCase);
|
||||
AssertOneofRoundTrip(message);
|
||||
|
||||
message.StringField = "foo";
|
||||
Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.StringField, message.OneofFieldCase);
|
||||
AssertOneofRoundTrip(message);
|
||||
|
||||
message.DoubleField = 0.0f;
|
||||
Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.DoubleField, message.OneofFieldCase);
|
||||
AssertOneofRoundTrip(message);
|
||||
|
||||
message.DoubleField = 1.0f;
|
||||
Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.DoubleField, message.OneofFieldCase);
|
||||
AssertOneofRoundTrip(message);
|
||||
|
||||
message.ClearOneofField();
|
||||
Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
|
||||
AssertOneofRoundTrip(message);
|
||||
}
|
||||
|
||||
private void AssertOneofRoundTrip(OneofWellKnownTypes message)
|
||||
{
|
||||
// Normal roundtrip, but explicitly checking the case...
|
||||
var bytes = message.ToByteArray();
|
||||
var parsed = OneofWellKnownTypes.Parser.ParseFrom(bytes);
|
||||
Assert.AreEqual(message, parsed);
|
||||
Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("x", "y", "y")]
|
||||
[TestCase("x", "", "x")]
|
||||
[TestCase("x", null, "x")]
|
||||
[TestCase("", "y", "y")]
|
||||
[TestCase("", "", "")]
|
||||
[TestCase("", null, "")]
|
||||
[TestCase(null, "y", "y")]
|
||||
[TestCase(null, "", "")]
|
||||
[TestCase(null, null, null)]
|
||||
public void Merging(string original, string merged, string expected)
|
||||
{
|
||||
var originalMessage = new TestWellKnownTypes { StringField = original };
|
||||
var mergingMessage = new TestWellKnownTypes { StringField = merged };
|
||||
originalMessage.MergeFrom(mergingMessage);
|
||||
Assert.AreEqual(expected, originalMessage.StringField);
|
||||
|
||||
// Try it using MergeFrom(CodedInputStream) too...
|
||||
originalMessage = new TestWellKnownTypes { StringField = original };
|
||||
originalMessage.MergeFrom(mergingMessage.ToByteArray());
|
||||
Assert.AreEqual(expected, originalMessage.StringField);
|
||||
}
|
||||
|
||||
// Merging is odd with wrapper types, due to the way that default values aren't emitted in
|
||||
// the binary stream. In fact we cheat a little bit - a message with an explicitly present default
|
||||
// value will have that default value ignored.
|
||||
[Test]
|
||||
public void MergingCornerCase()
|
||||
{
|
||||
var message = new TestWellKnownTypes { Int32Field = 5 };
|
||||
|
||||
// Create a byte array which has the data of an Int32Value explicitly containing a value of 0.
|
||||
// This wouldn't normally happen.
|
||||
byte[] bytes;
|
||||
var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
|
||||
var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint);
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
var coded = new CodedOutputStream(stream);
|
||||
coded.WriteTag(wrapperTag);
|
||||
coded.WriteLength(2); // valueTag + a value 0, each one byte
|
||||
coded.WriteTag(valueTag);
|
||||
coded.WriteInt32(0);
|
||||
coded.Flush();
|
||||
bytes = stream.ToArray();
|
||||
}
|
||||
|
||||
message.MergeFrom(bytes);
|
||||
// A normal implementation would have 0 now, as the explicit default would have been overwritten the 5.
|
||||
Assert.AreEqual(5, message.Int32Field);
|
||||
}
|
||||
}
|
||||
}
|
48
csharp/src/Google.Protobuf.sln
Normal file
48
csharp/src/Google.Protobuf.sln
Normal file
@ -0,0 +1,48 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.csproj", "{DD01ED24-3750-4567-9A23-1DB676A15610}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddressBook", "AddressBook\AddressBook.csproj", "{A31F5FB2-4FF3-432A-B35B-5CD203606311}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{D7282E99-2DC3-405B-946F-177DB2FD2AE2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
ReleaseSigned|Any CPU = ReleaseSigned|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
|
||||
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
|
||||
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|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
|
||||
{DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
|
||||
{DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
|
||||
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
|
||||
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,12 +28,11 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy
|
||||
@ -51,7 +47,7 @@ namespace Google.ProtocolBuffers
|
||||
/// <summary>
|
||||
/// Determines which copy routine to use based on the number of bytes to be copied.
|
||||
/// </summary>
|
||||
public static void Copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
||||
internal static void Copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
||||
{
|
||||
if (count > CopyThreshold)
|
||||
{
|
||||
@ -59,31 +55,22 @@ namespace Google.ProtocolBuffers
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteCopy(src, srcOffset, dst, dstOffset, count);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the bytes provided with a for loop, faster when there are only a few bytes to copy
|
||||
/// </summary>
|
||||
public static void ByteCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
|
||||
{
|
||||
int stop = srcOffset + count;
|
||||
for (int i = srcOffset; i < stop; i++)
|
||||
{
|
||||
dst[dstOffset++] = src[i];
|
||||
int stop = srcOffset + count;
|
||||
for (int i = srcOffset; i < stop; i++)
|
||||
{
|
||||
dst[dstOffset++] = src[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverses the order of bytes in the array
|
||||
/// </summary>
|
||||
public static void Reverse(byte[] bytes)
|
||||
internal static void Reverse(byte[] bytes)
|
||||
{
|
||||
byte temp;
|
||||
for (int first = 0, last = bytes.Length - 1; first < last; first++, last--)
|
||||
{
|
||||
temp = bytes[first];
|
||||
byte temp = bytes[first];
|
||||
bytes[first] = bytes[last];
|
||||
bytes[last] = temp;
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,7 +28,6 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
@ -40,7 +36,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Immutable array of bytes.
|
||||
@ -138,8 +134,10 @@ namespace Google.ProtocolBuffers
|
||||
/// 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.
|
||||
/// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form
|
||||
/// which is primarily useful for testing.
|
||||
/// </summary>
|
||||
public static ByteString CopyFrom(byte[] bytes)
|
||||
public static ByteString CopyFrom(params byte[] bytes)
|
||||
{
|
||||
return new ByteString((byte[]) bytes.Clone());
|
||||
}
|
||||
@ -205,19 +203,43 @@ namespace Google.ProtocolBuffers
|
||||
public CodedInputStream CreateCodedInput()
|
||||
{
|
||||
// We trust CodedInputStream not to reveal the provided byte array or modify it
|
||||
return CodedInputStream.CreateInstance(bytes);
|
||||
return new CodedInputStream(bytes);
|
||||
}
|
||||
|
||||
public static bool operator ==(ByteString lhs, ByteString rhs)
|
||||
{
|
||||
if (ReferenceEquals(lhs, rhs))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.bytes.Length != rhs.bytes.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < lhs.Length; i++)
|
||||
{
|
||||
if (rhs.bytes[i] != lhs.bytes[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool operator !=(ByteString lhs, ByteString rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
// 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);
|
||||
return this == (obj as ByteString);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
@ -232,50 +254,7 @@ namespace Google.ProtocolBuffers
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
internal 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);
|
||||
}
|
||||
|
||||
internal CodedOutputStream CodedOutput
|
||||
{
|
||||
get { return output; }
|
||||
}
|
||||
return this == other;
|
||||
}
|
||||
|
||||
/// <summary>
|
File diff suppressed because it is too large
Load Diff
304
csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
Normal file
304
csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
Normal file
@ -0,0 +1,304 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
// This part of CodedOutputStream provides all the static entry points that are used
|
||||
// by generated code and internally to compute the size of messages prior to being
|
||||
// written to an instance of CodedOutputStream.
|
||||
public sealed partial class CodedOutputStream
|
||||
{
|
||||
private const int LittleEndian64Size = 8;
|
||||
private const int LittleEndian32Size = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// double field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeDoubleSize(double value)
|
||||
{
|
||||
return LittleEndian64Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// float field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeFloatSize(float value)
|
||||
{
|
||||
return LittleEndian32Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// uint64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeUInt64Size(ulong value)
|
||||
{
|
||||
return ComputeRawVarint64Size(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode an
|
||||
/// int64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeInt64Size(long value)
|
||||
{
|
||||
return ComputeRawVarint64Size((ulong) value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode an
|
||||
/// int32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeInt32Size(int value)
|
||||
{
|
||||
if (value >= 0)
|
||||
{
|
||||
return ComputeRawVarint32Size((uint) value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must sign-extend.
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// fixed64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeFixed64Size(ulong value)
|
||||
{
|
||||
return LittleEndian64Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// fixed32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeFixed32Size(uint value)
|
||||
{
|
||||
return LittleEndian32Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// bool field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeBoolSize(bool value)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// string field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeStringSize(String value)
|
||||
{
|
||||
int byteArraySize = Utf8Encoding.GetByteCount(value);
|
||||
return ComputeLengthSize(byteArraySize) + byteArraySize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// group field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeGroupSize(IMessage value)
|
||||
{
|
||||
return value.CalculateSize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode an
|
||||
/// embedded message field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeMessageSize(IMessage value)
|
||||
{
|
||||
int size = value.CalculateSize();
|
||||
return ComputeLengthSize(size) + size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// bytes field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeBytesSize(ByteString value)
|
||||
{
|
||||
return ComputeLengthSize(value.Length) + value.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a
|
||||
/// uint32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeUInt32Size(uint value)
|
||||
{
|
||||
return ComputeRawVarint32Size(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes 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 value)
|
||||
{
|
||||
// Currently just a pass-through, but it's nice to separate it logically.
|
||||
return ComputeInt32Size(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode an
|
||||
/// sfixed32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSFixed32Size(int value)
|
||||
{
|
||||
return LittleEndian32Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode an
|
||||
/// sfixed64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSFixed64Size(long value)
|
||||
{
|
||||
return LittleEndian64Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode an
|
||||
/// sint32 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSInt32Size(int value)
|
||||
{
|
||||
return ComputeRawVarint32Size(EncodeZigZag32(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode an
|
||||
/// sint64 field, including the tag.
|
||||
/// </summary>
|
||||
public static int ComputeSInt64Size(long value)
|
||||
{
|
||||
return ComputeRawVarint64Size(EncodeZigZag64(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the number of bytes that would be needed to encode a length,
|
||||
/// as written by <see cref="WriteLength"/>.
|
||||
/// </summary>
|
||||
public static int ComputeLengthSize(int length)
|
||||
{
|
||||
return ComputeRawVarint32Size((uint) length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes 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>
|
||||
/// Computes 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes 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));
|
||||
}
|
||||
}
|
||||
}
|
695
csharp/src/Google.Protobuf/CodedOutputStream.cs
Normal file
695
csharp/src/Google.Protobuf/CodedOutputStream.cs
Normal file
@ -0,0 +1,695 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <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 partial class CodedOutputStream
|
||||
{
|
||||
// "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
|
||||
internal static readonly Encoding Utf8Encoding = Encoding.UTF8;
|
||||
|
||||
/// <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
|
||||
/// <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 CodedOutputStream(byte[] flatArray) : this(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>
|
||||
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 CodedOutputStream(Stream output) : this(output, DefaultBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CodedOutputStream which write to the given stream and uses
|
||||
/// the specified buffer size.
|
||||
/// </summary>
|
||||
public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize])
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current position in the stream, or the position in the output buffer
|
||||
/// </summary>
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
if (output != null)
|
||||
{
|
||||
return output.Position + position;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
#region Writing of values (not including tags)
|
||||
|
||||
/// <summary>
|
||||
/// Writes a double field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteDouble(double value)
|
||||
{
|
||||
WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a float field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteFloat(float value)
|
||||
{
|
||||
byte[] rawBytes = BitConverter.GetBytes(value);
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
ByteArray.Reverse(rawBytes);
|
||||
}
|
||||
|
||||
if (limit - position >= 4)
|
||||
{
|
||||
buffer[position++] = rawBytes[0];
|
||||
buffer[position++] = rawBytes[1];
|
||||
buffer[position++] = rawBytes[2];
|
||||
buffer[position++] = rawBytes[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteRawBytes(rawBytes, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a uint64 field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteUInt64(ulong value)
|
||||
{
|
||||
WriteRawVarint64(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an int64 field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteInt64(long value)
|
||||
{
|
||||
WriteRawVarint64((ulong) value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an int32 field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteInt32(int value)
|
||||
{
|
||||
if (value >= 0)
|
||||
{
|
||||
WriteRawVarint32((uint) value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must sign-extend.
|
||||
WriteRawVarint64((ulong) value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a fixed64 field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteFixed64(ulong value)
|
||||
{
|
||||
WriteRawLittleEndian64(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a fixed32 field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteFixed32(uint value)
|
||||
{
|
||||
WriteRawLittleEndian32(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a bool field value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteBool(bool value)
|
||||
{
|
||||
WriteRawByte(value ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a string field value, without a tag, to the stream.
|
||||
/// The data is length-prefixed.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteString(string value)
|
||||
{
|
||||
// Optimise the case where we have enough space to write
|
||||
// the string directly to the buffer, which should be common.
|
||||
int length = Utf8Encoding.GetByteCount(value);
|
||||
WriteLength(length);
|
||||
if (limit - position >= length)
|
||||
{
|
||||
if (length == value.Length) // Must be all ASCII...
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
buffer[position + i] = (byte)value[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Utf8Encoding.GetBytes(value, 0, value.Length, buffer, position);
|
||||
}
|
||||
position += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] bytes = Utf8Encoding.GetBytes(value);
|
||||
WriteRawBytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a message, without a tag, to the stream.
|
||||
/// The data is length-prefixed.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteMessage(IMessage value)
|
||||
{
|
||||
WriteLength(value.CalculateSize());
|
||||
value.WriteTo(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a byte string, without a tag, to the stream.
|
||||
/// The data is length-prefixed.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteBytes(ByteString value)
|
||||
{
|
||||
WriteLength(value.Length);
|
||||
value.WriteRawBytesTo(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a uint32 value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteUInt32(uint value)
|
||||
{
|
||||
WriteRawVarint32(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an enum value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteEnum(int value)
|
||||
{
|
||||
WriteInt32(value);
|
||||
}
|
||||
|
||||
public void WriteSFixed32(int value)
|
||||
{
|
||||
WriteRawLittleEndian32((uint) value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an sfixed64 value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteSFixed64(long value)
|
||||
{
|
||||
WriteRawLittleEndian64((ulong) value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an sint32 value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteSInt32(int value)
|
||||
{
|
||||
WriteRawVarint32(EncodeZigZag32(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an sint64 value, without a tag, to the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write</param>
|
||||
public void WriteSInt64(long value)
|
||||
{
|
||||
WriteRawVarint64(EncodeZigZag64(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a length (in bytes) for length-delimited data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method simply writes a rawint, but exists for clarity in calling code.
|
||||
/// </remarks>
|
||||
/// <param name="length">Length value, in bytes.</param>
|
||||
public void WriteLength(int length)
|
||||
{
|
||||
WriteRawVarint32((uint) length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Raw tag writing
|
||||
/// <summary>
|
||||
/// Encodes and writes a tag.
|
||||
/// </summary>
|
||||
/// <param name="fieldNumber">The number of the field to write the tag for</param>
|
||||
/// <param name="type">The wire format type of the tag to write</param>
|
||||
public void WriteTag(int fieldNumber, WireFormat.WireType type)
|
||||
{
|
||||
WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an already-encoded tag.
|
||||
/// </summary>
|
||||
/// <param name="tag">The encoded tag</param>
|
||||
public void WriteTag(uint tag)
|
||||
{
|
||||
WriteRawVarint32(tag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the given single-byte tag directly to the stream.
|
||||
/// </summary>
|
||||
/// <param name="b1">The encoded tag</param>
|
||||
public void WriteRawTag(byte b1)
|
||||
{
|
||||
WriteRawByte(b1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the given two-byte tag directly to the stream.
|
||||
/// </summary>
|
||||
/// <param name="b1">The first byte of the encoded tag</param>
|
||||
/// <param name="b2">The second byte of the encoded tag</param>
|
||||
public void WriteRawTag(byte b1, byte b2)
|
||||
{
|
||||
WriteRawByte(b1);
|
||||
WriteRawByte(b2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the given three-byte tag directly to the stream.
|
||||
/// </summary>
|
||||
/// <param name="b1">The first byte of the encoded tag</param>
|
||||
/// <param name="b2">The second byte of the encoded tag</param>
|
||||
/// <param name="b3">The third byte of the encoded tag</param>
|
||||
public void WriteRawTag(byte b1, byte b2, byte b3)
|
||||
{
|
||||
WriteRawByte(b1);
|
||||
WriteRawByte(b2);
|
||||
WriteRawByte(b3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the given four-byte tag directly to the stream.
|
||||
/// </summary>
|
||||
/// <param name="b1">The first byte of the encoded tag</param>
|
||||
/// <param name="b2">The second byte of the encoded tag</param>
|
||||
/// <param name="b3">The third byte of the encoded tag</param>
|
||||
/// <param name="b4">The fourth byte of the encoded tag</param>
|
||||
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
|
||||
{
|
||||
WriteRawByte(b1);
|
||||
WriteRawByte(b2);
|
||||
WriteRawByte(b3);
|
||||
WriteRawByte(b4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the given five-byte tag directly to the stream.
|
||||
/// </summary>
|
||||
/// <param name="b1">The first byte of the encoded tag</param>
|
||||
/// <param name="b2">The second byte of the encoded tag</param>
|
||||
/// <param name="b3">The third byte of the encoded tag</param>
|
||||
/// <param name="b4">The fourth byte of the encoded tag</param>
|
||||
/// <param name="b5">The fifth byte of the encoded tag</param>
|
||||
public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
|
||||
{
|
||||
WriteRawByte(b1);
|
||||
WriteRawByte(b2);
|
||||
WriteRawByte(b3);
|
||||
WriteRawByte(b4);
|
||||
WriteRawByte(b5);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Underlying writing primitives
|
||||
/// <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>
|
||||
internal void WriteRawVarint32(uint value)
|
||||
{
|
||||
// Optimize for the common case of a single byte value
|
||||
if (value < 128 && position < limit)
|
||||
{
|
||||
buffer[position++] = (byte)value;
|
||||
return;
|
||||
}
|
||||
|
||||
while (value > 127 && position < limit)
|
||||
{
|
||||
buffer[position++] = (byte) ((value & 0x7F) | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
while (value > 127)
|
||||
{
|
||||
WriteRawByte((byte) ((value & 0x7F) | 0x80));
|
||||
value >>= 7;
|
||||
}
|
||||
if (position < limit)
|
||||
{
|
||||
buffer[position++] = (byte) value;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteRawByte((byte) value);
|
||||
}
|
||||
}
|
||||
|
||||
internal void WriteRawVarint64(ulong value)
|
||||
{
|
||||
while (value > 127 && position < limit)
|
||||
{
|
||||
buffer[position++] = (byte) ((value & 0x7F) | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
while (value > 127)
|
||||
{
|
||||
WriteRawByte((byte) ((value & 0x7F) | 0x80));
|
||||
value >>= 7;
|
||||
}
|
||||
if (position < limit)
|
||||
{
|
||||
buffer[position++] = (byte) value;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteRawByte((byte) value);
|
||||
}
|
||||
}
|
||||
|
||||
internal void WriteRawLittleEndian32(uint value)
|
||||
{
|
||||
if (position + 4 > limit)
|
||||
{
|
||||
WriteRawByte((byte) value);
|
||||
WriteRawByte((byte) (value >> 8));
|
||||
WriteRawByte((byte) (value >> 16));
|
||||
WriteRawByte((byte) (value >> 24));
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[position++] = ((byte) value);
|
||||
buffer[position++] = ((byte) (value >> 8));
|
||||
buffer[position++] = ((byte) (value >> 16));
|
||||
buffer[position++] = ((byte) (value >> 24));
|
||||
}
|
||||
}
|
||||
|
||||
internal void WriteRawLittleEndian64(ulong value)
|
||||
{
|
||||
if (position + 8 > limit)
|
||||
{
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[position++] = ((byte) value);
|
||||
buffer[position++] = ((byte) (value >> 8));
|
||||
buffer[position++] = ((byte) (value >> 16));
|
||||
buffer[position++] = ((byte) (value >> 24));
|
||||
buffer[position++] = ((byte) (value >> 32));
|
||||
buffer[position++] = ((byte) (value >> 40));
|
||||
buffer[position++] = ((byte) (value >> 48));
|
||||
buffer[position++] = ((byte) (value >> 56));
|
||||
}
|
||||
}
|
||||
|
||||
internal void WriteRawByte(byte value)
|
||||
{
|
||||
if (position == limit)
|
||||
{
|
||||
RefreshBuffer();
|
||||
}
|
||||
|
||||
buffer[position++] = value;
|
||||
}
|
||||
|
||||
internal void WriteRawByte(uint value)
|
||||
{
|
||||
WriteRawByte((byte) value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes out an array of bytes.
|
||||
/// </summary>
|
||||
internal void WriteRawBytes(byte[] value)
|
||||
{
|
||||
WriteRawBytes(value, 0, value.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes out part of an array of bytes.
|
||||
/// </summary>
|
||||
internal void WriteRawBytes(byte[] value, int offset, int length)
|
||||
{
|
||||
if (limit - position >= length)
|
||||
{
|
||||
ByteArray.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;
|
||||
ByteArray.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.
|
||||
ByteArray.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
|
||||
|
||||
/// <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>
|
||||
internal 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>
|
||||
internal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
534
csharp/src/Google.Protobuf/Collections/MapField.cs
Normal file
534
csharp/src/Google.Protobuf/Collections/MapField.cs
Normal file
@ -0,0 +1,534 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using Google.Protobuf.Reflection;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.Protobuf.Compatibility;
|
||||
|
||||
namespace Google.Protobuf.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of a map field in a Protocol Buffer message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation preserves insertion order for simplicity of testing
|
||||
/// code using maps fields. Overwriting an existing entry does not change the
|
||||
/// position of that entry within the map. Equality is not order-sensitive.
|
||||
/// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal"/>.
|
||||
/// </remarks>
|
||||
/// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
|
||||
/// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
|
||||
public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
|
||||
{
|
||||
// TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
|
||||
private readonly bool allowNullValues;
|
||||
private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
|
||||
new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>();
|
||||
private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new map field, defaulting the value nullability to only allow null values for message types
|
||||
/// and non-nullable value types.
|
||||
/// </summary>
|
||||
public MapField() : this(typeof(IMessage).IsAssignableFrom(typeof(TValue)) || Nullable.GetUnderlyingType(typeof(TValue)) != null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new map field, overriding the choice of whether null values are permitted in the map.
|
||||
/// This is used by wrapper types, where maps with string and bytes wrappers as the value types
|
||||
/// support null values.
|
||||
/// </summary>
|
||||
/// <param name="allowNullValues">Whether null values are permitted in the map or not.</param>
|
||||
public MapField(bool allowNullValues)
|
||||
{
|
||||
if (allowNullValues && typeof(TValue).IsValueType() && Nullable.GetUnderlyingType(typeof(TValue)) == null)
|
||||
{
|
||||
throw new ArgumentException("allowNullValues", "Non-nullable value types do not support null values");
|
||||
}
|
||||
this.allowNullValues = allowNullValues;
|
||||
}
|
||||
|
||||
public MapField<TKey, TValue> Clone()
|
||||
{
|
||||
var clone = new MapField<TKey, TValue>(allowNullValues);
|
||||
// Keys are never cloneable. Values might be.
|
||||
if (typeof(IDeepCloneable<TValue>).IsAssignableFrom(typeof(TValue)))
|
||||
{
|
||||
foreach (var pair in list)
|
||||
{
|
||||
clone.Add(pair.Key, pair.Value == null ? pair.Value : ((IDeepCloneable<TValue>)pair.Value).Clone());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing is cloneable, so we don't need to worry.
|
||||
clone.Add(this);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
// Validation of arguments happens in ContainsKey and the indexer
|
||||
if (ContainsKey(key))
|
||||
{
|
||||
throw new ArgumentException("Key already exists in map", "key");
|
||||
}
|
||||
this[key] = value;
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
Preconditions.CheckNotNullUnconstrained(key, "key");
|
||||
return map.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
Preconditions.CheckNotNullUnconstrained(key, "key");
|
||||
LinkedListNode<KeyValuePair<TKey, TValue>> node;
|
||||
if (map.TryGetValue(key, out node))
|
||||
{
|
||||
map.Remove(key);
|
||||
node.List.Remove(node);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
LinkedListNode<KeyValuePair<TKey, TValue>> node;
|
||||
if (map.TryGetValue(key, out node))
|
||||
{
|
||||
value = node.Value.Value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = default(TValue);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
Preconditions.CheckNotNullUnconstrained(key, "key");
|
||||
TValue value;
|
||||
if (TryGetValue(key, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
set
|
||||
{
|
||||
Preconditions.CheckNotNullUnconstrained(key, "key");
|
||||
// value == null check here is redundant, but avoids boxing.
|
||||
if (value == null && !allowNullValues)
|
||||
{
|
||||
Preconditions.CheckNotNullUnconstrained(value, "value");
|
||||
}
|
||||
LinkedListNode<KeyValuePair<TKey, TValue>> node;
|
||||
var pair = new KeyValuePair<TKey, TValue>(key, value);
|
||||
if (map.TryGetValue(key, out node))
|
||||
{
|
||||
node.Value = pair;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = list.AddLast(pair);
|
||||
map[key] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make these views?
|
||||
public ICollection<TKey> Keys { get { return list.Select(t => t.Key).ToList(); } }
|
||||
public ICollection<TValue> Values { get { return list.Select(t => t.Value).ToList(); } }
|
||||
|
||||
public void Add(IDictionary<TKey, TValue> entries)
|
||||
{
|
||||
Preconditions.CheckNotNull(entries, "entries");
|
||||
foreach (var pair in entries)
|
||||
{
|
||||
Add(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return list.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
list.Clear();
|
||||
map.Clear();
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
TValue value;
|
||||
return TryGetValue(item.Key, out value)
|
||||
&& EqualityComparer<TValue>.Default.Equals(item.Value, value);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (item.Key == null)
|
||||
{
|
||||
throw new ArgumentException("Key is null", "item");
|
||||
}
|
||||
LinkedListNode<KeyValuePair<TKey, TValue>> node;
|
||||
if (map.TryGetValue(item.Key, out node) &&
|
||||
EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.Value))
|
||||
{
|
||||
map.Remove(item.Key);
|
||||
node.List.Remove(node);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not this map allows values to be null.
|
||||
/// </summary>
|
||||
public bool AllowsNullValues { get { return allowNullValues; } }
|
||||
|
||||
public int Count { get { return list.Count; } }
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
return Equals(other as MapField<TKey, TValue>);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var valueComparer = EqualityComparer<TValue>.Default;
|
||||
int hash = 0;
|
||||
foreach (var pair in list)
|
||||
{
|
||||
hash ^= pair.Key.GetHashCode() * 31 + valueComparer.GetHashCode(pair.Value);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public bool Equals(MapField<TKey, TValue> other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (other == this)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (other.Count != this.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var valueComparer = EqualityComparer<TValue>.Default;
|
||||
foreach (var pair in this)
|
||||
{
|
||||
TValue value;
|
||||
if (!other.TryGetValue(pair.Key, out value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!valueComparer.Equals(value, pair.Value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds entries to the map from the given stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is assumed that the stream is initially positioned after the tag specified by the codec.
|
||||
/// This method will continue reading entries from the stream until the end is reached, or
|
||||
/// a different tag is encountered.
|
||||
/// </remarks>
|
||||
/// <param name="input">Stream to read from</param>
|
||||
/// <param name="codec">Codec describing how the key/value pairs are encoded</param>
|
||||
public void AddEntriesFrom(CodedInputStream input, Codec codec)
|
||||
{
|
||||
var adapter = new Codec.MessageAdapter(codec);
|
||||
do
|
||||
{
|
||||
adapter.Reset();
|
||||
input.ReadMessage(adapter);
|
||||
this[adapter.Key] = adapter.Value;
|
||||
} while (input.MaybeConsumeTag(codec.MapTag));
|
||||
}
|
||||
|
||||
public void WriteTo(CodedOutputStream output, Codec codec)
|
||||
{
|
||||
var message = new Codec.MessageAdapter(codec);
|
||||
foreach (var entry in list)
|
||||
{
|
||||
message.Key = entry.Key;
|
||||
message.Value = entry.Value;
|
||||
output.WriteTag(codec.MapTag);
|
||||
output.WriteMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public int CalculateSize(Codec codec)
|
||||
{
|
||||
if (Count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var message = new Codec.MessageAdapter(codec);
|
||||
int size = 0;
|
||||
foreach (var entry in list)
|
||||
{
|
||||
message.Key = entry.Key;
|
||||
message.Value = entry.Value;
|
||||
size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);
|
||||
size += CodedOutputStream.ComputeMessageSize(message);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#region IDictionary explicit interface implementation
|
||||
void IDictionary.Add(object key, object value)
|
||||
{
|
||||
Add((TKey)key, (TValue)value);
|
||||
}
|
||||
|
||||
bool IDictionary.Contains(object key)
|
||||
{
|
||||
if (!(key is TKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ContainsKey((TKey)key);
|
||||
}
|
||||
|
||||
IDictionaryEnumerator IDictionary.GetEnumerator()
|
||||
{
|
||||
return new DictionaryEnumerator(GetEnumerator());
|
||||
}
|
||||
|
||||
void IDictionary.Remove(object key)
|
||||
{
|
||||
Preconditions.CheckNotNull(key, "key");
|
||||
if (!(key is TKey))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Remove((TKey)key);
|
||||
}
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
// This is ugly and slow as heck, but with any luck it will never be used anyway.
|
||||
ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key, pair.Value)).ToList();
|
||||
temp.CopyTo(array, index);
|
||||
}
|
||||
|
||||
bool IDictionary.IsFixedSize { get { return false; } }
|
||||
|
||||
ICollection IDictionary.Keys { get { return (ICollection)Keys; } }
|
||||
|
||||
ICollection IDictionary.Values { get { return (ICollection)Values; } }
|
||||
|
||||
bool ICollection.IsSynchronized { get { return false; } }
|
||||
|
||||
object ICollection.SyncRoot { get { return this; } }
|
||||
|
||||
object IDictionary.this[object key]
|
||||
{
|
||||
get
|
||||
{
|
||||
Preconditions.CheckNotNull(key, "key");
|
||||
if (!(key is TKey))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
TValue value;
|
||||
TryGetValue((TKey)key, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this[(TKey)key] = (TValue)value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private class DictionaryEnumerator : IDictionaryEnumerator
|
||||
{
|
||||
private readonly IEnumerator<KeyValuePair<TKey, TValue>> enumerator;
|
||||
|
||||
internal DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator)
|
||||
{
|
||||
this.enumerator = enumerator;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return enumerator.MoveNext();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
enumerator.Reset();
|
||||
}
|
||||
|
||||
public object Current { get { return Entry; } }
|
||||
public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
|
||||
public object Key { get { return enumerator.Current.Key; } }
|
||||
public object Value { get { return enumerator.Current.Value; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A codec for a specific map field. This contains all the information required to encoded and
|
||||
/// decode the nested messages.
|
||||
/// </summary>
|
||||
public sealed class Codec
|
||||
{
|
||||
private readonly FieldCodec<TKey> keyCodec;
|
||||
private readonly FieldCodec<TValue> valueCodec;
|
||||
private readonly uint mapTag;
|
||||
|
||||
public Codec(FieldCodec<TKey> keyCodec, FieldCodec<TValue> valueCodec, uint mapTag)
|
||||
{
|
||||
this.keyCodec = keyCodec;
|
||||
this.valueCodec = valueCodec;
|
||||
this.mapTag = mapTag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tag used in the enclosing message to indicate map entries.
|
||||
/// </summary>
|
||||
internal uint MapTag { get { return mapTag; } }
|
||||
|
||||
/// <summary>
|
||||
/// A mutable message class, used for parsing and serializing. This
|
||||
/// delegates the work to a codec, but implements the <see cref="IMessage"/> interface
|
||||
/// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.
|
||||
/// This is nested inside Codec as it's tightly coupled to the associated codec,
|
||||
/// and it's simpler if it has direct access to all its fields.
|
||||
/// </summary>
|
||||
internal class MessageAdapter : IMessage
|
||||
{
|
||||
private readonly Codec codec;
|
||||
internal TKey Key { get; set; }
|
||||
internal TValue Value { get; set; }
|
||||
|
||||
internal MessageAdapter(Codec codec)
|
||||
{
|
||||
this.codec = codec;
|
||||
}
|
||||
|
||||
internal void Reset()
|
||||
{
|
||||
Key = codec.keyCodec.DefaultValue;
|
||||
Value = codec.valueCodec.DefaultValue;
|
||||
}
|
||||
|
||||
public void MergeFrom(CodedInputStream input)
|
||||
{
|
||||
uint tag;
|
||||
while (input.ReadTag(out tag))
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
throw InvalidProtocolBufferException.InvalidTag();
|
||||
}
|
||||
if (tag == codec.keyCodec.Tag)
|
||||
{
|
||||
Key = codec.keyCodec.Read(input);
|
||||
}
|
||||
else if (tag == codec.valueCodec.Tag)
|
||||
{
|
||||
Value = codec.valueCodec.Read(input);
|
||||
}
|
||||
else if (WireFormat.IsEndGroupTag(tag))
|
||||
{
|
||||
// TODO(jonskeet): Do we need this? (Given that we don't support groups...)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteTo(CodedOutputStream output)
|
||||
{
|
||||
codec.keyCodec.WriteTagAndValue(output, Key);
|
||||
codec.valueCodec.WriteTagAndValue(output, Value);
|
||||
}
|
||||
|
||||
public int CalculateSize()
|
||||
{
|
||||
return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);
|
||||
}
|
||||
|
||||
MessageDescriptor IMessage.Descriptor { get { return null; } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -29,16 +28,18 @@
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Google.ProtocolBuffers.Collections
|
||||
namespace Google.Protobuf.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Read-only wrapper around another dictionary.
|
||||
/// </summary>
|
||||
public sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
|
||||
internal sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
|
||||
{
|
||||
private readonly IDictionary<TKey, TValue> wrapped;
|
||||
|
447
csharp/src/Google.Protobuf/Collections/RepeatedField.cs
Normal file
447
csharp/src/Google.Protobuf/Collections/RepeatedField.cs
Normal file
@ -0,0 +1,447 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using Google.Protobuf.Reflection;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Google.Protobuf.Compatibility;
|
||||
|
||||
namespace Google.Protobuf.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// The contents of a repeated field: essentially, a collection with some extra
|
||||
/// restrictions (no null values) and capabilities (deep cloning).
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The element type of the repeated field.</typeparam>
|
||||
public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>
|
||||
{
|
||||
private static readonly T[] EmptyArray = new T[0];
|
||||
private const int MinArraySize = 8;
|
||||
|
||||
private T[] array = EmptyArray;
|
||||
private int count = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of this repeated field.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the field type is
|
||||
/// a message type, each element is also cloned; otherwise, it is
|
||||
/// assumed that the field type is primitive (including string and
|
||||
/// bytes, both of which are immutable) and so a simple copy is
|
||||
/// equivalent to a deep clone.
|
||||
/// </remarks>
|
||||
/// <returns>A deep clone of this repeated field.</returns>
|
||||
public RepeatedField<T> Clone()
|
||||
{
|
||||
RepeatedField<T> clone = new RepeatedField<T>();
|
||||
if (array != EmptyArray)
|
||||
{
|
||||
clone.array = (T[])array.Clone();
|
||||
IDeepCloneable<T>[] cloneableArray = clone.array as IDeepCloneable<T>[];
|
||||
if (cloneableArray != null)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
clone.array[i] = cloneableArray[i].Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
clone.count = count;
|
||||
return clone;
|
||||
}
|
||||
|
||||
public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec)
|
||||
{
|
||||
// TODO: Inline some of the Add code, so we can avoid checking the size on every
|
||||
// iteration and the mutability.
|
||||
uint tag = input.LastTag;
|
||||
var reader = codec.ValueReader;
|
||||
// Value types can be packed or not.
|
||||
if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
|
||||
{
|
||||
int length = input.ReadLength();
|
||||
if (length > 0)
|
||||
{
|
||||
int oldLimit = input.PushLimit(length);
|
||||
while (!input.ReachedLimit)
|
||||
{
|
||||
Add(reader(input));
|
||||
}
|
||||
input.PopLimit(oldLimit);
|
||||
}
|
||||
// Empty packed field. Odd, but valid - just ignore.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not packed... (possibly not packable)
|
||||
do
|
||||
{
|
||||
Add(reader(input));
|
||||
} while (input.MaybeConsumeTag(tag));
|
||||
}
|
||||
}
|
||||
|
||||
public int CalculateSize(FieldCodec<T> codec)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint tag = codec.Tag;
|
||||
if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
|
||||
{
|
||||
int dataSize = CalculatePackedDataSize(codec);
|
||||
return CodedOutputStream.ComputeRawVarint32Size(tag) +
|
||||
CodedOutputStream.ComputeLengthSize(dataSize) +
|
||||
dataSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
var sizeCalculator = codec.ValueSizeCalculator;
|
||||
int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
size += sizeCalculator(array[i]);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
private int CalculatePackedDataSize(FieldCodec<T> codec)
|
||||
{
|
||||
int fixedSize = codec.FixedSize;
|
||||
if (fixedSize == 0)
|
||||
{
|
||||
var calculator = codec.ValueSizeCalculator;
|
||||
int tmp = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
tmp += calculator(array[i]);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fixedSize * Count;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteTo(CodedOutputStream output, FieldCodec<T> codec)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var writer = codec.ValueWriter;
|
||||
var tag = codec.Tag;
|
||||
if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited)
|
||||
{
|
||||
// Packed primitive type
|
||||
uint size = (uint)CalculatePackedDataSize(codec);
|
||||
output.WriteTag(tag);
|
||||
output.WriteRawVarint32(size);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
writer(output, array[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not packed: a simple tag/value pair for each value.
|
||||
// Can't use codec.WriteTagAndValue, as that omits default values.
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
output.WriteTag(tag);
|
||||
writer(output, array[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureSize(int size)
|
||||
{
|
||||
if (array.Length < size)
|
||||
{
|
||||
size = Math.Max(size, MinArraySize);
|
||||
int newSize = Math.Max(array.Length * 2, size);
|
||||
var tmp = new T[newSize];
|
||||
Array.Copy(array, 0, tmp, 0, array.Length);
|
||||
array = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException("item");
|
||||
}
|
||||
EnsureSize(count + 1);
|
||||
array[count++] = item;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
array = EmptyArray;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return IndexOf(item) != -1;
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
Array.Copy(this.array, 0, array, arrayIndex, count);
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
int index = IndexOf(item);
|
||||
if (index == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Array.Copy(array, index + 1, array, index, count - index - 1);
|
||||
count--;
|
||||
array[count] = default(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Count { get { return count; } }
|
||||
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
|
||||
public void Add(RepeatedField<T> values)
|
||||
{
|
||||
if (values == null)
|
||||
{
|
||||
throw new ArgumentNullException("values");
|
||||
}
|
||||
EnsureSize(count + values.count);
|
||||
// We know that all the values will be valid, because it's a RepeatedField.
|
||||
Array.Copy(values.array, 0, array, count, values.count);
|
||||
count += values.count;
|
||||
}
|
||||
|
||||
public void Add(IEnumerable<T> values)
|
||||
{
|
||||
if (values == null)
|
||||
{
|
||||
throw new ArgumentNullException("values");
|
||||
}
|
||||
// TODO: Check for ICollection and get the Count?
|
||||
foreach (T item in values)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
yield return array[i];
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as RepeatedField<T>);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
hash = hash * 31 + array[i].GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public bool Equals(RepeatedField<T> other)
|
||||
{
|
||||
if (ReferenceEquals(other, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (other.Count != this.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// TODO(jonskeet): Does this box for enums?
|
||||
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!comparer.Equals(array[i], other.array[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException("item");
|
||||
}
|
||||
// TODO(jonskeet): Does this box for enums?
|
||||
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (comparer.Equals(array[i], item))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException("item");
|
||||
}
|
||||
if (index < 0 || index > count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
EnsureSize(count + 1);
|
||||
Array.Copy(array, index, array, index + 1, count - index);
|
||||
array[index] = item;
|
||||
count++;
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
Array.Copy(array, index + 1, array, index, count - index - 1);
|
||||
count--;
|
||||
array[count] = default(T);
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
return array[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
array[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
#region Explicit interface implementation for IList and ICollection.
|
||||
bool IList.IsFixedSize { get { return false; } }
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
Array.Copy(this.array, 0, array, index, count);
|
||||
}
|
||||
|
||||
bool ICollection.IsSynchronized { get { return false; } }
|
||||
|
||||
object ICollection.SyncRoot { get { return this; } }
|
||||
|
||||
object IList.this[int index]
|
||||
{
|
||||
get { return this[index]; }
|
||||
set { this[index] = (T)value; }
|
||||
}
|
||||
|
||||
int IList.Add(object value)
|
||||
{
|
||||
Add((T) value);
|
||||
return count - 1;
|
||||
}
|
||||
|
||||
bool IList.Contains(object value)
|
||||
{
|
||||
return (value is T && Contains((T)value));
|
||||
}
|
||||
|
||||
int IList.IndexOf(object value)
|
||||
{
|
||||
if (!(value is T))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return IndexOf((T)value);
|
||||
}
|
||||
|
||||
void IList.Insert(int index, object value)
|
||||
{
|
||||
Insert(index, (T) value);
|
||||
}
|
||||
|
||||
void IList.Remove(object value)
|
||||
{
|
||||
if (!(value is T))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Remove((T)value);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,70 +1,64 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes multiple messages to the same stream. Each message is written
|
||||
/// as if it were an element of a repeated field 1 in a larger protocol buffer.
|
||||
/// This class takes no ownership of the stream it is given; it never closes the
|
||||
/// stream.
|
||||
/// </summary>
|
||||
public sealed class MessageStreamWriter<T> where T : IMessage<T>
|
||||
{
|
||||
private readonly CodedOutputStream codedOutput;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance which writes to the given stream.
|
||||
/// </summary>
|
||||
/// <param name="output">Stream to write messages to.</param>
|
||||
public MessageStreamWriter(Stream output)
|
||||
{
|
||||
codedOutput = CodedOutputStream.CreateInstance(output);
|
||||
}
|
||||
|
||||
public void Write(T message)
|
||||
{
|
||||
codedOutput.WriteMessage(1, "item", message);
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
codedOutput.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Google.Protobuf.Compatibility
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="PropertyInfo"/>, effectively providing
|
||||
/// the familiar members from previous desktop framework versions while
|
||||
/// targeting the newer releases, .NET Core etc.
|
||||
/// </summary>
|
||||
internal static class PropertyInfoExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the public getter of a property, or null if there is no such getter
|
||||
/// (either because it's read-only, or the getter isn't public).
|
||||
/// </summary>
|
||||
internal static MethodInfo GetGetMethod(this PropertyInfo target)
|
||||
{
|
||||
var method = target.GetMethod;
|
||||
return method != null && method.IsPublic ? method : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the public setter of a property, or null if there is no such setter
|
||||
/// (either because it's write-only, or the setter isn't public).
|
||||
/// </summary>
|
||||
internal static MethodInfo GetSetMethod(this PropertyInfo target)
|
||||
{
|
||||
var method = target.SetMethod;
|
||||
return method != null && method.IsPublic ? method : null;
|
||||
}
|
||||
}
|
||||
}
|
113
csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
Normal file
113
csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
Normal file
@ -0,0 +1,113 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Google.Protobuf.Compatibility
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods on Type that just proxy to TypeInfo.
|
||||
/// These are used to support the new type system from .NET 4.5, without
|
||||
/// having calls to GetTypeInfo all over the place. While the methods here are meant to be
|
||||
/// broadly compatible with the desktop framework, there are some subtle differences in behaviour - but
|
||||
/// they're not expected to affect our use cases. While the class is internal, that should be fine: we can
|
||||
/// evaluate each new use appropriately.
|
||||
/// </summary>
|
||||
internal static class TypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the target type is a value type, including a nullable value type or an enum, or false
|
||||
/// if it's a reference type (class, delegate, interface - including System.ValueType and System.Enum).
|
||||
/// </summary>
|
||||
internal static bool IsValueType(this Type target)
|
||||
{
|
||||
return target.GetTypeInfo().IsValueType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom
|
||||
/// </summary>
|
||||
internal static bool IsAssignableFrom(this Type target, Type c)
|
||||
{
|
||||
return target.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a representation of the public property associated with the given name in the given type,
|
||||
/// including inherited properties or null if there is no such public property.
|
||||
/// Here, "public property" means a property where either the getter, or the setter, or both, is public.
|
||||
/// </summary>
|
||||
internal static PropertyInfo GetProperty(this Type target, string name)
|
||||
{
|
||||
// GetDeclaredProperty only returns properties declared in the given type, so we need to recurse.
|
||||
while (target != null)
|
||||
{
|
||||
var typeInfo = target.GetTypeInfo();
|
||||
var ret = typeInfo.GetDeclaredProperty(name);
|
||||
if (ret != null && ((ret.CanRead && ret.GetMethod.IsPublic) || (ret.CanWrite && ret.SetMethod.IsPublic)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
target = typeInfo.BaseType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a representation of the public method associated with the given name in the given type,
|
||||
/// including inherited methods.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This has a few differences compared with Type.GetMethod in the desktop framework. It will throw
|
||||
/// if there is an ambiguous match even between a private method and a public one, but it *won't* throw
|
||||
/// if there are two overloads at different levels in the type hierarchy (e.g. class Base declares public void Foo(int) and
|
||||
/// class Child : Base declares public void Foo(long)).
|
||||
/// </remarks>
|
||||
/// <exception cref="AmbiguousMatchException">One type in the hierarchy declared more than one method with the same name</exception>
|
||||
internal static MethodInfo GetMethod(this Type target, string name)
|
||||
{
|
||||
// GetDeclaredMethod only returns methods declared in the given type, so we need to recurse.
|
||||
while (target != null)
|
||||
{
|
||||
var typeInfo = target.GetTypeInfo();
|
||||
var ret = typeInfo.GetDeclaredMethod(name);
|
||||
if (ret != null && ret.IsPublic)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
target = typeInfo.BaseType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
382
csharp/src/Google.Protobuf/FieldCodec.cs
Normal file
382
csharp/src/Google.Protobuf/FieldCodec.cs
Normal file
@ -0,0 +1,382 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory methods for <see cref="FieldCodec{T}"/>.
|
||||
/// </summary>
|
||||
public static class FieldCodec
|
||||
{
|
||||
// TODO: Avoid the "dual hit" of lambda expressions: create open delegates instead. (At least test...)
|
||||
public static FieldCodec<string> ForString(uint tag)
|
||||
{
|
||||
return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<ByteString> ForBytes(uint tag)
|
||||
{
|
||||
return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<bool> ForBool(uint tag)
|
||||
{
|
||||
return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<int> ForInt32(uint tag)
|
||||
{
|
||||
return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<int> ForSInt32(uint tag)
|
||||
{
|
||||
return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<uint> ForFixed32(uint tag)
|
||||
{
|
||||
return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<int> ForSFixed32(uint tag)
|
||||
{
|
||||
return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<uint> ForUInt32(uint tag)
|
||||
{
|
||||
return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<long> ForInt64(uint tag)
|
||||
{
|
||||
return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<long> ForSInt64(uint tag)
|
||||
{
|
||||
return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<ulong> ForFixed64(uint tag)
|
||||
{
|
||||
return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<long> ForSFixed64(uint tag)
|
||||
{
|
||||
return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<ulong> ForUInt64(uint tag)
|
||||
{
|
||||
return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<float> ForFloat(uint tag)
|
||||
{
|
||||
return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<double> ForDouble(uint tag)
|
||||
{
|
||||
return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag);
|
||||
}
|
||||
|
||||
// Enums are tricky. We can probably use expression trees to build these delegates automatically,
|
||||
// but it's easy to generate the code for it.
|
||||
public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
|
||||
{
|
||||
return new FieldCodec<T>(input => fromInt32(
|
||||
input.ReadEnum()),
|
||||
(output, value) => output.WriteEnum(toInt32(value)),
|
||||
value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag);
|
||||
}
|
||||
|
||||
public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : IMessage<T>
|
||||
{
|
||||
return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; },
|
||||
(output, value) => output.WriteMessage(value), message => CodedOutputStream.ComputeMessageSize(message), tag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a codec for a wrapper type of a class - which must be string or ByteString.
|
||||
/// </summary>
|
||||
public static FieldCodec<T> ForClassWrapper<T>(uint tag) where T : class
|
||||
{
|
||||
var nestedCodec = WrapperCodecs.GetCodec<T>();
|
||||
return new FieldCodec<T>(
|
||||
input => WrapperCodecs.Read<T>(input, nestedCodec),
|
||||
(output, value) => WrapperCodecs.Write<T>(output, value, nestedCodec),
|
||||
value => WrapperCodecs.CalculateSize<T>(value, nestedCodec),
|
||||
tag,
|
||||
null); // Default value for the wrapper
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a codec for a wrapper type of a struct - which must be Int32, Int64, UInt32, UInt64,
|
||||
/// Bool, Single or Double.
|
||||
/// </summary>
|
||||
public static FieldCodec<T?> ForStructWrapper<T>(uint tag) where T : struct
|
||||
{
|
||||
var nestedCodec = WrapperCodecs.GetCodec<T>();
|
||||
return new FieldCodec<T?>(
|
||||
input => WrapperCodecs.Read<T>(input, nestedCodec),
|
||||
(output, value) => WrapperCodecs.Write<T>(output, value.Value, nestedCodec),
|
||||
value => value == null ? 0 : WrapperCodecs.CalculateSize<T>(value.Value, nestedCodec),
|
||||
tag,
|
||||
null); // Default value for the wrapper
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper code to create codecs for wrapper types.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Somewhat ugly with all the static methods, but the conversions involved to/from nullable types make it
|
||||
/// slightly tricky to improve. So long as we keep the public API (ForClassWrapper, ForStructWrapper) in place,
|
||||
/// we can refactor later if we come up with something cleaner.
|
||||
/// </remarks>
|
||||
private static class WrapperCodecs
|
||||
{
|
||||
// All the field numbers are the same (1).
|
||||
private const int WrapperValueFieldNumber = Google.Protobuf.WellKnownTypes.Int32Value.ValueFieldNumber;
|
||||
|
||||
private static readonly Dictionary<Type, object> Codecs = new Dictionary<Type, object>
|
||||
{
|
||||
{ typeof(bool), ForBool(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
|
||||
{ typeof(int), ForInt32(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
|
||||
{ typeof(long), ForInt64(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
|
||||
{ typeof(uint), ForUInt32(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
|
||||
{ typeof(ulong), ForUInt64(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
|
||||
{ typeof(float), ForFloat(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Fixed32)) },
|
||||
{ typeof(double), ForDouble(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.Fixed64)) },
|
||||
{ typeof(string), ForString(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) },
|
||||
{ typeof(ByteString), ForBytes(WireFormat.MakeTag(WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns a field codec which effectively wraps a value of type T in a message.
|
||||
///
|
||||
/// </summary>
|
||||
internal static FieldCodec<T> GetCodec<T>()
|
||||
{
|
||||
object value;
|
||||
if (!Codecs.TryGetValue(typeof(T), out value))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid type argument requested for wrapper codec: " + typeof(T));
|
||||
}
|
||||
return (FieldCodec<T>) value;
|
||||
}
|
||||
|
||||
internal static T Read<T>(CodedInputStream input, FieldCodec<T> codec)
|
||||
{
|
||||
int length = input.ReadLength();
|
||||
int oldLimit = input.PushLimit(length);
|
||||
|
||||
uint tag;
|
||||
T value = codec.DefaultValue;
|
||||
while (input.ReadTag(out tag))
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
throw InvalidProtocolBufferException.InvalidTag();
|
||||
}
|
||||
if (tag == codec.Tag)
|
||||
{
|
||||
value = codec.Read(input);
|
||||
}
|
||||
if (WireFormat.IsEndGroupTag(tag))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
input.CheckLastTagWas(0);
|
||||
input.PopLimit(oldLimit);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
internal static void Write<T>(CodedOutputStream output, T value, FieldCodec<T> codec)
|
||||
{
|
||||
output.WriteLength(codec.CalculateSizeWithTag(value));
|
||||
codec.WriteTagAndValue(output, value);
|
||||
}
|
||||
|
||||
internal static int CalculateSize<T>(T value, FieldCodec<T> codec)
|
||||
{
|
||||
int fieldLength = codec.CalculateSizeWithTag(value);
|
||||
return CodedOutputStream.ComputeLengthSize(fieldLength) + fieldLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An encode/decode pair for a single field. This effectively encapsulates
|
||||
/// all the information needed to read or write the field value from/to a coded
|
||||
/// stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This never writes default values to the stream, and is not currently designed
|
||||
/// to play well with packed arrays.
|
||||
/// </remarks>
|
||||
public sealed class FieldCodec<T>
|
||||
{
|
||||
private static readonly T DefaultDefault;
|
||||
|
||||
static FieldCodec()
|
||||
{
|
||||
if (typeof(T) == typeof(string))
|
||||
{
|
||||
DefaultDefault = (T)(object)"";
|
||||
}
|
||||
else if (typeof(T) == typeof(ByteString))
|
||||
{
|
||||
DefaultDefault = (T)(object)ByteString.Empty;
|
||||
}
|
||||
// Otherwise it's the default value of the CLR type
|
||||
}
|
||||
|
||||
private static Func<T, bool> CreateDefaultValueCheck<TTmp>(Func<TTmp, bool> check)
|
||||
{
|
||||
return (Func<T, bool>)(object)check;
|
||||
}
|
||||
|
||||
private readonly Func<CodedInputStream, T> reader;
|
||||
private readonly Action<CodedOutputStream, T> writer;
|
||||
private readonly Func<T, int> sizeCalculator;
|
||||
private readonly uint tag;
|
||||
private readonly int tagSize;
|
||||
private readonly int fixedSize;
|
||||
// Default value for this codec. Usually the same for every instance of the same type, but
|
||||
// for string/ByteString wrapper fields the codec's default value is null, whereas for
|
||||
// other string/ByteString fields it's "" or ByteString.Empty.
|
||||
private readonly T defaultValue;
|
||||
|
||||
internal FieldCodec(
|
||||
Func<CodedInputStream, T> reader,
|
||||
Action<CodedOutputStream, T> writer,
|
||||
Func<T, int> sizeCalculator,
|
||||
uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault)
|
||||
{
|
||||
}
|
||||
|
||||
internal FieldCodec(
|
||||
Func<CodedInputStream, T> reader,
|
||||
Action<CodedOutputStream, T> writer,
|
||||
Func<T, int> sizeCalculator,
|
||||
uint tag,
|
||||
T defaultValue)
|
||||
{
|
||||
this.reader = reader;
|
||||
this.writer = writer;
|
||||
this.sizeCalculator = sizeCalculator;
|
||||
this.fixedSize = 0;
|
||||
this.tag = tag;
|
||||
this.defaultValue = defaultValue;
|
||||
tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
|
||||
}
|
||||
|
||||
internal FieldCodec(
|
||||
Func<CodedInputStream, T> reader,
|
||||
Action<CodedOutputStream, T> writer,
|
||||
int fixedSize,
|
||||
uint tag)
|
||||
{
|
||||
this.reader = reader;
|
||||
this.writer = writer;
|
||||
this.sizeCalculator = _ => fixedSize;
|
||||
this.fixedSize = fixedSize;
|
||||
this.tag = tag;
|
||||
tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the size calculator for just a value.
|
||||
/// </summary>
|
||||
internal Func<T, int> ValueSizeCalculator { get { return sizeCalculator; } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a delegate to write a value (unconditionally) to a coded output stream.
|
||||
/// </summary>
|
||||
internal Action<CodedOutputStream, T> ValueWriter { get { return writer; } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a delegate to read a value from a coded input stream. It is assumed that
|
||||
/// the stream is already positioned on the appropriate tag.
|
||||
/// </summary>
|
||||
internal Func<CodedInputStream, T> ValueReader { get { return reader; } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the fixed size for an entry, or 0 if sizes vary.
|
||||
/// </summary>
|
||||
internal int FixedSize { get { return fixedSize; } }
|
||||
|
||||
public uint Tag { get { return tag; } }
|
||||
|
||||
public T DefaultValue { get { return defaultValue; } }
|
||||
|
||||
/// <summary>
|
||||
/// Write a tag and the given value, *if* the value is not the default.
|
||||
/// </summary>
|
||||
public void WriteTagAndValue(CodedOutputStream output, T value)
|
||||
{
|
||||
if (!IsDefault(value))
|
||||
{
|
||||
output.WriteTag(tag);
|
||||
writer(output, value);
|
||||
}
|
||||
}
|
||||
|
||||
public T Read(CodedInputStream input)
|
||||
{
|
||||
return reader(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the size required to write the given value, with a tag,
|
||||
/// if the value is not the default.
|
||||
/// </summary>
|
||||
public int CalculateSizeWithTag(T value)
|
||||
{
|
||||
return IsDefault(value) ? 0 : sizeCalculator(value) + tagSize;
|
||||
}
|
||||
|
||||
private bool IsDefault(T value)
|
||||
{
|
||||
return EqualityComparer<T>.Default.Equals(value, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -29,24 +28,23 @@
|
||||
// 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.
|
||||
namespace Google.ProtocolBuffers.DescriptorProtos
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <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.
|
||||
/// Class containing helpful workarounds for various platform compatibility
|
||||
/// </summary>
|
||||
/// <typeparam name="TOptions">The associated options protocol buffer type</typeparam>
|
||||
public interface IDescriptorProto<TOptions>
|
||||
internal static class FrameworkPortability
|
||||
{
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The options for this descriptor.
|
||||
/// </summary>
|
||||
TOptions Options { get; }
|
||||
// TODO(jtattermusch): is this still a thing?
|
||||
// The value of RegexOptions.Compiled is 8. We can test for the presence at
|
||||
// execution time using Enum.IsDefined, so a single build will do the right thing
|
||||
// on each platform.
|
||||
internal static readonly RegexOptions CompiledRegexWhereAvailable =
|
||||
Enum.IsDefined(typeof(RegexOptions), 8) ? (RegexOptions)8 : RegexOptions.None;
|
||||
}
|
||||
}
|
140
csharp/src/Google.Protobuf/Google.Protobuf.csproj
Normal file
140
csharp/src/Google.Protobuf/Google.Protobuf.csproj
Normal file
@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" 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>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.Protobuf</RootNamespace>
|
||||
<AssemblyName>Google.Protobuf</AssemblyName>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
|
||||
<DocumentationFile>bin\Debug\Google.Protobuf.xml</DocumentationFile>
|
||||
<NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
|
||||
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
|
||||
<NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\ReleaseSigned</OutputPath>
|
||||
<IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
|
||||
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
|
||||
<NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
|
||||
<DefineConstants>TRACE;SIGNED</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<SignAssembly>True</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ByteArray.cs" />
|
||||
<Compile Include="ByteString.cs" />
|
||||
<Compile Include="CodedOutputStream.ComputeSize.cs" />
|
||||
<Compile Include="CodedInputStream.cs" />
|
||||
<Compile Include="CodedOutputStream.cs" />
|
||||
<Compile Include="Collections\MapField.cs" />
|
||||
<Compile Include="Collections\ReadOnlyDictionary.cs" />
|
||||
<Compile Include="Collections\RepeatedField.cs" />
|
||||
<Compile Include="Compatibility\PropertyInfoExtensions.cs" />
|
||||
<Compile Include="Compatibility\TypeExtensions.cs" />
|
||||
<Compile Include="FieldCodec.cs" />
|
||||
<Compile Include="FrameworkPortability.cs" />
|
||||
<Compile Include="JsonFormatter.cs" />
|
||||
<Compile Include="MessageExtensions.cs" />
|
||||
<Compile Include="IMessage.cs" />
|
||||
<Compile Include="InvalidProtocolBufferException.cs" />
|
||||
<Compile Include="LimitedInputStream.cs" />
|
||||
<Compile Include="MessageParser.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Reflection\DescriptorBase.cs" />
|
||||
<Compile Include="Reflection\DescriptorPool.cs" />
|
||||
<Compile Include="Reflection\DescriptorProtoFile.cs" />
|
||||
<Compile Include="Reflection\DescriptorUtil.cs" />
|
||||
<Compile Include="Reflection\DescriptorValidationException.cs" />
|
||||
<Compile Include="Reflection\EnumDescriptor.cs" />
|
||||
<Compile Include="Reflection\EnumValueDescriptor.cs" />
|
||||
<Compile Include="Reflection\FieldAccessorBase.cs" />
|
||||
<Compile Include="Reflection\FieldDescriptor.cs" />
|
||||
<Compile Include="Reflection\FieldType.cs" />
|
||||
<Compile Include="Reflection\FileDescriptor.cs" />
|
||||
<Compile Include="Reflection\GeneratedCodeInfo.cs" />
|
||||
<Compile Include="Reflection\IDescriptor.cs" />
|
||||
<Compile Include="Reflection\IFieldAccessor.cs" />
|
||||
<Compile Include="Reflection\MapFieldAccessor.cs" />
|
||||
<Compile Include="Reflection\MessageDescriptor.cs" />
|
||||
<Compile Include="Reflection\MethodDescriptor.cs" />
|
||||
<Compile Include="Reflection\OneofAccessor.cs" />
|
||||
<Compile Include="Reflection\OneofDescriptor.cs" />
|
||||
<Compile Include="Reflection\PackageDescriptor.cs" />
|
||||
<Compile Include="Reflection\PartialClasses.cs" />
|
||||
<Compile Include="Reflection\ReflectionUtil.cs" />
|
||||
<Compile Include="Reflection\RepeatedFieldAccessor.cs" />
|
||||
<Compile Include="Reflection\ServiceDescriptor.cs" />
|
||||
<Compile Include="Reflection\SingleFieldAccessor.cs" />
|
||||
<Compile Include="Preconditions.cs" />
|
||||
<Compile Include="WellKnownTypes\Any.cs" />
|
||||
<Compile Include="WellKnownTypes\Api.cs" />
|
||||
<Compile Include="WellKnownTypes\Duration.cs" />
|
||||
<Compile Include="WellKnownTypes\DurationPartial.cs" />
|
||||
<Compile Include="WellKnownTypes\Empty.cs" />
|
||||
<Compile Include="WellKnownTypes\FieldMask.cs" />
|
||||
<Compile Include="WellKnownTypes\SourceContext.cs" />
|
||||
<Compile Include="WellKnownTypes\Struct.cs" />
|
||||
<Compile Include="WellKnownTypes\TimeExtensions.cs" />
|
||||
<Compile Include="WellKnownTypes\Timestamp.cs" />
|
||||
<Compile Include="WellKnownTypes\TimestampPartial.cs" />
|
||||
<Compile Include="WellKnownTypes\Type.cs" />
|
||||
<Compile Include="WellKnownTypes\Wrappers.cs" />
|
||||
<Compile Include="WireFormat.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Google.Protobuf.nuspec" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.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>
|
36
csharp/src/Google.Protobuf/Google.Protobuf.nuspec
Normal file
36
csharp/src/Google.Protobuf/Google.Protobuf.nuspec
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Google.Protobuf</id>
|
||||
<title>Google Protocol Buffers C#</title>
|
||||
<summary>C# runtime library for Protocol Buffers - Google's data interchange format.</summary>
|
||||
<description>See project site for more info.</description>
|
||||
<version>3.0.0-alpha4</version>
|
||||
<authors>Google Inc.</authors>
|
||||
<owners>protobuf-packages</owners>
|
||||
<licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>
|
||||
<projectUrl>https://github.com/google/protobuf</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<releaseNotes>C# proto3 support</releaseNotes>
|
||||
<copyright>Copyright 2015, Google Inc.</copyright>
|
||||
<tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/portable-net45+netcore45+wpa81+wp8" />
|
||||
<file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" />
|
||||
<file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" />
|
||||
<file src="**\*.cs" target="src" />
|
||||
<file src="..\..\..\cmake\Release\protoc.exe" target="tools" />
|
||||
<file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\api.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\duration.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\empty.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\struct.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\type.proto" target="tools\google\protobuf" />
|
||||
<file src="..\..\..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" />
|
||||
</files>
|
||||
</package>
|
110
csharp/src/Google.Protobuf/IMessage.cs
Normal file
110
csharp/src/Google.Protobuf/IMessage.cs
Normal file
@ -0,0 +1,110 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Google.Protobuf.Reflection;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
|
||||
// TODO(jonskeet): Do we want a "weak" (non-generic) version of IReflectedMessage?
|
||||
// TODO(jonskeet): Split these interfaces into separate files when we're happy with them.
|
||||
|
||||
/// <summary>
|
||||
/// Interface for a Protocol Buffers message, supporting
|
||||
/// basic operations required for serialization.
|
||||
/// </summary>
|
||||
public interface IMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Merges the data from the specified coded input stream with the current message.
|
||||
/// </summary>
|
||||
/// <remarks>See the user guide for precise merge semantics.</remarks>
|
||||
/// <param name="input"></param>
|
||||
void MergeFrom(CodedInputStream input);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the data to the given coded output stream.
|
||||
/// </summary>
|
||||
/// <param name="output">Coded output stream to write the data to. Must not be null.</param>
|
||||
void WriteTo(CodedOutputStream output);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the size of this message in Protocol Buffer wire format, in bytes.
|
||||
/// </summary>
|
||||
/// <returns>The number of bytes required to write this message
|
||||
/// to a coded output stream.</returns>
|
||||
int CalculateSize();
|
||||
|
||||
/// <summary>
|
||||
/// Descriptor for this message. All instances are expected to return the same descriptor,
|
||||
/// and for generated types this will be an explicitly-implemented member, returning the
|
||||
/// same value as the static property declared on the type.
|
||||
/// </summary>
|
||||
MessageDescriptor Descriptor { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic interface for a Protocol Buffers message,
|
||||
/// where the type parameter is expected to be the same type as
|
||||
/// the implementation class.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The message type.</typeparam>
|
||||
public interface IMessage<T> : IMessage, IEquatable<T>, IDeepCloneable<T> where T : IMessage<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Merges the given message into this one.
|
||||
/// </summary>
|
||||
/// <remarks>See the user guide for precise merge semantics.</remarks>
|
||||
/// <param name="message">The message to merge with this one. Must not be null.</param>
|
||||
void MergeFrom(T message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic interface for a deeply cloneable type.
|
||||
/// <summary>
|
||||
/// <remarks>
|
||||
/// All generated messages implement this interface, but so do some non-message types.
|
||||
/// Additionally, due to the type constraint on <c>T</c> in <see cref="IMessage{T}"/>,
|
||||
/// it is simpler to keep this as a separate interface.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type itself, returned by the <see cref="Clone"/> method.</typeparam>
|
||||
public interface IDeepCloneable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a deep clone of this object.
|
||||
/// </summary>
|
||||
/// <returns>A deep clone of this object.</returns>
|
||||
T Clone();
|
||||
}
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
#region Copyright notice and license
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://github.com/jskeet/dotnet-protobufs/
|
||||
// Original C++/Java/Python code:
|
||||
// http://code.google.com/p/protobuf/
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
@ -31,12 +28,11 @@
|
||||
// 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.
|
||||
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Google.ProtocolBuffers
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Thrown when a protocol message being parsed is invalid in some way,
|
||||
@ -83,12 +79,6 @@ namespace Google.ProtocolBuffers
|
||||
"Protocol message end-group tag did not match expected tag.");
|
||||
}
|
||||
|
||||
internal static InvalidProtocolBufferException InvalidWireType()
|
||||
{
|
||||
return new InvalidProtocolBufferException(
|
||||
"Protocol message tag had invalid wire type.");
|
||||
}
|
||||
|
||||
internal static InvalidProtocolBufferException RecursionLimitExceeded()
|
||||
{
|
||||
return new InvalidProtocolBufferException(
|
777
csharp/src/Google.Protobuf/JsonFormatter.cs
Normal file
777
csharp/src/Google.Protobuf/JsonFormatter.cs
Normal file
@ -0,0 +1,777 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Google.Protobuf.Reflection;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using System.Linq;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Reflection-based converter from messages to JSON.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Instances of this class are thread-safe, with no mutable state.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This is a simple start to get JSON formatting working. As it's reflection-based,
|
||||
/// it's not as quick as baking calls into generated messages - but is a simpler implementation.
|
||||
/// (This code is generally not heavily optimized.)
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class JsonFormatter
|
||||
{
|
||||
private static JsonFormatter defaultInstance = new JsonFormatter(Settings.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a formatter using the default settings.
|
||||
/// </summary>
|
||||
public static JsonFormatter Default { get { return defaultInstance; } }
|
||||
|
||||
/// <summary>
|
||||
/// The JSON representation of the first 160 characters of Unicode.
|
||||
/// Empty strings are replaced by the static constructor.
|
||||
/// </summary>
|
||||
private static readonly string[] CommonRepresentations = {
|
||||
// C0 (ASCII and derivatives) control characters
|
||||
"\\u0000", "\\u0001", "\\u0002", "\\u0003", // 0x00
|
||||
"\\u0004", "\\u0005", "\\u0006", "\\u0007",
|
||||
"\\b", "\\t", "\\n", "\\u000b",
|
||||
"\\f", "\\r", "\\u000e", "\\u000f",
|
||||
"\\u0010", "\\u0011", "\\u0012", "\\u0013", // 0x10
|
||||
"\\u0014", "\\u0015", "\\u0016", "\\u0017",
|
||||
"\\u0018", "\\u0019", "\\u001a", "\\u001b",
|
||||
"\\u001c", "\\u001d", "\\u001e", "\\u001f",
|
||||
// Escaping of " and \ are required by www.json.org string definition.
|
||||
// Escaping of < and > are required for HTML security.
|
||||
"", "", "\\\"", "", "", "", "", "", // 0x20
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", // 0x30
|
||||
"", "", "", "", "\\u003c", "", "\\u003e", "",
|
||||
"", "", "", "", "", "", "", "", // 0x40
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", // 0x50
|
||||
"", "", "", "", "\\\\", "", "", "",
|
||||
"", "", "", "", "", "", "", "", // 0x60
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", // 0x70
|
||||
"", "", "", "", "", "", "", "\\u007f",
|
||||
// C1 (ISO 8859 and Unicode) extended control characters
|
||||
"\\u0080", "\\u0081", "\\u0082", "\\u0083", // 0x80
|
||||
"\\u0084", "\\u0085", "\\u0086", "\\u0087",
|
||||
"\\u0088", "\\u0089", "\\u008a", "\\u008b",
|
||||
"\\u008c", "\\u008d", "\\u008e", "\\u008f",
|
||||
"\\u0090", "\\u0091", "\\u0092", "\\u0093", // 0x90
|
||||
"\\u0094", "\\u0095", "\\u0096", "\\u0097",
|
||||
"\\u0098", "\\u0099", "\\u009a", "\\u009b",
|
||||
"\\u009c", "\\u009d", "\\u009e", "\\u009f"
|
||||
};
|
||||
|
||||
static JsonFormatter()
|
||||
{
|
||||
for (int i = 0; i < CommonRepresentations.Length; i++)
|
||||
{
|
||||
if (CommonRepresentations[i] == "")
|
||||
{
|
||||
CommonRepresentations[i] = ((char) i).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Settings settings;
|
||||
|
||||
public JsonFormatter(Settings settings)
|
||||
{
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public string Format(IMessage message)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (message.Descriptor.IsWellKnownType)
|
||||
{
|
||||
WriteWellKnownTypeValue(builder, message.Descriptor, message, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteMessage(builder, message);
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private void WriteMessage(StringBuilder builder, IMessage message)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
WriteNull(builder);
|
||||
return;
|
||||
}
|
||||
builder.Append("{ ");
|
||||
var fields = message.Descriptor.Fields;
|
||||
bool first = true;
|
||||
// First non-oneof fields
|
||||
foreach (var field in fields.InFieldNumberOrder())
|
||||
{
|
||||
var accessor = field.Accessor;
|
||||
// Oneofs are written later
|
||||
// TODO: Change to write out fields in order, interleaving oneofs appropriately (as per binary format)
|
||||
if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Omit default values unless we're asked to format them, or they're oneofs (where the default
|
||||
// value is still formatted regardless, because that's how we preserve the oneof case).
|
||||
object value = accessor.GetValue(message);
|
||||
if (field.ContainingOneof == null && !settings.FormatDefaultValues && IsDefaultValue(accessor, value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Omit awkward (single) values such as unknown enum values
|
||||
if (!field.IsRepeated && !field.IsMap && !CanWriteSingleValue(accessor.Descriptor, value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Okay, all tests complete: let's write the field value...
|
||||
if (!first)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
WriteString(builder, ToCamelCase(accessor.Descriptor.Name));
|
||||
builder.Append(": ");
|
||||
WriteValue(builder, accessor, value);
|
||||
first = false;
|
||||
}
|
||||
builder.Append(first ? "}" : " }");
|
||||
}
|
||||
|
||||
// Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase
|
||||
internal static string ToCamelCase(string input)
|
||||
{
|
||||
bool capitalizeNext = false;
|
||||
bool wasCap = true;
|
||||
bool isCap = false;
|
||||
bool firstWord = true;
|
||||
StringBuilder result = new StringBuilder(input.Length);
|
||||
|
||||
for (int i = 0; i < input.Length; i++, wasCap = isCap)
|
||||
{
|
||||
isCap = char.IsUpper(input[i]);
|
||||
if (input[i] == '_')
|
||||
{
|
||||
capitalizeNext = true;
|
||||
if (result.Length != 0)
|
||||
{
|
||||
firstWord = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (firstWord)
|
||||
{
|
||||
// Consider when the current character B is capitalized,
|
||||
// first word ends when:
|
||||
// 1) following a lowercase: "...aB..."
|
||||
// 2) followed by a lowercase: "...ABc..."
|
||||
if (result.Length != 0 && isCap &&
|
||||
(!wasCap || (i + 1 < input.Length && char.IsLower(input[i + 1]))))
|
||||
{
|
||||
firstWord = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(char.ToLowerInvariant(input[i]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (capitalizeNext)
|
||||
{
|
||||
capitalizeNext = false;
|
||||
if (char.IsLower(input[i]))
|
||||
{
|
||||
result.Append(char.ToUpperInvariant(input[i]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.Append(input[i]);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private static void WriteNull(StringBuilder builder)
|
||||
{
|
||||
builder.Append("null");
|
||||
}
|
||||
|
||||
private static bool IsDefaultValue(IFieldAccessor accessor, object value)
|
||||
{
|
||||
if (accessor.Descriptor.IsMap)
|
||||
{
|
||||
IDictionary dictionary = (IDictionary) value;
|
||||
return dictionary.Count == 0;
|
||||
}
|
||||
if (accessor.Descriptor.IsRepeated)
|
||||
{
|
||||
IList list = (IList) value;
|
||||
return list.Count == 0;
|
||||
}
|
||||
switch (accessor.Descriptor.FieldType)
|
||||
{
|
||||
case FieldType.Bool:
|
||||
return (bool) value == false;
|
||||
case FieldType.Bytes:
|
||||
return (ByteString) value == ByteString.Empty;
|
||||
case FieldType.String:
|
||||
return (string) value == "";
|
||||
case FieldType.Double:
|
||||
return (double) value == 0.0;
|
||||
case FieldType.SInt32:
|
||||
case FieldType.Int32:
|
||||
case FieldType.SFixed32:
|
||||
case FieldType.Enum:
|
||||
return (int) value == 0;
|
||||
case FieldType.Fixed32:
|
||||
case FieldType.UInt32:
|
||||
return (uint) value == 0;
|
||||
case FieldType.Fixed64:
|
||||
case FieldType.UInt64:
|
||||
return (ulong) value == 0;
|
||||
case FieldType.SFixed64:
|
||||
case FieldType.Int64:
|
||||
case FieldType.SInt64:
|
||||
return (long) value == 0;
|
||||
case FieldType.Float:
|
||||
return (float) value == 0f;
|
||||
case FieldType.Message:
|
||||
case FieldType.Group: // Never expect to get this, but...
|
||||
return value == null;
|
||||
default:
|
||||
throw new ArgumentException("Invalid field type");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteValue(StringBuilder builder, IFieldAccessor accessor, object value)
|
||||
{
|
||||
if (accessor.Descriptor.IsMap)
|
||||
{
|
||||
WriteDictionary(builder, accessor, (IDictionary) value);
|
||||
}
|
||||
else if (accessor.Descriptor.IsRepeated)
|
||||
{
|
||||
WriteList(builder, accessor, (IList) value);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteSingleValue(builder, accessor.Descriptor, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteSingleValue(StringBuilder builder, FieldDescriptor descriptor, object value)
|
||||
{
|
||||
switch (descriptor.FieldType)
|
||||
{
|
||||
case FieldType.Bool:
|
||||
builder.Append((bool) value ? "true" : "false");
|
||||
break;
|
||||
case FieldType.Bytes:
|
||||
// Nothing in Base64 needs escaping
|
||||
builder.Append('"');
|
||||
builder.Append(((ByteString) value).ToBase64());
|
||||
builder.Append('"');
|
||||
break;
|
||||
case FieldType.String:
|
||||
WriteString(builder, (string) value);
|
||||
break;
|
||||
case FieldType.Fixed32:
|
||||
case FieldType.UInt32:
|
||||
case FieldType.SInt32:
|
||||
case FieldType.Int32:
|
||||
case FieldType.SFixed32:
|
||||
{
|
||||
IFormattable formattable = (IFormattable) value;
|
||||
builder.Append(formattable.ToString("d", CultureInfo.InvariantCulture));
|
||||
break;
|
||||
}
|
||||
case FieldType.Enum:
|
||||
EnumValueDescriptor enumValue = descriptor.EnumType.FindValueByNumber((int) value);
|
||||
// We will already have validated that this is a known value.
|
||||
WriteString(builder, enumValue.Name);
|
||||
break;
|
||||
case FieldType.Fixed64:
|
||||
case FieldType.UInt64:
|
||||
case FieldType.SFixed64:
|
||||
case FieldType.Int64:
|
||||
case FieldType.SInt64:
|
||||
{
|
||||
builder.Append('"');
|
||||
IFormattable formattable = (IFormattable) value;
|
||||
builder.Append(formattable.ToString("d", CultureInfo.InvariantCulture));
|
||||
builder.Append('"');
|
||||
break;
|
||||
}
|
||||
case FieldType.Double:
|
||||
case FieldType.Float:
|
||||
string text = ((IFormattable) value).ToString("r", CultureInfo.InvariantCulture);
|
||||
if (text == "NaN" || text == "Infinity" || text == "-Infinity")
|
||||
{
|
||||
builder.Append('"');
|
||||
builder.Append(text);
|
||||
builder.Append('"');
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(text);
|
||||
}
|
||||
break;
|
||||
case FieldType.Message:
|
||||
case FieldType.Group: // Never expect to get this, but...
|
||||
if (descriptor.MessageType.IsWellKnownType)
|
||||
{
|
||||
WriteWellKnownTypeValue(builder, descriptor.MessageType, value, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteMessage(builder, (IMessage) value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Invalid field type: " + descriptor.FieldType);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Central interception point for well-known type formatting. Any well-known types which
|
||||
/// don't need special handling can fall back to WriteMessage. We avoid assuming that the
|
||||
/// values are using the embedded well-known types, in order to allow for dynamic messages
|
||||
/// in the future.
|
||||
/// </summary>
|
||||
private void WriteWellKnownTypeValue(StringBuilder builder, MessageDescriptor descriptor, object value, bool inField)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
WriteNull(builder);
|
||||
return;
|
||||
}
|
||||
// For wrapper types, the value will be the (possibly boxed) "native" value,
|
||||
// so we can write it as if we were unconditionally writing the Value field for the wrapper type.
|
||||
if (descriptor.File == Int32Value.Descriptor.File)
|
||||
{
|
||||
WriteSingleValue(builder, descriptor.FindFieldByNumber(1), value);
|
||||
return;
|
||||
}
|
||||
if (descriptor.FullName == Timestamp.Descriptor.FullName)
|
||||
{
|
||||
MaybeWrapInString(builder, value, WriteTimestamp, inField);
|
||||
return;
|
||||
}
|
||||
if (descriptor.FullName == Duration.Descriptor.FullName)
|
||||
{
|
||||
MaybeWrapInString(builder, value, WriteDuration, inField);
|
||||
return;
|
||||
}
|
||||
if (descriptor.FullName == FieldMask.Descriptor.FullName)
|
||||
{
|
||||
MaybeWrapInString(builder, value, WriteFieldMask, inField);
|
||||
return;
|
||||
}
|
||||
if (descriptor.FullName == Struct.Descriptor.FullName)
|
||||
{
|
||||
WriteStruct(builder, (IMessage) value);
|
||||
return;
|
||||
}
|
||||
if (descriptor.FullName == ListValue.Descriptor.FullName)
|
||||
{
|
||||
var fieldAccessor = descriptor.Fields[ListValue.ValuesFieldNumber].Accessor;
|
||||
WriteList(builder, fieldAccessor, (IList) fieldAccessor.GetValue(value));
|
||||
return;
|
||||
}
|
||||
if (descriptor.FullName == Value.Descriptor.FullName)
|
||||
{
|
||||
WriteStructFieldValue(builder, (IMessage) value);
|
||||
return;
|
||||
}
|
||||
WriteMessage(builder, (IMessage) value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some well-known types end up as string values... so they need wrapping in quotes, but only
|
||||
/// when they're being used as fields within another message.
|
||||
/// </summary>
|
||||
private void MaybeWrapInString(StringBuilder builder, object value, Action<StringBuilder, IMessage> action, bool inField)
|
||||
{
|
||||
if (inField)
|
||||
{
|
||||
builder.Append('"');
|
||||
action(builder, (IMessage) value);
|
||||
builder.Append('"');
|
||||
}
|
||||
else
|
||||
{
|
||||
action(builder, (IMessage) value);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteTimestamp(StringBuilder builder, IMessage value)
|
||||
{
|
||||
// TODO: In the common case where this *is* using the built-in Timestamp type, we could
|
||||
// avoid all the reflection at this point, by casting to Timestamp. In the interests of
|
||||
// avoiding subtle bugs, don't do that until we've implemented DynamicMessage so that we can prove
|
||||
// it still works in that case.
|
||||
int nanos = (int) value.Descriptor.Fields[Timestamp.NanosFieldNumber].Accessor.GetValue(value);
|
||||
long seconds = (long) value.Descriptor.Fields[Timestamp.SecondsFieldNumber].Accessor.GetValue(value);
|
||||
|
||||
// Even if the original message isn't using the built-in classes, we can still build one... and then
|
||||
// rely on it being normalized.
|
||||
Timestamp normalized = Timestamp.Normalize(seconds, nanos);
|
||||
// Use .NET's formatting for the value down to the second, including an opening double quote (as it's a string value)
|
||||
DateTime dateTime = normalized.ToDateTime();
|
||||
builder.Append(dateTime.ToString("yyyy'-'MM'-'dd'T'HH:mm:ss", CultureInfo.InvariantCulture));
|
||||
AppendNanoseconds(builder, Math.Abs(normalized.Nanos));
|
||||
builder.Append('Z');
|
||||
}
|
||||
|
||||
private void WriteDuration(StringBuilder builder, IMessage value)
|
||||
{
|
||||
// TODO: Same as for WriteTimestamp
|
||||
int nanos = (int) value.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.GetValue(value);
|
||||
long seconds = (long) value.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.GetValue(value);
|
||||
|
||||
// Even if the original message isn't using the built-in classes, we can still build one... and then
|
||||
// rely on it being normalized.
|
||||
Duration normalized = Duration.Normalize(seconds, nanos);
|
||||
|
||||
// The seconds part will normally provide the minus sign if we need it, but not if it's 0...
|
||||
if (normalized.Seconds == 0 && normalized.Nanos < 0)
|
||||
{
|
||||
builder.Append('-');
|
||||
}
|
||||
|
||||
builder.Append(normalized.Seconds.ToString("d", CultureInfo.InvariantCulture));
|
||||
AppendNanoseconds(builder, Math.Abs(normalized.Nanos));
|
||||
builder.Append('s');
|
||||
}
|
||||
|
||||
private void WriteFieldMask(StringBuilder builder, IMessage value)
|
||||
{
|
||||
IList paths = (IList) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value);
|
||||
AppendEscapedString(builder, string.Join(",", paths.Cast<string>().Select(ToCamelCase)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which
|
||||
/// case no "." is appended), or 3 6 or 9 digits.
|
||||
/// </summary>
|
||||
private static void AppendNanoseconds(StringBuilder builder, int nanos)
|
||||
{
|
||||
if (nanos != 0)
|
||||
{
|
||||
builder.Append('.');
|
||||
// Output to 3, 6 or 9 digits.
|
||||
if (nanos % 1000000 == 0)
|
||||
{
|
||||
builder.Append((nanos / 1000000).ToString("d", CultureInfo.InvariantCulture));
|
||||
}
|
||||
else if (nanos % 1000 == 0)
|
||||
{
|
||||
builder.Append((nanos / 1000).ToString("d", CultureInfo.InvariantCulture));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(nanos.ToString("d", CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteStruct(StringBuilder builder, IMessage message)
|
||||
{
|
||||
builder.Append("{ ");
|
||||
IDictionary fields = (IDictionary) message.Descriptor.Fields[Struct.FieldsFieldNumber].Accessor.GetValue(message);
|
||||
bool first = true;
|
||||
foreach (DictionaryEntry entry in fields)
|
||||
{
|
||||
string key = (string) entry.Key;
|
||||
IMessage value = (IMessage) entry.Value;
|
||||
if (string.IsNullOrEmpty(key) || value == null)
|
||||
{
|
||||
throw new InvalidOperationException("Struct fields cannot have an empty key or a null value.");
|
||||
}
|
||||
|
||||
if (!first)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
WriteString(builder, key);
|
||||
builder.Append(": ");
|
||||
WriteStructFieldValue(builder, value);
|
||||
first = false;
|
||||
}
|
||||
builder.Append(first ? "}" : " }");
|
||||
}
|
||||
|
||||
private void WriteStructFieldValue(StringBuilder builder, IMessage message)
|
||||
{
|
||||
var specifiedField = message.Descriptor.Oneofs[0].Accessor.GetCaseFieldDescriptor(message);
|
||||
if (specifiedField == null)
|
||||
{
|
||||
throw new InvalidOperationException("Value message must contain a value for the oneof.");
|
||||
}
|
||||
|
||||
object value = specifiedField.Accessor.GetValue(message);
|
||||
|
||||
switch (specifiedField.FieldNumber)
|
||||
{
|
||||
case Value.BoolValueFieldNumber:
|
||||
case Value.StringValueFieldNumber:
|
||||
case Value.NumberValueFieldNumber:
|
||||
WriteSingleValue(builder, specifiedField, value);
|
||||
return;
|
||||
case Value.StructValueFieldNumber:
|
||||
case Value.ListValueFieldNumber:
|
||||
// Structs and ListValues are nested messages, and already well-known types.
|
||||
var nestedMessage = (IMessage) specifiedField.Accessor.GetValue(message);
|
||||
WriteWellKnownTypeValue(builder, nestedMessage.Descriptor, nestedMessage, true);
|
||||
return;
|
||||
case Value.NullValueFieldNumber:
|
||||
WriteNull(builder);
|
||||
return;
|
||||
default:
|
||||
throw new InvalidOperationException("Unexpected case in struct field: " + specifiedField.FieldNumber);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteList(StringBuilder builder, IFieldAccessor accessor, IList list)
|
||||
{
|
||||
builder.Append("[ ");
|
||||
bool first = true;
|
||||
foreach (var value in list)
|
||||
{
|
||||
if (!CanWriteSingleValue(accessor.Descriptor, value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!first)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
WriteSingleValue(builder, accessor.Descriptor, value);
|
||||
first = false;
|
||||
}
|
||||
builder.Append(first ? "]" : " ]");
|
||||
}
|
||||
|
||||
private void WriteDictionary(StringBuilder builder, IFieldAccessor accessor, IDictionary dictionary)
|
||||
{
|
||||
builder.Append("{ ");
|
||||
bool first = true;
|
||||
FieldDescriptor keyType = accessor.Descriptor.MessageType.FindFieldByNumber(1);
|
||||
FieldDescriptor valueType = accessor.Descriptor.MessageType.FindFieldByNumber(2);
|
||||
// This will box each pair. Could use IDictionaryEnumerator, but that's ugly in terms of disposal.
|
||||
foreach (DictionaryEntry pair in dictionary)
|
||||
{
|
||||
if (!CanWriteSingleValue(valueType, pair.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!first)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
string keyText;
|
||||
switch (keyType.FieldType)
|
||||
{
|
||||
case FieldType.String:
|
||||
keyText = (string) pair.Key;
|
||||
break;
|
||||
case FieldType.Bool:
|
||||
keyText = (bool) pair.Key ? "true" : "false";
|
||||
break;
|
||||
case FieldType.Fixed32:
|
||||
case FieldType.Fixed64:
|
||||
case FieldType.SFixed32:
|
||||
case FieldType.SFixed64:
|
||||
case FieldType.Int32:
|
||||
case FieldType.Int64:
|
||||
case FieldType.SInt32:
|
||||
case FieldType.SInt64:
|
||||
case FieldType.UInt32:
|
||||
case FieldType.UInt64:
|
||||
keyText = ((IFormattable) pair.Key).ToString("d", CultureInfo.InvariantCulture);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Invalid key type: " + keyType.FieldType);
|
||||
}
|
||||
WriteString(builder, keyText);
|
||||
builder.Append(": ");
|
||||
WriteSingleValue(builder, valueType, pair.Value);
|
||||
first = false;
|
||||
}
|
||||
builder.Append(first ? "}" : " }");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not a singular value can be represented in JSON.
|
||||
/// Currently only relevant for enums, where unknown values can't be represented.
|
||||
/// For repeated/map fields, this always returns true.
|
||||
/// </summary>
|
||||
private bool CanWriteSingleValue(FieldDescriptor descriptor, object value)
|
||||
{
|
||||
if (descriptor.FieldType == FieldType.Enum)
|
||||
{
|
||||
EnumValueDescriptor enumValue = descriptor.EnumType.FindValueByNumber((int) value);
|
||||
return enumValue != null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a string (including leading and trailing double quotes) to a builder, escaping as required.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Other than surrogate pair handling, this code is mostly taken from src/google/protobuf/util/internal/json_escaping.cc.
|
||||
/// </remarks>
|
||||
private void WriteString(StringBuilder builder, string text)
|
||||
{
|
||||
builder.Append('"');
|
||||
AppendEscapedString(builder, text);
|
||||
builder.Append('"');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the given text to the string builder, escaping as required.
|
||||
/// </summary>
|
||||
private void AppendEscapedString(StringBuilder builder, string text)
|
||||
{
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
char c = text[i];
|
||||
if (c < 0xa0)
|
||||
{
|
||||
builder.Append(CommonRepresentations[c]);
|
||||
continue;
|
||||
}
|
||||
if (char.IsHighSurrogate(c))
|
||||
{
|
||||
// Encountered first part of a surrogate pair.
|
||||
// Check that we have the whole pair, and encode both parts as hex.
|
||||
i++;
|
||||
if (i == text.Length || !char.IsLowSurrogate(text[i]))
|
||||
{
|
||||
throw new ArgumentException("String contains low surrogate not followed by high surrogate");
|
||||
}
|
||||
HexEncodeUtf16CodeUnit(builder, c);
|
||||
HexEncodeUtf16CodeUnit(builder, text[i]);
|
||||
continue;
|
||||
}
|
||||
else if (char.IsLowSurrogate(c))
|
||||
{
|
||||
throw new ArgumentException("String contains high surrogate not preceded by low surrogate");
|
||||
}
|
||||
switch ((uint) c)
|
||||
{
|
||||
// These are not required by json spec
|
||||
// but used to prevent security bugs in javascript.
|
||||
case 0xfeff: // Zero width no-break space
|
||||
case 0xfff9: // Interlinear annotation anchor
|
||||
case 0xfffa: // Interlinear annotation separator
|
||||
case 0xfffb: // Interlinear annotation terminator
|
||||
|
||||
case 0x00ad: // Soft-hyphen
|
||||
case 0x06dd: // Arabic end of ayah
|
||||
case 0x070f: // Syriac abbreviation mark
|
||||
case 0x17b4: // Khmer vowel inherent Aq
|
||||
case 0x17b5: // Khmer vowel inherent Aa
|
||||
HexEncodeUtf16CodeUnit(builder, c);
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((c >= 0x0600 && c <= 0x0603) || // Arabic signs
|
||||
(c >= 0x200b && c <= 0x200f) || // Zero width etc.
|
||||
(c >= 0x2028 && c <= 0x202e) || // Separators etc.
|
||||
(c >= 0x2060 && c <= 0x2064) || // Invisible etc.
|
||||
(c >= 0x206a && c <= 0x206f))
|
||||
{
|
||||
HexEncodeUtf16CodeUnit(builder, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No handling of surrogates here - that's done earlier
|
||||
builder.Append(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const string Hex = "0123456789abcdef";
|
||||
private static void HexEncodeUtf16CodeUnit(StringBuilder builder, char c)
|
||||
{
|
||||
uint utf16 = c;
|
||||
builder.Append("\\u");
|
||||
builder.Append(Hex[(c >> 12) & 0xf]);
|
||||
builder.Append(Hex[(c >> 8) & 0xf]);
|
||||
builder.Append(Hex[(c >> 4) & 0xf]);
|
||||
builder.Append(Hex[(c >> 0) & 0xf]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Settings controlling JSON formatting.
|
||||
/// </summary>
|
||||
public sealed class Settings
|
||||
{
|
||||
private static readonly Settings defaultInstance = new Settings(false);
|
||||
|
||||
/// <summary>
|
||||
/// Default settings, as used by <see cref="JsonFormatter.Default"/>
|
||||
/// </summary>
|
||||
public static Settings Default { get { return defaultInstance; } }
|
||||
|
||||
private readonly bool formatDefaultValues;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether fields whose values are the default for the field type (e.g. 0 for integers)
|
||||
/// should be formatted (true) or omitted (false).
|
||||
/// </summary>
|
||||
public bool FormatDefaultValues { get { return formatDefaultValues; } }
|
||||
|
||||
public Settings(bool formatDefaultValues)
|
||||
{
|
||||
this.formatDefaultValues = formatDefaultValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
110
csharp/src/Google.Protobuf/LimitedInputStream.cs
Normal file
110
csharp/src/Google.Protobuf/LimitedInputStream.cs
Normal file
@ -0,0 +1,110 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Stream implementation which proxies another stream, only allowing a certain amount
|
||||
/// of data to be read. Note that this is only used to read delimited streams, so it
|
||||
/// doesn't attempt to implement everything.
|
||||
/// </summary>
|
||||
internal sealed class LimitedInputStream : Stream
|
||||
{
|
||||
private readonly Stream proxied;
|
||||
private int bytesLeft;
|
||||
|
||||
internal LimitedInputStream(Stream proxied, int size)
|
||||
{
|
||||
this.proxied = proxied;
|
||||
bytesLeft = size;
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (bytesLeft > 0)
|
||||
{
|
||||
int bytesRead = proxied.Read(buffer, offset, Math.Min(bytesLeft, count));
|
||||
bytesLeft -= bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
113
csharp/src/Google.Protobuf/MessageExtensions.cs
Normal file
113
csharp/src/Google.Protobuf/MessageExtensions.cs
Normal file
@ -0,0 +1,113 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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.
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Google.Protobuf
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods on <see cref="IMessage"/> and <see cref="IMessage{T}"/>.
|
||||
/// </summary>
|
||||
public static class MessageExtensions
|
||||
{
|
||||
public static void MergeFrom(this IMessage message, byte[] data)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
Preconditions.CheckNotNull(data, "data");
|
||||
CodedInputStream input = new CodedInputStream(data);
|
||||
message.MergeFrom(input);
|
||||
input.CheckLastTagWas(0);
|
||||
}
|
||||
|
||||
public static void MergeFrom(this IMessage message, ByteString data)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
Preconditions.CheckNotNull(data, "data");
|
||||
CodedInputStream input = data.CreateCodedInput();
|
||||
message.MergeFrom(input);
|
||||
input.CheckLastTagWas(0);
|
||||
}
|
||||
|
||||
public static void MergeFrom(this IMessage message, Stream input)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
Preconditions.CheckNotNull(input, "input");
|
||||
CodedInputStream codedInput = new CodedInputStream(input);
|
||||
message.MergeFrom(codedInput);
|
||||
codedInput.CheckLastTagWas(0);
|
||||
}
|
||||
|
||||
public static void MergeDelimitedFrom(this IMessage message, Stream input)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
Preconditions.CheckNotNull(input, "input");
|
||||
int size = (int) CodedInputStream.ReadRawVarint32(input);
|
||||
Stream limitedStream = new LimitedInputStream(input, size);
|
||||
message.MergeFrom(limitedStream);
|
||||
}
|
||||
|
||||
public static byte[] ToByteArray(this IMessage message)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
byte[] result = new byte[message.CalculateSize()];
|
||||
CodedOutputStream output = new CodedOutputStream(result);
|
||||
message.WriteTo(output);
|
||||
output.CheckNoSpaceLeft();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void WriteTo(this IMessage message, Stream output)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
Preconditions.CheckNotNull(output, "output");
|
||||
CodedOutputStream codedOutput = new CodedOutputStream(output);
|
||||
message.WriteTo(codedOutput);
|
||||
codedOutput.Flush();
|
||||
}
|
||||
|
||||
public static void WriteDelimitedTo(this IMessage message, Stream output)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
Preconditions.CheckNotNull(output, "output");
|
||||
CodedOutputStream codedOutput = new CodedOutputStream(output);
|
||||
codedOutput.WriteRawVarint32((uint)message.CalculateSize());
|
||||
message.WriteTo(codedOutput);
|
||||
codedOutput.Flush();
|
||||
}
|
||||
|
||||
public static ByteString ToByteString(this IMessage message)
|
||||
{
|
||||
Preconditions.CheckNotNull(message, "message");
|
||||
return ByteString.AttachBytes(message.ToByteArray());
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user