PROTOBUF_SYNC_PIPER
pull/9734/head^2
Mike Kruskal 3 years ago
parent 40db3dabf0
commit a29e0e3f44
  1. 2
      .github/workflows/codespell.yml
  2. 6
      .gitignore
  3. 117
      BUILD
  4. 7
      CHANGES.txt
  5. 2
      Protobuf.podspec
  6. 1
      cmake/tests.cmake
  7. 4
      conformance/binary_json_conformance_suite.cc
  8. 17
      csharp/.editorconfig
  9. 2
      csharp/Google.Protobuf.Tools.nuspec
  10. 340
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/ByteStringTest.cs
  11. 1194
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs
  12. 836
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
  13. 110
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
  14. 1450
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/GeneratedMessageTest.cs
  15. 164
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/IssuesTest.cs
  16. 124
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/TestCornerCases.cs
  17. 4
      csharp/generate_protos.sh
  18. 14
      csharp/protos/unittest_issues.proto
  19. 262
      csharp/src/AddressBook/AddPerson.cs
  20. 196
      csharp/src/AddressBook/ListPeople.cs
  21. 188
      csharp/src/AddressBook/Program.cs
  22. 144
      csharp/src/AddressBook/SampleUsage.cs
  23. 4
      csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
  24. 144
      csharp/src/Google.Protobuf.JsonDump/Program.cs
  25. 50
      csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj
  26. 6
      csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
  27. 534
      csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
  28. 876
      csharp/src/Google.Protobuf.Test/ByteStringTest.cs
  29. 2016
      csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
  30. 1164
      csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
  31. 110
      csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
  32. 392
      csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
  33. 794
      csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
  34. 1596
      csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
  35. 8
      csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
  36. 248
      csharp/src/Google.Protobuf.Test/IssuesTest.cs
  37. 1410
      csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
  38. 124
      csharp/src/Google.Protobuf.Test/TestCornerCases.cs
  39. 18
      csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
  40. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  41. 156
      csharp/src/Google.Protobuf/ByteArray.cs
  42. 866
      csharp/src/Google.Protobuf/ByteString.cs
  43. 1396
      csharp/src/Google.Protobuf/CodedInputStream.cs
  44. 614
      csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
  45. 1214
      csharp/src/Google.Protobuf/CodedOutputStream.cs
  46. 1524
      csharp/src/Google.Protobuf/Collections/MapField.cs
  47. 292
      csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs
  48. 1396
      csharp/src/Google.Protobuf/Collections/RepeatedField.cs
  49. 856
      csharp/src/Google.Protobuf/ExtensionSet.cs
  50. 96
      csharp/src/Google.Protobuf/FrameworkPortability.cs
  51. 2
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  52. 174
      csharp/src/Google.Protobuf/IMessage.cs
  53. 278
      csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
  54. 24
      csharp/src/Google.Protobuf/JsonFormatter.cs
  55. 74
      csharp/src/Google.Protobuf/ObjectIntPair.cs
  56. 112
      csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
  57. 156
      csharp/src/Google.Protobuf/ProtoPreconditions.cs
  58. 12
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  59. 18
      csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
  60. 206
      csharp/src/Google.Protobuf/WireFormat.cs
  61. 1
      docs/third_party.md
  62. 6
      java/README.md
  63. 2
      java/bom/pom.xml
  64. 2
      java/core/pom.xml
  65. 6
      java/core/src/main/java/com/google/protobuf/Descriptors.java
  66. 12
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  67. 28
      java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
  68. 6
      java/core/src/test/java/com/google/protobuf/TestUtil.java
  69. 2
      java/kotlin-lite/pom.xml
  70. 2
      java/kotlin/pom.xml
  71. 2
      java/lite.md
  72. 2
      java/lite/pom.xml
  73. 2
      java/pom.xml
  74. 2
      java/util/pom.xml
  75. 2
      java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
  76. 3
      java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
  77. 17
      java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
  78. 8
      js/binary/reader_test.js
  79. 2
      js/binary/writer_test.js
  80. 8
      js/compatibility_tests/v3.0.0/binary/reader_test.js
  81. 2
      js/compatibility_tests/v3.0.0/binary/writer_test.js
  82. 8
      js/compatibility_tests/v3.1.0/binary/reader_test.js
  83. 2
      js/compatibility_tests/v3.1.0/binary/writer_test.js
  84. 92
      kokoro/caplog.sh
  85. 1
      kokoro/linux/dockerfile/test/ruby/Dockerfile
  86. 4
      kokoro/macos-next/README.md
  87. 55
      kokoro/macos-next/cpp/build.sh
  88. 13
      kokoro/macos-next/cpp/continuous.cfg
  89. 13
      kokoro/macos-next/cpp/presubmit.cfg
  90. 86
      maven_install.json
  91. 48
      php/ext/google/protobuf/package.xml
  92. 2
      php/ext/google/protobuf/protobuf.h
  93. 6
      php/release.sh
  94. 32
      php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
  95. 4
      php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
  96. 10
      protobuf.bzl
  97. 6
      protobuf_deps.bzl
  98. 2
      protobuf_version.bzl
  99. 2
      protoc-artifacts/pom.xml
  100. 14
      python/google/protobuf/internal/descriptor_test.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -13,4 +13,4 @@ jobs:
with:
check_filenames: true
skip: ./.git,./conformance/third_party,*.snk,*.pb,*.pb.cc,*.pb.h,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal,./.github/workflows/codespell.yml
ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,sur"
ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,streem,sur"

6
.gitignore vendored

@ -46,7 +46,7 @@ src/.libs
any_test.pb.*
map*unittest.pb.*
unittest*.pb.*
cpp_test*.pb.*
src/google/protobuf/compiler/cpp/test*.pb.*
src/google/protobuf/util/**/*.pb.cc
src/google/protobuf/util/**/*.pb.h
@ -89,6 +89,10 @@ java/**/*.iml
# Windows native output.
cmake/build
build_msvc
# Directories suggested by cmake/README.md
/debug/
/solution/
/release/
# NuGet packages: we want the repository configuration, but not the
# packages themselves.

117
BUILD

@ -159,6 +159,7 @@ cc_library(
"src/google/protobuf/any_lite.cc",
"src/google/protobuf/arena.cc",
"src/google/protobuf/arenastring.cc",
"src/google/protobuf/arenaz_sampler.cc",
"src/google/protobuf/extension_set.cc",
"src/google/protobuf/generated_enum_util.cc",
"src/google/protobuf/generated_message_tctable_lite.cc",
@ -419,21 +420,21 @@ cc_library(
# AUTOGEN(protoc_lib_srcs)
"src/google/protobuf/compiler/code_generator.cc",
"src/google/protobuf/compiler/command_line_interface.cc",
"src/google/protobuf/compiler/cpp/cpp_enum.cc",
"src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
"src/google/protobuf/compiler/cpp/cpp_extension.cc",
"src/google/protobuf/compiler/cpp/cpp_field.cc",
"src/google/protobuf/compiler/cpp/cpp_file.cc",
"src/google/protobuf/compiler/cpp/cpp_generator.cc",
"src/google/protobuf/compiler/cpp/cpp_helpers.cc",
"src/google/protobuf/compiler/cpp/cpp_map_field.cc",
"src/google/protobuf/compiler/cpp/cpp_message.cc",
"src/google/protobuf/compiler/cpp/cpp_message_field.cc",
"src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc",
"src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc",
"src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
"src/google/protobuf/compiler/cpp/cpp_service.cc",
"src/google/protobuf/compiler/cpp/cpp_string_field.cc",
"src/google/protobuf/compiler/cpp/enum.cc",
"src/google/protobuf/compiler/cpp/enum_field.cc",
"src/google/protobuf/compiler/cpp/extension.cc",
"src/google/protobuf/compiler/cpp/field.cc",
"src/google/protobuf/compiler/cpp/file.cc",
"src/google/protobuf/compiler/cpp/generator.cc",
"src/google/protobuf/compiler/cpp/helpers.cc",
"src/google/protobuf/compiler/cpp/map_field.cc",
"src/google/protobuf/compiler/cpp/message.cc",
"src/google/protobuf/compiler/cpp/message_field.cc",
"src/google/protobuf/compiler/cpp/padding_optimizer.cc",
"src/google/protobuf/compiler/cpp/parse_function_generator.cc",
"src/google/protobuf/compiler/cpp/primitive_field.cc",
"src/google/protobuf/compiler/cpp/service.cc",
"src/google/protobuf/compiler/cpp/string_field.cc",
"src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
"src/google/protobuf/compiler/csharp/csharp_enum.cc",
"src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
@ -450,35 +451,35 @@ 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_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",
"src/google/protobuf/compiler/java/java_enum_field.cc",
"src/google/protobuf/compiler/java/java_enum_field_lite.cc",
"src/google/protobuf/compiler/java/java_enum_lite.cc",
"src/google/protobuf/compiler/java/java_extension.cc",
"src/google/protobuf/compiler/java/java_extension_lite.cc",
"src/google/protobuf/compiler/java/java_field.cc",
"src/google/protobuf/compiler/java/java_file.cc",
"src/google/protobuf/compiler/java/java_generator.cc",
"src/google/protobuf/compiler/java/java_generator_factory.cc",
"src/google/protobuf/compiler/java/java_helpers.cc",
"src/google/protobuf/compiler/java/java_kotlin_generator.cc",
"src/google/protobuf/compiler/java/java_map_field.cc",
"src/google/protobuf/compiler/java/java_map_field_lite.cc",
"src/google/protobuf/compiler/java/java_message.cc",
"src/google/protobuf/compiler/java/java_message_builder.cc",
"src/google/protobuf/compiler/java/java_message_builder_lite.cc",
"src/google/protobuf/compiler/java/java_message_field.cc",
"src/google/protobuf/compiler/java/java_message_field_lite.cc",
"src/google/protobuf/compiler/java/java_message_lite.cc",
"src/google/protobuf/compiler/java/java_name_resolver.cc",
"src/google/protobuf/compiler/java/java_primitive_field.cc",
"src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
"src/google/protobuf/compiler/java/java_service.cc",
"src/google/protobuf/compiler/java/java_shared_code_generator.cc",
"src/google/protobuf/compiler/java/java_string_field.cc",
"src/google/protobuf/compiler/java/java_string_field_lite.cc",
"src/google/protobuf/compiler/java/context.cc",
"src/google/protobuf/compiler/java/doc_comment.cc",
"src/google/protobuf/compiler/java/enum.cc",
"src/google/protobuf/compiler/java/enum_field.cc",
"src/google/protobuf/compiler/java/enum_field_lite.cc",
"src/google/protobuf/compiler/java/enum_lite.cc",
"src/google/protobuf/compiler/java/extension.cc",
"src/google/protobuf/compiler/java/extension_lite.cc",
"src/google/protobuf/compiler/java/field.cc",
"src/google/protobuf/compiler/java/file.cc",
"src/google/protobuf/compiler/java/generator.cc",
"src/google/protobuf/compiler/java/generator_factory.cc",
"src/google/protobuf/compiler/java/helpers.cc",
"src/google/protobuf/compiler/java/kotlin_generator.cc",
"src/google/protobuf/compiler/java/map_field.cc",
"src/google/protobuf/compiler/java/map_field_lite.cc",
"src/google/protobuf/compiler/java/message.cc",
"src/google/protobuf/compiler/java/message_builder.cc",
"src/google/protobuf/compiler/java/message_builder_lite.cc",
"src/google/protobuf/compiler/java/message_field.cc",
"src/google/protobuf/compiler/java/message_field_lite.cc",
"src/google/protobuf/compiler/java/message_lite.cc",
"src/google/protobuf/compiler/java/name_resolver.cc",
"src/google/protobuf/compiler/java/primitive_field.cc",
"src/google/protobuf/compiler/java/primitive_field_lite.cc",
"src/google/protobuf/compiler/java/service.cc",
"src/google/protobuf/compiler/java/shared_code_generator.cc",
"src/google/protobuf/compiler/java/string_field.cc",
"src/google/protobuf/compiler/java/string_field_lite.cc",
"src/google/protobuf/compiler/js/js_generator.cc",
"src/google/protobuf/compiler/js/well_known_types_embed.cc",
"src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
@ -496,9 +497,9 @@ cc_library(
"src/google/protobuf/compiler/php/php_generator.cc",
"src/google/protobuf/compiler/plugin.cc",
"src/google/protobuf/compiler/plugin.pb.cc",
"src/google/protobuf/compiler/python/python_generator.cc",
"src/google/protobuf/compiler/python/python_helpers.cc",
"src/google/protobuf/compiler/python/python_pyi_generator.cc",
"src/google/protobuf/compiler/python/generator.cc",
"src/google/protobuf/compiler/python/helpers.cc",
"src/google/protobuf/compiler/python/pyi_generator.cc",
"src/google/protobuf/compiler/ruby/ruby_generator.cc",
"src/google/protobuf/compiler/subprocess.cc",
"src/google/protobuf/compiler/zip_writer.cc",
@ -605,8 +606,8 @@ LITE_TEST_PROTOS = ["src/" + s for s in RELATIVE_LITE_TEST_PROTOS]
RELATIVE_TEST_PROTOS = [
# AUTOGEN(test_protos)
"google/protobuf/any_test.proto",
"google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto",
"google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto",
"google/protobuf/compiler/cpp/test_bad_identifiers.proto",
"google/protobuf/compiler/cpp/test_large_enum_value.proto",
"google/protobuf/map_proto2_unittest.proto",
"google/protobuf/map_unittest.proto",
"google/protobuf/unittest.proto",
@ -765,23 +766,24 @@ cc_test(
"src/google/protobuf/any_test.cc",
"src/google/protobuf/arena_unittest.cc",
"src/google/protobuf/arenastring_unittest.cc",
"src/google/protobuf/arenaz_sampler_test.cc",
"src/google/protobuf/compiler/annotation_test_util.cc",
"src/google/protobuf/compiler/command_line_interface_unittest.cc",
"src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc",
"src/google/protobuf/compiler/cpp/cpp_move_unittest.cc",
"src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc",
"src/google/protobuf/compiler/cpp/cpp_unittest.cc",
"src/google/protobuf/compiler/cpp/cpp_unittest.inc",
"src/google/protobuf/compiler/cpp/bootstrap_unittest.cc",
"src/google/protobuf/compiler/cpp/metadata_test.cc",
"src/google/protobuf/compiler/cpp/move_unittest.cc",
"src/google/protobuf/compiler/cpp/plugin_unittest.cc",
"src/google/protobuf/compiler/cpp/unittest.cc",
"src/google/protobuf/compiler/cpp/unittest.inc",
"src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc",
"src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc",
"src/google/protobuf/compiler/importer_unittest.cc",
"src/google/protobuf/compiler/java/java_doc_comment_unittest.cc",
"src/google/protobuf/compiler/java/java_plugin_unittest.cc",
"src/google/protobuf/compiler/java/doc_comment_unittest.cc",
"src/google/protobuf/compiler/java/plugin_unittest.cc",
"src/google/protobuf/compiler/mock_code_generator.cc",
"src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc",
"src/google/protobuf/compiler/parser_unittest.cc",
"src/google/protobuf/compiler/python/python_plugin_unittest.cc",
"src/google/protobuf/compiler/python/plugin_unittest.cc",
"src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc",
"src/google/protobuf/descriptor_database_unittest.cc",
"src/google/protobuf/descriptor_unittest.cc",
@ -789,6 +791,7 @@ cc_test(
"src/google/protobuf/dynamic_message_unittest.cc",
"src/google/protobuf/extension_set_unittest.cc",
"src/google/protobuf/generated_message_reflection_unittest.cc",
"src/google/protobuf/generated_message_tctable_lite_test.cc",
"src/google/protobuf/inlined_string_field_unittest.cc",
"src/google/protobuf/io/coded_stream_unittest.cc",
"src/google/protobuf/io/io_win32_unittest.cc",

@ -17,8 +17,11 @@ Python
Ruby
* Dropped Ruby 2.3 and 2.4 support for CI and releases. (#9311)
* Message.decode/encode: Add max_recursion_depth option (#9218)
* Rename max_recursion_depth to recursion_limit (#9486)
* Added Ruby 3.1 support for CI and releases (#9566).
* Message.decode/encode: Add recursion_limit option (#9218/#9486)
* Allocate with xrealloc()/xfree() so message allocation is visible to the
Ruby GC. In certain tests this leads to much lower memory usage due to more
frequent GC runs (#9586).
* Fix conversion of singleton classes in Ruby (#9342)
* Suppress warning for intentional circular require (#9556)
* JSON will now output shorter strings for double and float fields when possible

@ -5,7 +5,7 @@
# dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s|
s.name = 'Protobuf'
s.version = '3.20.0-rc1'
s.version = '3.20.0'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/protocolbuffers/protobuf'
s.license = 'BSD-3-Clause'

@ -145,6 +145,7 @@ set(tests_files
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.h
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface_unittest.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_size_unittest.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/metadata_test.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/move_unittest.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/plugin_unittest.cc

@ -2226,11 +2226,11 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() {
"optional_aliased_enum: ALIAS_BAZ");
RunValidJsonTest(
"EnumFieldWithAliasUseAlias", REQUIRED,
R"({"optionalAliasedEnum": "QUX"})",
R"({"optionalAliasedEnum": "MOO"})",
"optional_aliased_enum: ALIAS_BAZ");
RunValidJsonTest(
"EnumFieldWithAliasLowerCase", REQUIRED,
R"({"optionalAliasedEnum": "qux"})",
R"({"optionalAliasedEnum": "moo"})",
"optional_aliased_enum: ALIAS_BAZ");
RunValidJsonTest(
"EnumFieldWithAliasDifferentCase", REQUIRED,

@ -0,0 +1,17 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
# C# files
[*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
indent_style = space
tab_width = 4
# New line preferences
end_of_line = lf
insert_final_newline = false
trim_trailing_whitespace = true

@ -5,7 +5,7 @@
<title>Google Protocol Buffers tools</title>
<summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
<description>See project site for more info.</description>
<version>3.20.0-rc1</version>
<version>3.20.0</version>
<authors>Google Inc.</authors>
<owners>protobuf-packages</owners>
<licenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</licenseUrl>

@ -1,171 +1,171 @@
#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.Text;
using NUnit.Framework;
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()
{
Assert.AreEqual(0, ByteString.Empty.Length);
}
[Test]
public void CopyFromStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
Assert.AreEqual(4, bs.Length);
Assert.AreEqual(65, bs[0]);
Assert.AreEqual(0, bs[1]);
Assert.AreEqual(66, bs[2]);
Assert.AreEqual(0, bs[3]);
}
[Test]
public void IsEmptyWhenEmpty()
{
Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
}
[Test]
public void IsEmptyWhenNotEmpty()
{
Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
}
[Test]
public void CopyFromByteArrayCopiesContents()
{
byte[] data = new byte[1];
data[0] = 10;
ByteString bs = ByteString.CopyFrom(data);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void ToByteArrayCopiesContents()
{
ByteString bs = ByteString.CopyFromUtf8("Hello");
byte[] data = bs.ToByteArray();
Assert.AreEqual((byte)'H', data[0]);
Assert.AreEqual((byte)'H', bs[0]);
data[0] = 0;
Assert.AreEqual(0, data[0]);
Assert.AreEqual((byte)'H', bs[0]);
}
[Test]
public void CopyFromUtf8UsesUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(0xe2, bs[0]);
Assert.AreEqual(0x82, bs[1]);
Assert.AreEqual(0xac, bs[2]);
}
[Test]
public void CopyFromPortion()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
ByteString bs = ByteString.CopyFrom(data, 2, 3);
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(2, bs[0]);
Assert.AreEqual(3, bs[1]);
}
[Test]
public void ToStringUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual("\u20ac", bs.ToStringUtf8());
}
[Test]
public void ToStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
}
[Test]
public void FromBase64_WithText()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
string base64 = Convert.ToBase64String(data);
ByteString bs = ByteString.FromBase64(base64);
Assert.AreEqual(data, bs.ToByteArray());
}
[Test]
public void FromBase64_Empty()
{
// Optimization which also fixes issue 61.
Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
}
}
#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.Text;
using NUnit.Framework;
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()
{
Assert.AreEqual(0, ByteString.Empty.Length);
}
[Test]
public void CopyFromStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
Assert.AreEqual(4, bs.Length);
Assert.AreEqual(65, bs[0]);
Assert.AreEqual(0, bs[1]);
Assert.AreEqual(66, bs[2]);
Assert.AreEqual(0, bs[3]);
}
[Test]
public void IsEmptyWhenEmpty()
{
Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
}
[Test]
public void IsEmptyWhenNotEmpty()
{
Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
}
[Test]
public void CopyFromByteArrayCopiesContents()
{
byte[] data = new byte[1];
data[0] = 10;
ByteString bs = ByteString.CopyFrom(data);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void ToByteArrayCopiesContents()
{
ByteString bs = ByteString.CopyFromUtf8("Hello");
byte[] data = bs.ToByteArray();
Assert.AreEqual((byte)'H', data[0]);
Assert.AreEqual((byte)'H', bs[0]);
data[0] = 0;
Assert.AreEqual(0, data[0]);
Assert.AreEqual((byte)'H', bs[0]);
}
[Test]
public void CopyFromUtf8UsesUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(0xe2, bs[0]);
Assert.AreEqual(0x82, bs[1]);
Assert.AreEqual(0xac, bs[2]);
}
[Test]
public void CopyFromPortion()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
ByteString bs = ByteString.CopyFrom(data, 2, 3);
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(2, bs[0]);
Assert.AreEqual(3, bs[1]);
}
[Test]
public void ToStringUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual("\u20ac", bs.ToStringUtf8());
}
[Test]
public void ToStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
}
[Test]
public void FromBase64_WithText()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
string base64 = Convert.ToBase64String(data);
ByteString bs = ByteString.FromBase64(base64);
Assert.AreEqual(data, bs.ToByteArray());
}
[Test]
public void FromBase64_Empty()
{
// Optimization which also fixes issue 61.
Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
}
}
}

@ -1,419 +1,419 @@
#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 Google.Protobuf.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
public class CodedOutputStreamTest
{
/// <summary>
/// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
/// checks that the result matches the given bytes
/// </summary>
private static void AssertWriteVarint(byte[] data, ulong value)
{
// Only do 32-bit write if the value fits in 32 bits.
if ((value >> 32) == 0)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Also try computing size.
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
}
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Also try computing size.
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
}
// Try different buffer sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
{
// Only do 32-bit write if the value fits in 32 bits.
if ((value >> 32) == 0)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output =
new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
}
/// <summary>
/// Tests WriteRawVarint32() and WriteRawVarint64()
/// </summary>
[Test]
public void WriteVarint()
{
AssertWriteVarint(new byte[] {0x00}, 0);
AssertWriteVarint(new byte[] {0x01}, 1);
AssertWriteVarint(new byte[] {0x7f}, 127);
// 14882
AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7));
// 2961488830
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b},
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x0bL << 28));
// 64-bit
// 7256456126
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b},
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x1bL << 28));
// 41256202580718336
AssertWriteVarint(
new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49},
(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
(0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
// 11964378330978735131
AssertWriteVarint(
new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01},
unchecked((ulong)
((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
(0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
(0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
}
/// <summary>
/// Parses the given bytes using WriteRawLittleEndian32() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertWriteLittleEndian32(byte[] data, uint value)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Try different buffer sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
{
rawOutput = new MemoryStream();
output = new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
/// <summary>
/// Parses the given bytes using WriteRawLittleEndian64() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertWriteLittleEndian64(byte[] data, ulong value)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
{
rawOutput = new MemoryStream();
output = new CodedOutputStream(rawOutput, blockSize);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
/// <summary>
/// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
/// </summary>
[Test]
public void WriteLittleEndian()
{
AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678);
AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0);
AssertWriteLittleEndian64(
new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12},
0x123456789abcdef0L);
AssertWriteLittleEndian64(
new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a},
0x9abcdef012345678UL);
}
[Test]
public void WriteWholeMessage_VaryingBlockSizes()
{
TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
byte[] rawBytes = message.ToByteArray();
// Try different block sizes.
for (int blockSize = 1; blockSize < 256; blockSize *= 2)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize);
message.WriteTo(output);
output.Flush();
Assert.AreEqual(rawBytes, rawOutput.ToArray());
}
}
[Test]
public void EncodeZigZag32()
{
Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0));
Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1));
Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1));
Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2));
Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF));
Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000)));
Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF));
Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000)));
}
[Test]
public void EncodeZigZag64()
{
Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0));
Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1));
Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1));
Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2));
Assert.AreEqual(0x000000007FFFFFFEuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));
Assert.AreEqual(0x000000007FFFFFFFuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));
Assert.AreEqual(0x00000000FFFFFFFEuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));
Assert.AreEqual(0x00000000FFFFFFFFuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));
}
[Test]
public void RoundTripZigZag32()
{
// Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
// were chosen semi-randomly via keyboard bashing.
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612)));
}
[Test]
public void RoundTripZigZag64()
{
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612)));
Assert.AreEqual(856912304801416L,
ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L)));
Assert.AreEqual(-75123905439571256L,
ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L)));
}
[Test]
public void TestNegativeEnumNoTag()
{
Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue));
byte[] bytes = new byte[10];
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 TestCodedInputOutputPosition()
{
byte[] content = new byte[110];
for (int i = 0; i < content.Length; i++)
content[i] = (byte)i;
byte[] child = new byte[120];
{
MemoryStream ms = new MemoryStream(child);
CodedOutputStream cout = new CodedOutputStream(ms, 20);
// Field 11: numeric value: 500
cout.WriteTag(11, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
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.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.WriteSFixed32(501);
Assert.AreEqual(120, cout.Position);
cout.Flush();
}
byte[] bytes = new byte[130];
{
CodedOutputStream cout = new CodedOutputStream(bytes);
// Field 1: numeric value: 500
cout.WriteTag(1, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
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.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.WriteSFixed32(501);
Assert.AreEqual(130, cout.Position);
cout.Flush();
}
// Now test Input stream:
{
CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0, false);
Assert.AreEqual(0, cin.Position);
// Field 1:
uint tag = cin.ReadTag();
Assert.AreEqual(1, tag >> 3);
Assert.AreEqual(1, cin.Position);
Assert.AreEqual(500, cin.ReadInt32());
Assert.AreEqual(3, cin.Position);
//Field 2:
tag = cin.ReadTag();
Assert.AreEqual(2, tag >> 3);
Assert.AreEqual(4, cin.Position);
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
tag = cin.ReadTag();
Assert.AreEqual(11, tag >> 3);
Assert.AreEqual(6, cin.Position);
Assert.AreEqual(500, cin.ReadInt32());
Assert.AreEqual(8, cin.Position);
//Field 12: length delimited 120 bytes
tag = cin.ReadTag();
Assert.AreEqual(12, tag >> 3);
Assert.AreEqual(9, cin.Position);
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
tag = cin.ReadTag();
Assert.AreEqual(13, tag >> 3);
// ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit
Assert.AreEqual(121, cin.Position);
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
tag = cin.ReadTag();
Assert.AreEqual(3, tag >> 3);
Assert.AreEqual(126, cin.Position);
Assert.AreEqual(501, cin.ReadSFixed32());
Assert.AreEqual(130, cin.Position);
Assert.IsTrue(cin.IsAtEnd);
}
}
[Test]
public void Dispose_DisposesUnderlyingStream()
{
var memoryStream = new MemoryStream();
Assert.IsTrue(memoryStream.CanWrite);
using (var cos = new CodedOutputStream(memoryStream))
{
cos.WriteRawBytes(new byte[] {0});
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
}
Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream
Assert.IsFalse(memoryStream.CanWrite); // Disposed
}
[Test]
public void Dispose_WithLeaveOpen()
{
var memoryStream = new MemoryStream();
Assert.IsTrue(memoryStream.CanWrite);
using (var cos = new CodedOutputStream(memoryStream, true))
{
cos.WriteRawBytes(new byte[] {0});
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
}
Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream
Assert.IsTrue(memoryStream.CanWrite); // We left the stream open
}
}
#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 Google.Protobuf.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
public class CodedOutputStreamTest
{
/// <summary>
/// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
/// checks that the result matches the given bytes
/// </summary>
private static void AssertWriteVarint(byte[] data, ulong value)
{
// Only do 32-bit write if the value fits in 32 bits.
if ((value >> 32) == 0)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Also try computing size.
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
}
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Also try computing size.
Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
}
// Try different buffer sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
{
// Only do 32-bit write if the value fits in 32 bits.
if ((value >> 32) == 0)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output =
new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
}
/// <summary>
/// Tests WriteRawVarint32() and WriteRawVarint64()
/// </summary>
[Test]
public void WriteVarint()
{
AssertWriteVarint(new byte[] {0x00}, 0);
AssertWriteVarint(new byte[] {0x01}, 1);
AssertWriteVarint(new byte[] {0x7f}, 127);
// 14882
AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7));
// 2961488830
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b},
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x0bL << 28));
// 64-bit
// 7256456126
AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b},
(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
(0x1bL << 28));
// 41256202580718336
AssertWriteVarint(
new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49},
(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
(0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
// 11964378330978735131
AssertWriteVarint(
new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01},
unchecked((ulong)
((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
(0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
(0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
}
/// <summary>
/// Parses the given bytes using WriteRawLittleEndian32() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertWriteLittleEndian32(byte[] data, uint value)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Try different buffer sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
{
rawOutput = new MemoryStream();
output = new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
/// <summary>
/// Parses the given bytes using WriteRawLittleEndian64() and checks
/// that the result matches the given value.
/// </summary>
private static void AssertWriteLittleEndian64(byte[] data, ulong value)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
{
rawOutput = new MemoryStream();
output = new CodedOutputStream(rawOutput, blockSize);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
}
}
/// <summary>
/// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
/// </summary>
[Test]
public void WriteLittleEndian()
{
AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678);
AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0);
AssertWriteLittleEndian64(
new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12},
0x123456789abcdef0L);
AssertWriteLittleEndian64(
new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a},
0x9abcdef012345678UL);
}
[Test]
public void WriteWholeMessage_VaryingBlockSizes()
{
TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
byte[] rawBytes = message.ToByteArray();
// Try different block sizes.
for (int blockSize = 1; blockSize < 256; blockSize *= 2)
{
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize);
message.WriteTo(output);
output.Flush();
Assert.AreEqual(rawBytes, rawOutput.ToArray());
}
}
[Test]
public void EncodeZigZag32()
{
Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0));
Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1));
Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1));
Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2));
Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF));
Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000)));
Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF));
Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000)));
}
[Test]
public void EncodeZigZag64()
{
Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0));
Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1));
Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1));
Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2));
Assert.AreEqual(0x000000007FFFFFFEuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));
Assert.AreEqual(0x000000007FFFFFFFuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));
Assert.AreEqual(0x00000000FFFFFFFEuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));
Assert.AreEqual(0x00000000FFFFFFFFuL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));
}
[Test]
public void RoundTripZigZag32()
{
// Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
// were chosen semi-randomly via keyboard bashing.
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612)));
}
[Test]
public void RoundTripZigZag64()
{
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612)));
Assert.AreEqual(856912304801416L,
ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L)));
Assert.AreEqual(-75123905439571256L,
ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L)));
}
[Test]
public void TestNegativeEnumNoTag()
{
Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue));
byte[] bytes = new byte[10];
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 TestCodedInputOutputPosition()
{
byte[] content = new byte[110];
for (int i = 0; i < content.Length; i++)
content[i] = (byte)i;
byte[] child = new byte[120];
{
MemoryStream ms = new MemoryStream(child);
CodedOutputStream cout = new CodedOutputStream(ms, 20);
// Field 11: numeric value: 500
cout.WriteTag(11, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
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.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.WriteSFixed32(501);
Assert.AreEqual(120, cout.Position);
cout.Flush();
}
byte[] bytes = new byte[130];
{
CodedOutputStream cout = new CodedOutputStream(bytes);
// Field 1: numeric value: 500
cout.WriteTag(1, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
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.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.WriteSFixed32(501);
Assert.AreEqual(130, cout.Position);
cout.Flush();
}
// Now test Input stream:
{
CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0, false);
Assert.AreEqual(0, cin.Position);
// Field 1:
uint tag = cin.ReadTag();
Assert.AreEqual(1, tag >> 3);
Assert.AreEqual(1, cin.Position);
Assert.AreEqual(500, cin.ReadInt32());
Assert.AreEqual(3, cin.Position);
//Field 2:
tag = cin.ReadTag();
Assert.AreEqual(2, tag >> 3);
Assert.AreEqual(4, cin.Position);
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
tag = cin.ReadTag();
Assert.AreEqual(11, tag >> 3);
Assert.AreEqual(6, cin.Position);
Assert.AreEqual(500, cin.ReadInt32());
Assert.AreEqual(8, cin.Position);
//Field 12: length delimited 120 bytes
tag = cin.ReadTag();
Assert.AreEqual(12, tag >> 3);
Assert.AreEqual(9, cin.Position);
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
tag = cin.ReadTag();
Assert.AreEqual(13, tag >> 3);
// ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit
Assert.AreEqual(121, cin.Position);
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
tag = cin.ReadTag();
Assert.AreEqual(3, tag >> 3);
Assert.AreEqual(126, cin.Position);
Assert.AreEqual(501, cin.ReadSFixed32());
Assert.AreEqual(130, cin.Position);
Assert.IsTrue(cin.IsAtEnd);
}
}
[Test]
public void Dispose_DisposesUnderlyingStream()
{
var memoryStream = new MemoryStream();
Assert.IsTrue(memoryStream.CanWrite);
using (var cos = new CodedOutputStream(memoryStream))
{
cos.WriteRawBytes(new byte[] {0});
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
}
Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream
Assert.IsFalse(memoryStream.CanWrite); // Disposed
}
[Test]
public void Dispose_WithLeaveOpen()
{
var memoryStream = new MemoryStream();
Assert.IsTrue(memoryStream.CanWrite);
using (var cos = new CodedOutputStream(memoryStream, true))
{
cos.WriteRawBytes(new byte[] {0});
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
}
Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream
Assert.IsTrue(memoryStream.CanWrite); // We left the stream open
}
}
}

@ -1,55 +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"));
}
}
}
#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"));
}
}
}

@ -1,82 +1,82 @@
#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 Google.Protobuf.Reflection;
using UnitTest.Issues.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
/// <summary>
/// Tests for issues which aren't easily compartmentalized into other unit tests.
/// </summary>
public class IssuesTest
{
// Issue 45
[Test]
public void FieldCalledItem()
{
ItemField message = new ItemField { Item = 3 };
FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
Assert.NotNull(field);
Assert.AreEqual(3, (int)field.Accessor.GetValue(message));
}
[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());
}
[Test]
public void JsonNameParseTest()
{
var settings = new JsonParser.Settings(10, TypeRegistry.FromFiles(UnittestIssuesReflection.Descriptor));
var parser = new JsonParser(settings);
// It is safe to use either original field name or explicitly specified json_name
Assert.AreEqual(new TestJsonName { Name = "test", Description = "test2", Guid = "test3" },
parser.Parse<TestJsonName>("{ \"name\": \"test\", \"desc\": \"test2\", \"guid\": \"test3\" }"));
}
[Test]
public void JsonNameFormatTest()
{
var message = new TestJsonName { Name = "test", Description = "test2", Guid = "test3" };
Assert.AreEqual("{ \"name\": \"test\", \"desc\": \"test2\", \"exid\": \"test3\" }",
JsonFormatter.Default.Format(message));
}
}
}
#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 Google.Protobuf.Reflection;
using UnitTest.Issues.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
/// <summary>
/// Tests for issues which aren't easily compartmentalized into other unit tests.
/// </summary>
public class IssuesTest
{
// Issue 45
[Test]
public void FieldCalledItem()
{
ItemField message = new ItemField { Item = 3 };
FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
Assert.NotNull(field);
Assert.AreEqual(3, (int)field.Accessor.GetValue(message));
}
[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());
}
[Test]
public void JsonNameParseTest()
{
var settings = new JsonParser.Settings(10, TypeRegistry.FromFiles(UnittestIssuesReflection.Descriptor));
var parser = new JsonParser(settings);
// It is safe to use either original field name or explicitly specified json_name
Assert.AreEqual(new TestJsonName { Name = "test", Description = "test2", Guid = "test3" },
parser.Parse<TestJsonName>("{ \"name\": \"test\", \"desc\": \"test2\", \"guid\": \"test3\" }"));
}
[Test]
public void JsonNameFormatTest()
{
var message = new TestJsonName { Name = "test", Description = "test2", Guid = "test3" };
Assert.AreEqual("{ \"name\": \"test\", \"desc\": \"test2\", \"exid\": \"test3\" }",
JsonFormatter.Default.Format(message));
}
}
}

@ -1,62 +1,62 @@
#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 UnitTest.Issues.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
public class TestCornerCases
{
[Test]
public void TestRoundTripNegativeEnums()
{
NegativeEnumMessage msg = new NegativeEnumMessage
{
Value = NegativeEnum.MinusOne,
Values = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
PackedValues = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
};
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);
}
}
}
#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 UnitTest.Issues.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
public class TestCornerCases
{
[Test]
public void TestRoundTripNegativeEnums()
{
NegativeEnumMessage msg = new NegativeEnumMessage
{
Value = NegativeEnum.MinusOne,
Values = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
PackedValues = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
};
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);
}
}
}

@ -13,7 +13,9 @@ pushd $(dirname $0)/..
# Windows and Unix.
if [ -z "$PROTOC" ]; then
# TODO(jonskeet): Use an array and a for loop instead?
if [ -x cmake/build/Debug/protoc.exe ]; then
if [ -x solution/Debug/protoc.exe ]; then
PROTOC=solution/Debug/protoc.exe
elif [ -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

@ -156,3 +156,17 @@ message MixedRegularAndOptional {
string regular_field = 1;
optional string optional_field = 2;
}
message OneofWithNoneField {
oneof test {
string x = 1;
string none = 2;
}
}
message OneofWithNoneName {
oneof none {
string x = 1;
string y = 2;
}
}

@ -1,132 +1,132 @@
#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.Protobuf.Examples.AddressBook
{
internal class AddPerson
{
/// <summary>
/// Builds a person based on user input
/// </summary>
private static Person PromptForAddress(TextReader input, TextWriter output)
{
Person person = new Person();
output.Write("Enter person ID: ");
person.Id = int.Parse(input.ReadLine());
output.Write("Enter name: ");
person.Name = input.ReadLine();
output.Write("Enter email address (blank for none): ");
string email = input.ReadLine();
if (email.Length > 0)
{
person.Email = email;
}
while (true)
{
output.Write("Enter a phone number (or leave blank to finish): ");
string number = input.ReadLine();
if (number.Length == 0)
{
break;
}
Person.Types.PhoneNumber phoneNumber = new Person.Types.PhoneNumber { Number = number };
output.Write("Is this a mobile, home, or work phone? ");
String type = input.ReadLine();
switch (type)
{
case "mobile":
phoneNumber.Type = Person.Types.PhoneType.Mobile;
break;
case "home":
phoneNumber.Type = Person.Types.PhoneType.Home;
break;
case "work":
phoneNumber.Type = Person.Types.PhoneType.Work;
break;
default:
output.Write("Unknown phone type. Using default.");
break;
}
person.Phones.Add(phoneNumber);
}
return person;
}
/// <summary>
/// Entry point - loads an existing addressbook or creates a new one,
/// then writes it back to the file.
/// </summary>
public static int Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: AddPerson ADDRESS_BOOK_FILE");
return -1;
}
AddressBook addressBook;
if (File.Exists(args[0]))
{
using (Stream file = File.OpenRead(args[0]))
{
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.People.Add(PromptForAddress(Console.In, Console.Out));
// Write the new address book back to disk.
using (Stream output = File.OpenWrite(args[0]))
{
addressBook.WriteTo(output);
}
return 0;
}
}
#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.Protobuf.Examples.AddressBook
{
internal class AddPerson
{
/// <summary>
/// Builds a person based on user input
/// </summary>
private static Person PromptForAddress(TextReader input, TextWriter output)
{
Person person = new Person();
output.Write("Enter person ID: ");
person.Id = int.Parse(input.ReadLine());
output.Write("Enter name: ");
person.Name = input.ReadLine();
output.Write("Enter email address (blank for none): ");
string email = input.ReadLine();
if (email.Length > 0)
{
person.Email = email;
}
while (true)
{
output.Write("Enter a phone number (or leave blank to finish): ");
string number = input.ReadLine();
if (number.Length == 0)
{
break;
}
Person.Types.PhoneNumber phoneNumber = new Person.Types.PhoneNumber { Number = number };
output.Write("Is this a mobile, home, or work phone? ");
String type = input.ReadLine();
switch (type)
{
case "mobile":
phoneNumber.Type = Person.Types.PhoneType.Mobile;
break;
case "home":
phoneNumber.Type = Person.Types.PhoneType.Home;
break;
case "work":
phoneNumber.Type = Person.Types.PhoneType.Work;
break;
default:
output.Write("Unknown phone type. Using default.");
break;
}
person.Phones.Add(phoneNumber);
}
return person;
}
/// <summary>
/// Entry point - loads an existing addressbook or creates a new one,
/// then writes it back to the file.
/// </summary>
public static int Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: AddPerson ADDRESS_BOOK_FILE");
return -1;
}
AddressBook addressBook;
if (File.Exists(args[0]))
{
using (Stream file = File.OpenRead(args[0]))
{
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.People.Add(PromptForAddress(Console.In, Console.Out));
// Write the new address book back to disk.
using (Stream output = File.OpenWrite(args[0]))
{
addressBook.WriteTo(output);
}
return 0;
}
}
}

@ -1,99 +1,99 @@
#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.Protobuf.Examples.AddressBook
{
internal class ListPeople
{
/// <summary>
/// Iterates though all people in the AddressBook and prints info about them.
/// </summary>
private static void Print(AddressBook addressBook)
{
foreach (Person person in addressBook.People)
{
Console.WriteLine("Person ID: {0}", person.Id);
Console.WriteLine(" Name: {0}", person.Name);
if (person.Email != "")
{
Console.WriteLine(" E-mail address: {0}", person.Email);
}
foreach (Person.Types.PhoneNumber phoneNumber in person.Phones)
{
switch (phoneNumber.Type)
{
case Person.Types.PhoneType.Mobile:
Console.Write(" Mobile phone #: ");
break;
case Person.Types.PhoneType.Home:
Console.Write(" Home phone #: ");
break;
case Person.Types.PhoneType.Work:
Console.Write(" Work phone #: ");
break;
}
Console.WriteLine(phoneNumber.Number);
}
}
}
/// <summary>
/// Entry point - loads the addressbook and then displays it.
/// </summary>
public static int Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: ListPeople ADDRESS_BOOK_FILE");
return 1;
}
if (!File.Exists(args[0]))
{
Console.WriteLine("{0} doesn't exist. Add a person to create the file first.", args[0]);
return 0;
}
// Read the existing address book.
using (Stream stream = File.OpenRead(args[0]))
{
AddressBook addressBook = AddressBook.Parser.ParseFrom(stream);
Print(addressBook);
}
return 0;
}
}
#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.Protobuf.Examples.AddressBook
{
internal class ListPeople
{
/// <summary>
/// Iterates though all people in the AddressBook and prints info about them.
/// </summary>
private static void Print(AddressBook addressBook)
{
foreach (Person person in addressBook.People)
{
Console.WriteLine("Person ID: {0}", person.Id);
Console.WriteLine(" Name: {0}", person.Name);
if (person.Email != "")
{
Console.WriteLine(" E-mail address: {0}", person.Email);
}
foreach (Person.Types.PhoneNumber phoneNumber in person.Phones)
{
switch (phoneNumber.Type)
{
case Person.Types.PhoneType.Mobile:
Console.Write(" Mobile phone #: ");
break;
case Person.Types.PhoneType.Home:
Console.Write(" Home phone #: ");
break;
case Person.Types.PhoneType.Work:
Console.Write(" Work phone #: ");
break;
}
Console.WriteLine(phoneNumber.Number);
}
}
}
/// <summary>
/// Entry point - loads the addressbook and then displays it.
/// </summary>
public static int Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: ListPeople ADDRESS_BOOK_FILE");
return 1;
}
if (!File.Exists(args[0]))
{
Console.WriteLine("{0} doesn't exist. Add a person to create the file first.", args[0]);
return 0;
}
// Read the existing address book.
using (Stream stream = File.OpenRead(args[0]))
{
AddressBook addressBook = AddressBook.Parser.ParseFrom(stream);
Print(addressBook);
}
return 0;
}
}
}

@ -1,95 +1,95 @@
#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.Examples.AddressBook
{
/// <summary>
/// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour
/// to individual actions. Each action has its own Main method, so that it can be used as an
/// individual complete program.
/// </summary>
internal class Program
{
private static int Main(string[] args)
{
if (args.Length > 1)
{
Console.Error.WriteLine("Usage: AddressBook [file]");
Console.Error.WriteLine("If the filename isn't specified, \"addressbook.data\" is used instead.");
return 1;
}
string addressBookFile = args.Length > 0 ? args[0] : "addressbook.data";
bool stopping = false;
while (!stopping)
{
Console.WriteLine("Options:");
Console.WriteLine(" L: List contents");
Console.WriteLine(" A: Add new person");
Console.WriteLine(" Q: Quit");
Console.Write("Action? ");
Console.Out.Flush();
char choice = Console.ReadKey().KeyChar;
Console.WriteLine();
try
{
switch (choice)
{
case 'A':
case 'a':
AddPerson.Main(new string[] {addressBookFile});
break;
case 'L':
case 'l':
ListPeople.Main(new string[] {addressBookFile});
break;
case 'Q':
case 'q':
stopping = true;
break;
default:
Console.WriteLine("Unknown option: {0}", choice);
break;
}
}
catch (Exception e)
{
Console.WriteLine("Exception executing action: {0}", e);
}
Console.WriteLine();
}
return 0;
}
}
#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.Examples.AddressBook
{
/// <summary>
/// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour
/// to individual actions. Each action has its own Main method, so that it can be used as an
/// individual complete program.
/// </summary>
internal class Program
{
private static int Main(string[] args)
{
if (args.Length > 1)
{
Console.Error.WriteLine("Usage: AddressBook [file]");
Console.Error.WriteLine("If the filename isn't specified, \"addressbook.data\" is used instead.");
return 1;
}
string addressBookFile = args.Length > 0 ? args[0] : "addressbook.data";
bool stopping = false;
while (!stopping)
{
Console.WriteLine("Options:");
Console.WriteLine(" L: List contents");
Console.WriteLine(" A: Add new person");
Console.WriteLine(" Q: Quit");
Console.Write("Action? ");
Console.Out.Flush();
char choice = Console.ReadKey().KeyChar;
Console.WriteLine();
try
{
switch (choice)
{
case 'A':
case 'a':
AddPerson.Main(new string[] {addressBookFile});
break;
case 'L':
case 'l':
ListPeople.Main(new string[] {addressBookFile});
break;
case 'Q':
case 'q':
stopping = true;
break;
default:
Console.WriteLine("Unknown option: {0}", choice);
break;
}
}
catch (Exception e)
{
Console.WriteLine("Exception executing action: {0}", e);
}
Console.WriteLine();
}
return 0;
}
}
}

@ -1,73 +1,73 @@
#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.Protobuf.Examples.AddressBook
{
internal class SampleUsage
{
private static void Main()
{
byte[] bytes;
// 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
person.WriteTo(stream);
bytes = stream.ToArray();
}
Person copy = Person.Parser.ParseFrom(bytes);
AddressBook book = new AddressBook
{
People = { copy }
};
bytes = book.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 Exception("There is a bad person in here!");
}
}
}
#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.Protobuf.Examples.AddressBook
{
internal class SampleUsage
{
private static void Main()
{
byte[] bytes;
// 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
person.WriteTo(stream);
bytes = stream.ToArray();
}
Person copy = Person.Parser.ParseFrom(bytes);
AddressBook book = new AddressBook
{
People = { copy }
};
bytes = book.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 Exception("There is a bad person in here!");
}
}
}
}

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<IsPackable>False</IsPackable>
@ -15,7 +15,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj" />
</ItemGroup>

@ -1,73 +1,73 @@
#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.Reflection;
namespace Google.Protobuf.ProtoDump
{
/// <summary>
/// Small utility to load a binary message and dump it in JSON format.
/// </summary>
internal class Program
{
private static int Main(string[] args)
{
if (args.Length != 2)
{
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;
}
Type type = Type.GetType(args[0]);
if (type == null)
{
Console.Error.WriteLine("Unable to load type {0}.", args[0]);
return 1;
}
if (!typeof(IMessage).GetTypeInfo().IsAssignableFrom(type))
{
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;
}
}
#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.Reflection;
namespace Google.Protobuf.ProtoDump
{
/// <summary>
/// Small utility to load a binary message and dump it in JSON format.
/// </summary>
internal class Program
{
private static int Main(string[] args)
{
if (args.Length != 2)
{
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;
}
Type type = Type.GetType(args[0]);
if (type == null)
{
Console.Error.WriteLine("Unable to load type {0}.", args[0]);
return 1;
}
if (!typeof(IMessage).GetTypeInfo().IsAssignableFrom(type))
{
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;
}
}
}

@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<!--
This TestProtos project is kept separate from the original test project for many reasons.
It allows us to make sure code can compile on a separate compiler version, different frameworks,
and without the internal visibility from the test project (all of which have caused issues in the past).
-->
<PropertyGroup>
<TargetFrameworks>net462;netstandard1.1;netstandard2.0</TargetFrameworks>
<LangVersion>3.0</LangVersion>
<AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<IsPackable>False</IsPackable>
</PropertyGroup>
<!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<!--
This TestProtos project is kept separate from the original test project for many reasons.
It allows us to make sure code can compile on a separate compiler version, different frameworks,
and without the internal visibility from the test project (all of which have caused issues in the past).
-->
<PropertyGroup>
<TargetFrameworks>net462;netstandard1.1;netstandard2.0</TargetFrameworks>
<LangVersion>3.0</LangVersion>
<AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<IsPackable>False</IsPackable>
</PropertyGroup>
<!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj" />
</ItemGroup>
</Project>

@ -226,7 +226,7 @@ namespace ProtobufTestMessages.Proto3 {
"dG8zLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0ZWRFbnVtEgcKA0ZPTxAAEgcK",
"A0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8BIlkKC0FsaWFzZWRF",
"bnVtEg0KCUFMSUFTX0ZPTxAAEg0KCUFMSUFTX0JBUhABEg0KCUFMSUFTX0JB",
"WhACEgcKA1FVWBACEgcKA3F1eBACEgcKA2JBehACGgIQAUINCgtvbmVvZl9m",
"WhACEgcKA01PTxACEgcKA21vbxACEgcKA2JBehACGgIQAUINCgtvbmVvZl9m",
"aWVsZEoGCPUDEP8DIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUiFgoU",
"TnVsbEh5cG90aGVzaXNQcm90bzMiLwoORW51bU9ubHlQcm90bzMiHQoEQm9v",
"bBIKCgZrRmFsc2UQABIJCgVrVHJ1ZRABKkAKC0ZvcmVpZ25FbnVtEg8KC0ZP",
@ -5432,8 +5432,8 @@ namespace ProtobufTestMessages.Proto3 {
[pbr::OriginalName("ALIAS_FOO")] AliasFoo = 0,
[pbr::OriginalName("ALIAS_BAR")] AliasBar = 1,
[pbr::OriginalName("ALIAS_BAZ")] AliasBaz = 2,
[pbr::OriginalName("QUX", PreferredAlias = false)] Qux = 2,
[pbr::OriginalName("qux", PreferredAlias = false)] Qux_ = 2,
[pbr::OriginalName("MOO", PreferredAlias = false)] Moo = 2,
[pbr::OriginalName("moo", PreferredAlias = false)] Moo_ = 2,
[pbr::OriginalName("bAz", PreferredAlias = false)] BAz = 2,
}

@ -54,11 +54,13 @@ namespace UnitTest.Issues.TestProtos {
"dEluT25lb2YSLgoKbnVsbF92YWx1ZRgCIAEoDjIaLmdvb2dsZS5wcm90b2J1",
"Zi5OdWxsVmFsdWUiYAoXTWl4ZWRSZWd1bGFyQW5kT3B0aW9uYWwSFQoNcmVn",
"dWxhcl9maWVsZBgBIAEoCRIbCg5vcHRpb25hbF9maWVsZBgCIAEoCUgAiAEB",
"QhEKD19vcHRpb25hbF9maWVsZCpVCgxOZWdhdGl2ZUVudW0SFgoSTkVHQVRJ",
"VkVfRU5VTV9aRVJPEAASFgoJRml2ZUJlbG93EPv//////////wESFQoITWlu",
"dXNPbmUQ////////////ASouCg5EZXByZWNhdGVkRW51bRITCg9ERVBSRUNB",
"VEVEX1pFUk8QABIHCgNvbmUQAUIdqgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQ",
"cm90b3NiBnByb3RvMw=="));
"QhEKD19vcHRpb25hbF9maWVsZCI5ChJPbmVvZldpdGhOb25lRmllbGQSCwoB",
"eBgBIAEoCUgAEg4KBG5vbmUYAiABKAlIAEIGCgR0ZXN0IjUKEU9uZW9mV2l0",
"aE5vbmVOYW1lEgsKAXgYASABKAlIABILCgF5GAIgASgJSABCBgoEbm9uZSpV",
"CgxOZWdhdGl2ZUVudW0SFgoSTkVHQVRJVkVfRU5VTV9aRVJPEAASFgoJRml2",
"ZUJlbG93EPv//////////wESFQoITWludXNPbmUQ////////////ASouCg5E",
"ZXByZWNhdGVkRW51bRITCg9ERVBSRUNBVEVEX1pFUk8QABIHCgNvbmUQAUId",
"qgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQcm90b3NiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, null, new pbr::GeneratedClrTypeInfo[] {
@ -73,7 +75,9 @@ namespace UnitTest.Issues.TestProtos {
new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging), global::UnitTest.Issues.TestProtos.OneofMerging.Parser, new[]{ "Text", "Nested" }, new[]{ "Value" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested), global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested.Parser, new[]{ "X", "Y" }, null, null, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueOutsideStruct), global::UnitTest.Issues.TestProtos.NullValueOutsideStruct.Parser, new[]{ "StringValue", "NullValue" }, new[]{ "Value" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueNotInOneof), global::UnitTest.Issues.TestProtos.NullValueNotInOneof.Parser, new[]{ "NullValue" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.MixedRegularAndOptional), global::UnitTest.Issues.TestProtos.MixedRegularAndOptional.Parser, new[]{ "RegularField", "OptionalField" }, new[]{ "OptionalField" }, null, null, null)
new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.MixedRegularAndOptional), global::UnitTest.Issues.TestProtos.MixedRegularAndOptional.Parser, new[]{ "RegularField", "OptionalField" }, new[]{ "OptionalField" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofWithNoneField), global::UnitTest.Issues.TestProtos.OneofWithNoneField.Parser, new[]{ "X", "None" }, new[]{ "Test" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofWithNoneName), global::UnitTest.Issues.TestProtos.OneofWithNoneName.Parser, new[]{ "X", "Y" }, new[]{ "None" }, null, null, null)
}));
}
#endregion
@ -3825,6 +3829,524 @@ namespace UnitTest.Issues.TestProtos {
}
public sealed partial class OneofWithNoneField : pb::IMessage<OneofWithNoneField>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<OneofWithNoneField> _parser = new pb::MessageParser<OneofWithNoneField>(() => new OneofWithNoneField());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<OneofWithNoneField> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[12]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public OneofWithNoneField() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public OneofWithNoneField(OneofWithNoneField other) : this() {
switch (other.TestCase) {
case TestOneofCase.X:
X = other.X;
break;
case TestOneofCase.None_:
None = other.None;
break;
}
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public OneofWithNoneField Clone() {
return new OneofWithNoneField(this);
}
/// <summary>Field number for the "x" field.</summary>
public const int XFieldNumber = 1;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string X {
get { return testCase_ == TestOneofCase.X ? (string) test_ : ""; }
set {
test_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
testCase_ = TestOneofCase.X;
}
}
/// <summary>Field number for the "none" field.</summary>
public const int NoneFieldNumber = 2;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string None {
get { return testCase_ == TestOneofCase.None_ ? (string) test_ : ""; }
set {
test_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
testCase_ = TestOneofCase.None_;
}
}
private object test_;
/// <summary>Enum of possible cases for the "test" oneof.</summary>
public enum TestOneofCase {
None = 0,
X = 1,
None_ = 2,
}
private TestOneofCase testCase_ = TestOneofCase.None;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public TestOneofCase TestCase {
get { return testCase_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void ClearTest() {
testCase_ = TestOneofCase.None;
test_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as OneofWithNoneField);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(OneofWithNoneField other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (X != other.X) return false;
if (None != other.None) return false;
if (TestCase != other.TestCase) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (testCase_ == TestOneofCase.X) hash ^= X.GetHashCode();
if (testCase_ == TestOneofCase.None_) hash ^= None.GetHashCode();
hash ^= (int) testCase_;
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (testCase_ == TestOneofCase.X) {
output.WriteRawTag(10);
output.WriteString(X);
}
if (testCase_ == TestOneofCase.None_) {
output.WriteRawTag(18);
output.WriteString(None);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (testCase_ == TestOneofCase.X) {
output.WriteRawTag(10);
output.WriteString(X);
}
if (testCase_ == TestOneofCase.None_) {
output.WriteRawTag(18);
output.WriteString(None);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (testCase_ == TestOneofCase.X) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(X);
}
if (testCase_ == TestOneofCase.None_) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(None);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(OneofWithNoneField other) {
if (other == null) {
return;
}
switch (other.TestCase) {
case TestOneofCase.X:
X = other.X;
break;
case TestOneofCase.None_:
None = other.None;
break;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
X = input.ReadString();
break;
}
case 18: {
None = input.ReadString();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
X = input.ReadString();
break;
}
case 18: {
None = input.ReadString();
break;
}
}
}
}
#endif
}
public sealed partial class OneofWithNoneName : pb::IMessage<OneofWithNoneName>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<OneofWithNoneName> _parser = new pb::MessageParser<OneofWithNoneName>(() => new OneofWithNoneName());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<OneofWithNoneName> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[13]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public OneofWithNoneName() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public OneofWithNoneName(OneofWithNoneName other) : this() {
switch (other.NoneCase) {
case NoneOneofCase.X:
X = other.X;
break;
case NoneOneofCase.Y:
Y = other.Y;
break;
}
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public OneofWithNoneName Clone() {
return new OneofWithNoneName(this);
}
/// <summary>Field number for the "x" field.</summary>
public const int XFieldNumber = 1;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string X {
get { return noneCase_ == NoneOneofCase.X ? (string) none_ : ""; }
set {
none_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
noneCase_ = NoneOneofCase.X;
}
}
/// <summary>Field number for the "y" field.</summary>
public const int YFieldNumber = 2;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Y {
get { return noneCase_ == NoneOneofCase.Y ? (string) none_ : ""; }
set {
none_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
noneCase_ = NoneOneofCase.Y;
}
}
private object none_;
/// <summary>Enum of possible cases for the "none" oneof.</summary>
public enum NoneOneofCase {
None = 0,
X = 1,
Y = 2,
}
private NoneOneofCase noneCase_ = NoneOneofCase.None;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public NoneOneofCase NoneCase {
get { return noneCase_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void ClearNone() {
noneCase_ = NoneOneofCase.None;
none_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as OneofWithNoneName);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(OneofWithNoneName other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (X != other.X) return false;
if (Y != other.Y) return false;
if (NoneCase != other.NoneCase) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (noneCase_ == NoneOneofCase.X) hash ^= X.GetHashCode();
if (noneCase_ == NoneOneofCase.Y) hash ^= Y.GetHashCode();
hash ^= (int) noneCase_;
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (noneCase_ == NoneOneofCase.X) {
output.WriteRawTag(10);
output.WriteString(X);
}
if (noneCase_ == NoneOneofCase.Y) {
output.WriteRawTag(18);
output.WriteString(Y);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (noneCase_ == NoneOneofCase.X) {
output.WriteRawTag(10);
output.WriteString(X);
}
if (noneCase_ == NoneOneofCase.Y) {
output.WriteRawTag(18);
output.WriteString(Y);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (noneCase_ == NoneOneofCase.X) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(X);
}
if (noneCase_ == NoneOneofCase.Y) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Y);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(OneofWithNoneName other) {
if (other == null) {
return;
}
switch (other.NoneCase) {
case NoneOneofCase.X:
X = other.X;
break;
case NoneOneofCase.Y:
Y = other.Y;
break;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
X = input.ReadString();
break;
}
case 18: {
Y = input.ReadString();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
X = input.ReadString();
break;
}
case 18: {
Y = input.ReadString();
break;
}
}
}
}
#endif
}
#endregion
}

@ -1,439 +1,439 @@
#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.Text;
using NUnit.Framework;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Buffers;
using System.Runtime.InteropServices;
using System.Threading;
using System.Runtime.CompilerServices;
#if !NET35
using System.Threading.Tasks;
#endif
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);
EqualityTester.AssertEquality(ByteString.Empty, ByteString.Empty);
#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);
Assert.IsTrue(ByteString.Empty == ByteString.Empty);
#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()
{
Assert.AreEqual(0, ByteString.Empty.Length);
}
[Test]
public void CopyFromStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
Assert.AreEqual(4, bs.Length);
Assert.AreEqual(65, bs[0]);
Assert.AreEqual(0, bs[1]);
Assert.AreEqual(66, bs[2]);
Assert.AreEqual(0, bs[3]);
}
[Test]
public void IsEmptyWhenEmpty()
{
Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
}
[Test]
public void IsEmptyWhenNotEmpty()
{
Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
}
[Test]
public void CopyFromByteArrayCopiesContents()
{
byte[] data = new byte[1];
data[0] = 10;
ByteString bs = ByteString.CopyFrom(data);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void CopyFromReadOnlySpanCopiesContents()
{
byte[] data = new byte[1];
data[0] = 10;
ReadOnlySpan<byte> byteSpan = data;
var bs = ByteString.CopyFrom(byteSpan);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void ToByteArrayCopiesContents()
{
ByteString bs = ByteString.CopyFromUtf8("Hello");
byte[] data = bs.ToByteArray();
Assert.AreEqual((byte)'H', data[0]);
Assert.AreEqual((byte)'H', bs[0]);
data[0] = 0;
Assert.AreEqual(0, data[0]);
Assert.AreEqual((byte)'H', bs[0]);
}
[Test]
public void CopyFromUtf8UsesUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(0xe2, bs[0]);
Assert.AreEqual(0x82, bs[1]);
Assert.AreEqual(0xac, bs[2]);
}
[Test]
public void CopyFromPortion()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
ByteString bs = ByteString.CopyFrom(data, 2, 3);
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(2, bs[0]);
Assert.AreEqual(3, bs[1]);
}
[Test]
public void CopyTo()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
byte[] dest = new byte[data.Length];
bs.CopyTo(dest, 0);
CollectionAssert.AreEqual(data, dest);
}
[Test]
public void GetEnumerator()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
IEnumerator<byte> genericEnumerator = bs.GetEnumerator();
Assert.IsTrue(genericEnumerator.MoveNext());
Assert.AreEqual(0, genericEnumerator.Current);
IEnumerator enumerator = ((IEnumerable)bs).GetEnumerator();
Assert.IsTrue(enumerator.MoveNext());
Assert.AreEqual(0, enumerator.Current);
// Call via LINQ
CollectionAssert.AreEqual(bs.Span.ToArray(), bs.ToArray());
}
[Test]
public void UnsafeWrap()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
ReadOnlySpan<byte> s = bs.Span;
Assert.AreEqual(3, s.Length);
Assert.AreEqual(2, s[0]);
Assert.AreEqual(3, s[1]);
Assert.AreEqual(4, s[2]);
// Check that the value is not a copy
data[2] = byte.MaxValue;
Assert.AreEqual(byte.MaxValue, s[0]);
}
[Test]
public void CreateCodedInput_FromArraySegment()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
CodedInputStream codedInputStream = bs.CreateCodedInput();
byte[] bytes = codedInputStream.ReadRawBytes(3);
Assert.AreEqual(3, bytes.Length);
Assert.AreEqual(2, bytes[0]);
Assert.AreEqual(3, bytes[1]);
Assert.AreEqual(4, bytes[2]);
Assert.IsTrue(codedInputStream.IsAtEnd);
}
[Test]
public void WriteToStream()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
MemoryStream ms = new MemoryStream();
bs.WriteTo(ms);
CollectionAssert.AreEqual(data, ms.ToArray());
}
[Test]
public void WriteToStream_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
MemoryStream ms = new MemoryStream();
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
bs.WriteTo(ms);
}
CollectionAssert.AreEqual(data, ms.ToArray());
}
[Test]
public void ToStringUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual("\u20ac", bs.ToStringUtf8());
}
[Test]
public void ToStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
}
[Test]
public void ToString_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8));
}
}
[Test]
public void FromBase64_WithText()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
string base64 = Convert.ToBase64String(data);
ByteString bs = ByteString.FromBase64(base64);
Assert.AreEqual(data, bs.ToByteArray());
}
[Test]
public void FromBase64_Empty()
{
// Optimization which also fixes issue 61.
Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
}
[Test]
public void ToBase64_Array()
{
ByteString bs = ByteString.CopyFrom(Encoding.UTF8.GetBytes("Hello world"));
Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
}
[Test]
public void ToBase64_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
}
}
[Test]
public void FromStream_Seekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
var actual = ByteString.FromStream(stream);
ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
[Test]
public void FromStream_NotSeekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
// Wrap the original stream in LimitedInputStream, which has CanSeek=false
var limitedStream = new LimitedInputStream(stream, 3);
var actual = ByteString.FromStream(limitedStream);
ByteString expected = ByteString.CopyFrom(2, 3, 4);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
#if !NET35
[Test]
public async Task FromStreamAsync_Seekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
var actual = await ByteString.FromStreamAsync(stream);
ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
[Test]
public async Task FromStreamAsync_NotSeekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
// Wrap the original stream in LimitedInputStream, which has CanSeek=false
var limitedStream = new LimitedInputStream(stream, 3);
var actual = await ByteString.FromStreamAsync(limitedStream);
ByteString expected = ByteString.CopyFrom(2, 3, 4);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
#endif
[Test]
public void GetHashCode_Regression()
{
// We used to have an awful hash algorithm where only the last four
// bytes were relevant. This is a regression test for
// https://github.com/protocolbuffers/protobuf/issues/2511
ByteString b1 = ByteString.CopyFrom(100, 1, 2, 3, 4);
ByteString b2 = ByteString.CopyFrom(200, 1, 2, 3, 4);
Assert.AreNotEqual(b1.GetHashCode(), b2.GetHashCode());
}
[Test]
public void GetContentsAsReadOnlySpan()
{
var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);
var copied = byteString.Span.ToArray();
CollectionAssert.AreEqual(byteString, copied);
}
[Test]
public void GetContentsAsReadOnlyMemory()
{
var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);
var copied = byteString.Memory.ToArray();
CollectionAssert.AreEqual(byteString, copied);
}
// Create Memory<byte> from non-array source.
// Use by ByteString tests that have optimized path for array backed Memory<byte>.
private sealed unsafe class UnmanagedMemoryManager<T> : MemoryManager<T> where T : unmanaged
{
private readonly T* _pointer;
private readonly int _length;
public UnmanagedMemoryManager(Span<T> span)
{
fixed (T* ptr = &MemoryMarshal.GetReference(span))
{
_pointer = ptr;
_length = span.Length;
}
}
public override Span<T> GetSpan() => new Span<T>(_pointer, _length);
public override MemoryHandle Pin(int elementIndex = 0)
{
if (elementIndex < 0 || elementIndex >= _length)
{
throw new ArgumentOutOfRangeException(nameof(elementIndex));
}
return new MemoryHandle(_pointer + elementIndex);
}
public override void Unpin() { }
protected override void Dispose(bool disposing) { }
}
}
#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.Text;
using NUnit.Framework;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Buffers;
using System.Runtime.InteropServices;
using System.Threading;
using System.Runtime.CompilerServices;
#if !NET35
using System.Threading.Tasks;
#endif
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);
EqualityTester.AssertEquality(ByteString.Empty, ByteString.Empty);
#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);
Assert.IsTrue(ByteString.Empty == ByteString.Empty);
#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()
{
Assert.AreEqual(0, ByteString.Empty.Length);
}
[Test]
public void CopyFromStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
Assert.AreEqual(4, bs.Length);
Assert.AreEqual(65, bs[0]);
Assert.AreEqual(0, bs[1]);
Assert.AreEqual(66, bs[2]);
Assert.AreEqual(0, bs[3]);
}
[Test]
public void IsEmptyWhenEmpty()
{
Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
}
[Test]
public void IsEmptyWhenNotEmpty()
{
Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
}
[Test]
public void CopyFromByteArrayCopiesContents()
{
byte[] data = new byte[1];
data[0] = 10;
ByteString bs = ByteString.CopyFrom(data);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void CopyFromReadOnlySpanCopiesContents()
{
byte[] data = new byte[1];
data[0] = 10;
ReadOnlySpan<byte> byteSpan = data;
var bs = ByteString.CopyFrom(byteSpan);
Assert.AreEqual(10, bs[0]);
data[0] = 5;
Assert.AreEqual(10, bs[0]);
}
[Test]
public void ToByteArrayCopiesContents()
{
ByteString bs = ByteString.CopyFromUtf8("Hello");
byte[] data = bs.ToByteArray();
Assert.AreEqual((byte)'H', data[0]);
Assert.AreEqual((byte)'H', bs[0]);
data[0] = 0;
Assert.AreEqual(0, data[0]);
Assert.AreEqual((byte)'H', bs[0]);
}
[Test]
public void CopyFromUtf8UsesUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(0xe2, bs[0]);
Assert.AreEqual(0x82, bs[1]);
Assert.AreEqual(0xac, bs[2]);
}
[Test]
public void CopyFromPortion()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
ByteString bs = ByteString.CopyFrom(data, 2, 3);
Assert.AreEqual(3, bs.Length);
Assert.AreEqual(2, bs[0]);
Assert.AreEqual(3, bs[1]);
}
[Test]
public void CopyTo()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
byte[] dest = new byte[data.Length];
bs.CopyTo(dest, 0);
CollectionAssert.AreEqual(data, dest);
}
[Test]
public void GetEnumerator()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
IEnumerator<byte> genericEnumerator = bs.GetEnumerator();
Assert.IsTrue(genericEnumerator.MoveNext());
Assert.AreEqual(0, genericEnumerator.Current);
IEnumerator enumerator = ((IEnumerable)bs).GetEnumerator();
Assert.IsTrue(enumerator.MoveNext());
Assert.AreEqual(0, enumerator.Current);
// Call via LINQ
CollectionAssert.AreEqual(bs.Span.ToArray(), bs.ToArray());
}
[Test]
public void UnsafeWrap()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
ReadOnlySpan<byte> s = bs.Span;
Assert.AreEqual(3, s.Length);
Assert.AreEqual(2, s[0]);
Assert.AreEqual(3, s[1]);
Assert.AreEqual(4, s[2]);
// Check that the value is not a copy
data[2] = byte.MaxValue;
Assert.AreEqual(byte.MaxValue, s[0]);
}
[Test]
public void CreateCodedInput_FromArraySegment()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
CodedInputStream codedInputStream = bs.CreateCodedInput();
byte[] bytes = codedInputStream.ReadRawBytes(3);
Assert.AreEqual(3, bytes.Length);
Assert.AreEqual(2, bytes[0]);
Assert.AreEqual(3, bytes[1]);
Assert.AreEqual(4, bytes[2]);
Assert.IsTrue(codedInputStream.IsAtEnd);
}
[Test]
public void WriteToStream()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.CopyFrom(data);
MemoryStream ms = new MemoryStream();
bs.WriteTo(ms);
CollectionAssert.AreEqual(data, ms.ToArray());
}
[Test]
public void WriteToStream_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
MemoryStream ms = new MemoryStream();
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
bs.WriteTo(ms);
}
CollectionAssert.AreEqual(data, ms.ToArray());
}
[Test]
public void ToStringUtf8()
{
ByteString bs = ByteString.CopyFromUtf8("\u20ac");
Assert.AreEqual("\u20ac", bs.ToStringUtf8());
}
[Test]
public void ToStringWithExplicitEncoding()
{
ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
}
[Test]
public void ToString_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8));
}
}
[Test]
public void FromBase64_WithText()
{
byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
string base64 = Convert.ToBase64String(data);
ByteString bs = ByteString.FromBase64(base64);
Assert.AreEqual(data, bs.ToByteArray());
}
[Test]
public void FromBase64_Empty()
{
// Optimization which also fixes issue 61.
Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
}
[Test]
public void ToBase64_Array()
{
ByteString bs = ByteString.CopyFrom(Encoding.UTF8.GetBytes("Hello world"));
Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
}
[Test]
public void ToBase64_Stackalloc()
{
byte[] data = Encoding.UTF8.GetBytes("Hello world");
Span<byte> s = stackalloc byte[data.Length];
data.CopyTo(s);
using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
{
ByteString bs = ByteString.AttachBytes(manager.Memory);
Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
}
}
[Test]
public void FromStream_Seekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
var actual = ByteString.FromStream(stream);
ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
[Test]
public void FromStream_NotSeekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
// Wrap the original stream in LimitedInputStream, which has CanSeek=false
var limitedStream = new LimitedInputStream(stream, 3);
var actual = ByteString.FromStream(limitedStream);
ByteString expected = ByteString.CopyFrom(2, 3, 4);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
#if !NET35
[Test]
public async Task FromStreamAsync_Seekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
var actual = await ByteString.FromStreamAsync(stream);
ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
[Test]
public async Task FromStreamAsync_NotSeekable()
{
var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
// Consume the first byte, just to test that it's "from current position"
stream.ReadByte();
// Wrap the original stream in LimitedInputStream, which has CanSeek=false
var limitedStream = new LimitedInputStream(stream, 3);
var actual = await ByteString.FromStreamAsync(limitedStream);
ByteString expected = ByteString.CopyFrom(2, 3, 4);
Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
}
#endif
[Test]
public void GetHashCode_Regression()
{
// We used to have an awful hash algorithm where only the last four
// bytes were relevant. This is a regression test for
// https://github.com/protocolbuffers/protobuf/issues/2511
ByteString b1 = ByteString.CopyFrom(100, 1, 2, 3, 4);
ByteString b2 = ByteString.CopyFrom(200, 1, 2, 3, 4);
Assert.AreNotEqual(b1.GetHashCode(), b2.GetHashCode());
}
[Test]
public void GetContentsAsReadOnlySpan()
{
var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);
var copied = byteString.Span.ToArray();
CollectionAssert.AreEqual(byteString, copied);
}
[Test]
public void GetContentsAsReadOnlyMemory()
{
var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);
var copied = byteString.Memory.ToArray();
CollectionAssert.AreEqual(byteString, copied);
}
// Create Memory<byte> from non-array source.
// Use by ByteString tests that have optimized path for array backed Memory<byte>.
private sealed unsafe class UnmanagedMemoryManager<T> : MemoryManager<T> where T : unmanaged
{
private readonly T* _pointer;
private readonly int _length;
public UnmanagedMemoryManager(Span<T> span)
{
fixed (T* ptr = &MemoryMarshal.GetReference(span))
{
_pointer = ptr;
_length = span.Length;
}
}
public override Span<T> GetSpan() => new Span<T>(_pointer, _length);
public override MemoryHandle Pin(int elementIndex = 0)
{
if (elementIndex < 0 || elementIndex >= _length)
{
throw new ArgumentOutOfRangeException(nameof(elementIndex));
}
return new MemoryHandle(_pointer + elementIndex);
}
public override void Unpin() { }
protected override void Dispose(bool disposing) { }
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,55 +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"));
}
}
}
#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"));
}
}
}

@ -1,196 +1,196 @@
using System;
using System.Collections;
using Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf
{
public class ExtensionSetTest
{
[Test]
public void EmptyExtensionSet()
{
ExtensionSet<TestAllExtensions> extensions = new ExtensionSet<TestAllExtensions>();
Assert.AreEqual(0, extensions.CalculateSize());
}
[Test]
public void MergeExtensionSet()
{
ExtensionSet<TestAllExtensions> extensions = null;
ExtensionSet.Set(ref extensions, OptionalBoolExtension, true);
ExtensionSet<TestAllExtensions> other = null;
Assert.IsFalse(ExtensionSet.Has(ref other, OptionalBoolExtension));
ExtensionSet.MergeFrom(ref other, extensions);
Assert.IsTrue(ExtensionSet.Has(ref other, OptionalBoolExtension));
}
[Test]
public void TestMergeCodedInput()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var serialized = message.ToByteArray();
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertReadingMessage(
TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }),
serialized,
other =>
{
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
});
}
[Test]
public void TestMergeMessage()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = new TestAllExtensions();
Assert.AreNotEqual(message, other);
Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize());
other.MergeFrom(message);
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TryMergeFieldFrom_CodedInputStream()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalStringExtension, "abcd");
var input = new CodedInputStream(message.ToByteArray());
input.ExtensionRegistry = new ExtensionRegistry() { OptionalStringExtension };
input.ReadTag(); // TryMergeFieldFrom expects that a tag was just read and will inspect the LastTag value
ExtensionSet<TestAllExtensions> extensionSet = null;
// test the legacy overload of TryMergeFieldFrom that takes a CodedInputStream
Assert.IsTrue(ExtensionSet.TryMergeFieldFrom(ref extensionSet, input));
Assert.AreEqual("abcd", ExtensionSet.Get(ref extensionSet, OptionalStringExtension));
}
[Test]
public void GetSingle()
{
var extensionValue = new TestAllTypes.Types.NestedMessage() { Bb = 42 };
var untypedExtension = new Extension<TestAllExtensions, object>(OptionalNestedMessageExtension.FieldNumber, codec: null);
var wrongTypedExtension = new Extension<TestAllExtensions, TestAllTypes>(OptionalNestedMessageExtension.FieldNumber, codec: null);
var message = new TestAllExtensions();
var value1 = message.GetExtension(untypedExtension);
Assert.IsNull(value1);
message.SetExtension(OptionalNestedMessageExtension, extensionValue);
var value2 = message.GetExtension(untypedExtension);
Assert.IsNotNull(value2);
var valueBytes = ((IMessage)value2).ToByteArray();
var parsedValue = TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser.ParseFrom(valueBytes);
Assert.AreEqual(extensionValue, parsedValue);
var ex = Assert.Throws<InvalidOperationException>(() => message.GetExtension(wrongTypedExtension));
var expectedMessage = "The stored extension value has a type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes+Types+NestedMessage, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'. " +
"This a different from the requested type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'.";
Assert.AreEqual(expectedMessage, ex.Message);
}
[Test]
public void GetRepeated()
{
var extensionValue = new TestAllTypes.Types.NestedMessage() { Bb = 42 };
var untypedExtension = new Extension<TestAllExtensions, IList>(RepeatedNestedMessageExtension.FieldNumber, codec: null);
var wrongTypedExtension = new RepeatedExtension<TestAllExtensions, TestAllTypes>(RepeatedNestedMessageExtension.FieldNumber, codec: null);
var message = new TestAllExtensions();
var value1 = message.GetExtension(untypedExtension);
Assert.IsNull(value1);
var repeatedField = message.GetOrInitializeExtension<TestAllTypes.Types.NestedMessage>(RepeatedNestedMessageExtension);
repeatedField.Add(extensionValue);
var value2 = message.GetExtension(untypedExtension);
Assert.IsNotNull(value2);
Assert.AreEqual(1, value2.Count);
var valueBytes = ((IMessage)value2[0]).ToByteArray();
var parsedValue = TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser.ParseFrom(valueBytes);
Assert.AreEqual(extensionValue, parsedValue);
var ex = Assert.Throws<InvalidOperationException>(() => message.GetExtension(wrongTypedExtension));
var expectedMessage = "The stored extension value has a type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes+Types+NestedMessage, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'. " +
"This a different from the requested type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'.";
Assert.AreEqual(expectedMessage, ex.Message);
}
[Test]
public void TestEquals()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = new TestAllExtensions();
Assert.AreNotEqual(message, other);
Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize());
other.SetExtension(OptionalBoolExtension, true);
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestHashCode()
{
var message = new TestAllExtensions();
var hashCode = message.GetHashCode();
message.SetExtension(OptionalBoolExtension, true);
Assert.AreNotEqual(hashCode, message.GetHashCode());
}
[Test]
public void TestClone()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = message.Clone();
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestDefaultValueRoundTrip()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, false);
Assert.IsFalse(message.GetExtension(OptionalBoolExtension));
Assert.IsTrue(message.HasExtension(OptionalBoolExtension));
var bytes = message.ToByteArray();
var registry = new ExtensionRegistry { OptionalBoolExtension };
var parsed = TestAllExtensions.Parser.WithExtensionRegistry(registry).ParseFrom(bytes);
Assert.IsFalse(parsed.GetExtension(OptionalBoolExtension));
Assert.IsTrue(parsed.HasExtension(OptionalBoolExtension));
}
}
}
using System;
using System.Collections;
using Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf
{
public class ExtensionSetTest
{
[Test]
public void EmptyExtensionSet()
{
ExtensionSet<TestAllExtensions> extensions = new ExtensionSet<TestAllExtensions>();
Assert.AreEqual(0, extensions.CalculateSize());
}
[Test]
public void MergeExtensionSet()
{
ExtensionSet<TestAllExtensions> extensions = null;
ExtensionSet.Set(ref extensions, OptionalBoolExtension, true);
ExtensionSet<TestAllExtensions> other = null;
Assert.IsFalse(ExtensionSet.Has(ref other, OptionalBoolExtension));
ExtensionSet.MergeFrom(ref other, extensions);
Assert.IsTrue(ExtensionSet.Has(ref other, OptionalBoolExtension));
}
[Test]
public void TestMergeCodedInput()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var serialized = message.ToByteArray();
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertReadingMessage(
TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }),
serialized,
other =>
{
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
});
}
[Test]
public void TestMergeMessage()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = new TestAllExtensions();
Assert.AreNotEqual(message, other);
Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize());
other.MergeFrom(message);
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TryMergeFieldFrom_CodedInputStream()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalStringExtension, "abcd");
var input = new CodedInputStream(message.ToByteArray());
input.ExtensionRegistry = new ExtensionRegistry() { OptionalStringExtension };
input.ReadTag(); // TryMergeFieldFrom expects that a tag was just read and will inspect the LastTag value
ExtensionSet<TestAllExtensions> extensionSet = null;
// test the legacy overload of TryMergeFieldFrom that takes a CodedInputStream
Assert.IsTrue(ExtensionSet.TryMergeFieldFrom(ref extensionSet, input));
Assert.AreEqual("abcd", ExtensionSet.Get(ref extensionSet, OptionalStringExtension));
}
[Test]
public void GetSingle()
{
var extensionValue = new TestAllTypes.Types.NestedMessage() { Bb = 42 };
var untypedExtension = new Extension<TestAllExtensions, object>(OptionalNestedMessageExtension.FieldNumber, codec: null);
var wrongTypedExtension = new Extension<TestAllExtensions, TestAllTypes>(OptionalNestedMessageExtension.FieldNumber, codec: null);
var message = new TestAllExtensions();
var value1 = message.GetExtension(untypedExtension);
Assert.IsNull(value1);
message.SetExtension(OptionalNestedMessageExtension, extensionValue);
var value2 = message.GetExtension(untypedExtension);
Assert.IsNotNull(value2);
var valueBytes = ((IMessage)value2).ToByteArray();
var parsedValue = TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser.ParseFrom(valueBytes);
Assert.AreEqual(extensionValue, parsedValue);
var ex = Assert.Throws<InvalidOperationException>(() => message.GetExtension(wrongTypedExtension));
var expectedMessage = "The stored extension value has a type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes+Types+NestedMessage, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'. " +
"This a different from the requested type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'.";
Assert.AreEqual(expectedMessage, ex.Message);
}
[Test]
public void GetRepeated()
{
var extensionValue = new TestAllTypes.Types.NestedMessage() { Bb = 42 };
var untypedExtension = new Extension<TestAllExtensions, IList>(RepeatedNestedMessageExtension.FieldNumber, codec: null);
var wrongTypedExtension = new RepeatedExtension<TestAllExtensions, TestAllTypes>(RepeatedNestedMessageExtension.FieldNumber, codec: null);
var message = new TestAllExtensions();
var value1 = message.GetExtension(untypedExtension);
Assert.IsNull(value1);
var repeatedField = message.GetOrInitializeExtension<TestAllTypes.Types.NestedMessage>(RepeatedNestedMessageExtension);
repeatedField.Add(extensionValue);
var value2 = message.GetExtension(untypedExtension);
Assert.IsNotNull(value2);
Assert.AreEqual(1, value2.Count);
var valueBytes = ((IMessage)value2[0]).ToByteArray();
var parsedValue = TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser.ParseFrom(valueBytes);
Assert.AreEqual(extensionValue, parsedValue);
var ex = Assert.Throws<InvalidOperationException>(() => message.GetExtension(wrongTypedExtension));
var expectedMessage = "The stored extension value has a type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes+Types+NestedMessage, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'. " +
"This a different from the requested type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes, Google.Protobuf.Test.TestProtos, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604'.";
Assert.AreEqual(expectedMessage, ex.Message);
}
[Test]
public void TestEquals()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = new TestAllExtensions();
Assert.AreNotEqual(message, other);
Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize());
other.SetExtension(OptionalBoolExtension, true);
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestHashCode()
{
var message = new TestAllExtensions();
var hashCode = message.GetHashCode();
message.SetExtension(OptionalBoolExtension, true);
Assert.AreNotEqual(hashCode, message.GetHashCode());
}
[Test]
public void TestClone()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = message.Clone();
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestDefaultValueRoundTrip()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, false);
Assert.IsFalse(message.GetExtension(OptionalBoolExtension));
Assert.IsTrue(message.HasExtension(OptionalBoolExtension));
var bytes = message.ToByteArray();
var registry = new ExtensionRegistry { OptionalBoolExtension };
var parsed = TestAllExtensions.Parser.WithExtensionRegistry(registry).ParseFrom(bytes);
Assert.IsFalse(parsed.GetExtension(OptionalBoolExtension));
Assert.IsTrue(parsed.HasExtension(OptionalBoolExtension));
}
}
}

@ -1,397 +1,397 @@
using Google.Protobuf.TestProtos.Proto2;
using Proto2 = Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf
{
/// <summary>
/// Tests around the generated TestAllTypes message in unittest.proto
/// </summary>
public partial class GeneratedMessageTest
{
[Test]
public void DefaultProto2Values()
{
var message = new TestAllTypes();
Assert.AreEqual(false, message.OptionalBool);
Assert.AreEqual(ByteString.Empty, message.OptionalBytes);
Assert.AreEqual(0.0, message.OptionalDouble);
Assert.AreEqual(0, message.OptionalFixed32);
Assert.AreEqual(0L, message.OptionalFixed64);
Assert.AreEqual(0.0f, message.OptionalFloat);
Assert.AreEqual(ForeignEnum.ForeignFoo, message.OptionalForeignEnum);
Assert.IsNull(message.OptionalForeignMessage);
Assert.AreEqual(ImportEnum.ImportFoo, message.OptionalImportEnum);
Assert.IsNull(message.OptionalImportMessage);
Assert.AreEqual(0, message.OptionalInt32);
Assert.AreEqual(0L, message.OptionalInt64);
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.OptionalNestedEnum);
Assert.IsNull(message.OptionalNestedMessage);
Assert.IsNull(message.OptionalPublicImportMessage);
Assert.AreEqual(0, message.OptionalSfixed32);
Assert.AreEqual(0L, message.OptionalSfixed64);
Assert.AreEqual(0, message.OptionalSint32);
Assert.AreEqual(0L, message.OptionalSint64);
Assert.AreEqual("", message.OptionalString);
Assert.AreEqual(0U, message.OptionalUint32);
Assert.AreEqual(0UL, message.OptionalUint64);
// 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.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(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(true, message.DefaultBool);
Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.DefaultBytes);
Assert.AreEqual("123", message.DefaultCord);
Assert.AreEqual(52e3, message.DefaultDouble);
Assert.AreEqual(47, message.DefaultFixed32);
Assert.AreEqual(48, message.DefaultFixed64);
Assert.AreEqual(51.5, message.DefaultFloat);
Assert.AreEqual(ForeignEnum.ForeignBar, message.DefaultForeignEnum);
Assert.AreEqual(ImportEnum.ImportBar, message.DefaultImportEnum);
Assert.AreEqual(41, message.DefaultInt32);
Assert.AreEqual(42, message.DefaultInt64);
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.DefaultNestedEnum);
Assert.AreEqual(49, message.DefaultSfixed32);
Assert.AreEqual(-50, message.DefaultSfixed64);
Assert.AreEqual(-45, message.DefaultSint32);
Assert.AreEqual(46, message.DefaultSint64);
Assert.AreEqual("hello", message.DefaultString);
Assert.AreEqual("abc", message.DefaultStringPiece);
Assert.AreEqual(43, message.DefaultUint32);
Assert.AreEqual(44, message.DefaultUint64);
Assert.False(message.HasDefaultBool);
Assert.False(message.HasDefaultBytes);
Assert.False(message.HasDefaultCord);
Assert.False(message.HasDefaultDouble);
Assert.False(message.HasDefaultFixed32);
Assert.False(message.HasDefaultFixed64);
Assert.False(message.HasDefaultFloat);
Assert.False(message.HasDefaultForeignEnum);
Assert.False(message.HasDefaultImportEnum);
Assert.False(message.HasDefaultInt32);
Assert.False(message.HasDefaultInt64);
Assert.False(message.HasDefaultNestedEnum);
Assert.False(message.HasDefaultSfixed32);
Assert.False(message.HasDefaultSfixed64);
Assert.False(message.HasDefaultSint32);
Assert.False(message.HasDefaultSint64);
Assert.False(message.HasDefaultString);
Assert.False(message.HasDefaultStringPiece);
Assert.False(message.HasDefaultUint32);
Assert.False(message.HasDefaultUint64);
}
[Test]
public void DefaultExtensionValues()
{
var message = new TestAllExtensions();
Assert.AreEqual(false, message.GetExtension(OptionalBoolExtension));
Assert.AreEqual(ByteString.Empty, message.GetExtension(OptionalBytesExtension));
Assert.AreEqual(0.0, message.GetExtension(OptionalDoubleExtension));
Assert.AreEqual(0, message.GetExtension(OptionalFixed32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalFixed64Extension));
Assert.AreEqual(0.0f, message.GetExtension(OptionalFloatExtension));
Assert.AreEqual(ForeignEnum.ForeignFoo, message.GetExtension(OptionalForeignEnumExtension));
Assert.IsNull(message.GetExtension(OptionalForeignMessageExtension));
Assert.AreEqual(ImportEnum.ImportFoo, message.GetExtension(OptionalImportEnumExtension));
Assert.IsNull(message.GetExtension(OptionalImportMessageExtension));
Assert.AreEqual(0, message.GetExtension(OptionalInt32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalInt64Extension));
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.GetExtension(OptionalNestedEnumExtension));
Assert.IsNull(message.GetExtension(OptionalNestedMessageExtension));
Assert.IsNull(message.GetExtension(OptionalPublicImportMessageExtension));
Assert.AreEqual(0, message.GetExtension(OptionalSfixed32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalSfixed64Extension));
Assert.AreEqual(0, message.GetExtension(OptionalSint32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalSint64Extension));
Assert.AreEqual("", message.GetExtension(OptionalStringExtension));
Assert.AreEqual(0U, message.GetExtension(OptionalUint32Extension));
Assert.AreEqual(0UL, message.GetExtension(OptionalUint64Extension));
// Repeated fields
Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
Assert.IsNull(message.GetExtension(RepeatedBytesExtension));
Assert.IsNull(message.GetExtension(RepeatedDoubleExtension));
Assert.IsNull(message.GetExtension(RepeatedFixed32Extension));
Assert.IsNull(message.GetExtension(RepeatedFixed64Extension));
Assert.IsNull(message.GetExtension(RepeatedFloatExtension));
Assert.IsNull(message.GetExtension(RepeatedForeignEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedForeignMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedImportEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedImportMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedNestedEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedNestedMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedSfixed32Extension));
Assert.IsNull(message.GetExtension(RepeatedSfixed64Extension));
Assert.IsNull(message.GetExtension(RepeatedSint32Extension));
Assert.IsNull(message.GetExtension(RepeatedSint64Extension));
Assert.IsNull(message.GetExtension(RepeatedStringExtension));
Assert.IsNull(message.GetExtension(RepeatedUint32Extension));
Assert.IsNull(message.GetExtension(RepeatedUint64Extension));
// Oneof fields
Assert.AreEqual(0, message.GetExtension(OneofUint32Extension));
Assert.AreEqual("", message.GetExtension(OneofStringExtension));
Assert.AreEqual(ByteString.Empty, message.GetExtension(OneofBytesExtension));
Assert.IsNull(message.GetExtension(OneofNestedMessageExtension));
Assert.AreEqual(true, message.GetExtension(DefaultBoolExtension));
Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.GetExtension(DefaultBytesExtension));
Assert.AreEqual("123", message.GetExtension(DefaultCordExtension));
Assert.AreEqual(52e3, message.GetExtension(DefaultDoubleExtension));
Assert.AreEqual(47, message.GetExtension(DefaultFixed32Extension));
Assert.AreEqual(48, message.GetExtension(DefaultFixed64Extension));
Assert.AreEqual(51.5, message.GetExtension(DefaultFloatExtension));
Assert.AreEqual(ForeignEnum.ForeignBar, message.GetExtension(DefaultForeignEnumExtension));
Assert.AreEqual(ImportEnum.ImportBar, message.GetExtension(DefaultImportEnumExtension));
Assert.AreEqual(41, message.GetExtension(DefaultInt32Extension));
Assert.AreEqual(42, message.GetExtension(DefaultInt64Extension));
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.GetExtension(DefaultNestedEnumExtension));
Assert.AreEqual(49, message.GetExtension(DefaultSfixed32Extension));
Assert.AreEqual(-50, message.GetExtension(DefaultSfixed64Extension));
Assert.AreEqual(-45, message.GetExtension(DefaultSint32Extension));
Assert.AreEqual(46, message.GetExtension(DefaultSint64Extension));
Assert.AreEqual("hello", message.GetExtension(DefaultStringExtension));
Assert.AreEqual("abc", message.GetExtension(DefaultStringPieceExtension));
Assert.AreEqual(43, message.GetExtension(DefaultUint32Extension));
Assert.AreEqual(44, message.GetExtension(DefaultUint64Extension));
Assert.False(message.HasExtension(DefaultBoolExtension));
Assert.False(message.HasExtension(DefaultBytesExtension));
Assert.False(message.HasExtension(DefaultCordExtension));
Assert.False(message.HasExtension(DefaultDoubleExtension));
Assert.False(message.HasExtension(DefaultFixed32Extension));
Assert.False(message.HasExtension(DefaultFixed64Extension));
Assert.False(message.HasExtension(DefaultFloatExtension));
Assert.False(message.HasExtension(DefaultForeignEnumExtension));
Assert.False(message.HasExtension(DefaultImportEnumExtension));
Assert.False(message.HasExtension(DefaultInt32Extension));
Assert.False(message.HasExtension(DefaultInt64Extension));
Assert.False(message.HasExtension(DefaultNestedEnumExtension));
Assert.False(message.HasExtension(DefaultSfixed32Extension));
Assert.False(message.HasExtension(DefaultSfixed64Extension));
Assert.False(message.HasExtension(DefaultSint32Extension));
Assert.False(message.HasExtension(DefaultSint64Extension));
Assert.False(message.HasExtension(DefaultStringExtension));
Assert.False(message.HasExtension(DefaultStringPieceExtension));
Assert.False(message.HasExtension(DefaultUint32Extension));
Assert.False(message.HasExtension(DefaultUint64Extension));
}
[Test]
public void FieldPresence()
{
var message = new TestAllTypes();
Assert.False(message.HasOptionalBool);
Assert.False(message.OptionalBool);
message.OptionalBool = true;
Assert.True(message.HasOptionalBool);
Assert.True(message.OptionalBool);
message.OptionalBool = false;
Assert.True(message.HasOptionalBool);
Assert.False(message.OptionalBool);
message.ClearOptionalBool();
Assert.False(message.HasOptionalBool);
Assert.False(message.OptionalBool);
Assert.False(message.HasDefaultBool);
Assert.True(message.DefaultBool);
message.DefaultBool = false;
Assert.True(message.HasDefaultBool);
Assert.False(message.DefaultBool);
message.DefaultBool = true;
Assert.True(message.HasDefaultBool);
Assert.True(message.DefaultBool);
message.ClearDefaultBool();
Assert.False(message.HasDefaultBool);
Assert.True(message.DefaultBool);
}
[Test]
public void RequiredFields()
{
var message = new TestRequired();
Assert.False(message.IsInitialized());
message.A = 1;
message.B = 2;
message.C = 3;
Assert.True(message.IsInitialized());
}
/// <summary>
/// Code was accidentally left in message parser that threw exceptions when missing required fields after parsing.
/// We've decided to not throw exceptions on missing fields, instead leaving it up to the consumer how they
/// want to check and handle missing fields.
/// </summary>
[Test]
public void RequiredFieldsNoThrow()
{
Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser, new byte[0], m => { }));
Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser as MessageParser, new byte[0], m => { }));
}
[Test]
public void RequiredFieldsInExtensions()
{
var message = new TestAllExtensions();
Assert.True(message.IsInitialized());
message.SetExtension(TestRequired.Extensions.Single, new TestRequired());
Assert.False(message.IsInitialized());
var extensionMessage = message.GetExtension(TestRequired.Extensions.Single);
extensionMessage.A = 1;
extensionMessage.B = 2;
extensionMessage.C = 3;
Assert.True(message.IsInitialized());
message.GetOrInitializeExtension(TestRequired.Extensions.Multi);
Assert.True(message.IsInitialized());
message.GetExtension(TestRequired.Extensions.Multi).Add(new TestRequired());
Assert.False(message.IsInitialized());
extensionMessage = message.GetExtension(TestRequired.Extensions.Multi)[0];
extensionMessage.A = 1;
extensionMessage.B = 2;
extensionMessage.C = 3;
Assert.True(message.IsInitialized());
message.SetExtension(UnittestExtensions.OptionalBoolExtension, true);
Assert.True(message.IsInitialized());
message.GetOrInitializeExtension(UnittestExtensions.RepeatedBoolExtension).Add(true);
Assert.True(message.IsInitialized());
}
[Test]
public void RequiredFieldInNestedMessageMapValue()
{
var message = new TestRequiredMap();
message.Foo.Add(0, new TestRequiredMap.Types.NestedMessage());
Assert.False(message.IsInitialized());
message.Foo[0].RequiredInt32 = 12;
Assert.True(message.IsInitialized());
}
[Test]
public void RoundTrip_Groups()
{
var message = new TestAllTypes
{
OptionalGroup = new TestAllTypes.Types.OptionalGroup
{
A = 10
},
RepeatedGroup =
{
new TestAllTypes.Types.RepeatedGroup { A = 10 },
new TestAllTypes.Types.RepeatedGroup { A = 20 },
new TestAllTypes.Types.RepeatedGroup { A = 30 }
}
};
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertRoundtrip(Proto2.TestAllTypes.Parser, message);
}
[Test]
public void RoundTrip_ExtensionGroups()
{
var message = new TestAllExtensions();
message.SetExtension(UnittestExtensions.OptionalGroupExtension, new OptionalGroup_extension { A = 10 });
message.GetOrInitializeExtension(UnittestExtensions.RepeatedGroupExtension).AddRange(new[]
{
new RepeatedGroup_extension { A = 10 },
new RepeatedGroup_extension { A = 20 },
new RepeatedGroup_extension { A = 30 }
});
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertRoundtrip(
TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }),
message);
}
[Test]
public void RoundTrip_NestedExtensionGroup()
{
var message = new TestGroupExtension();
message.SetExtension(TestNestedExtension.Extensions.OptionalGroupExtension, new TestNestedExtension.Types.OptionalGroup_extension { A = 10 });
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertRoundtrip(
TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }),
message);
}
[Test]
public void RoundTrip_ParseUsingCodedInput()
{
var message = new TestAllExtensions();
message.SetExtension(UnittestExtensions.OptionalBoolExtension, true);
byte[] bytes = message.ToByteArray();
using (CodedInputStream input = new CodedInputStream(bytes))
{
var parsed = TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalBoolExtension }).ParseFrom(input);
Assert.AreEqual(message, parsed);
}
}
}
}
using Google.Protobuf.TestProtos.Proto2;
using Proto2 = Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf
{
/// <summary>
/// Tests around the generated TestAllTypes message in unittest.proto
/// </summary>
public partial class GeneratedMessageTest
{
[Test]
public void DefaultProto2Values()
{
var message = new TestAllTypes();
Assert.AreEqual(false, message.OptionalBool);
Assert.AreEqual(ByteString.Empty, message.OptionalBytes);
Assert.AreEqual(0.0, message.OptionalDouble);
Assert.AreEqual(0, message.OptionalFixed32);
Assert.AreEqual(0L, message.OptionalFixed64);
Assert.AreEqual(0.0f, message.OptionalFloat);
Assert.AreEqual(ForeignEnum.ForeignFoo, message.OptionalForeignEnum);
Assert.IsNull(message.OptionalForeignMessage);
Assert.AreEqual(ImportEnum.ImportFoo, message.OptionalImportEnum);
Assert.IsNull(message.OptionalImportMessage);
Assert.AreEqual(0, message.OptionalInt32);
Assert.AreEqual(0L, message.OptionalInt64);
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.OptionalNestedEnum);
Assert.IsNull(message.OptionalNestedMessage);
Assert.IsNull(message.OptionalPublicImportMessage);
Assert.AreEqual(0, message.OptionalSfixed32);
Assert.AreEqual(0L, message.OptionalSfixed64);
Assert.AreEqual(0, message.OptionalSint32);
Assert.AreEqual(0L, message.OptionalSint64);
Assert.AreEqual("", message.OptionalString);
Assert.AreEqual(0U, message.OptionalUint32);
Assert.AreEqual(0UL, message.OptionalUint64);
// 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.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(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(true, message.DefaultBool);
Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.DefaultBytes);
Assert.AreEqual("123", message.DefaultCord);
Assert.AreEqual(52e3, message.DefaultDouble);
Assert.AreEqual(47, message.DefaultFixed32);
Assert.AreEqual(48, message.DefaultFixed64);
Assert.AreEqual(51.5, message.DefaultFloat);
Assert.AreEqual(ForeignEnum.ForeignBar, message.DefaultForeignEnum);
Assert.AreEqual(ImportEnum.ImportBar, message.DefaultImportEnum);
Assert.AreEqual(41, message.DefaultInt32);
Assert.AreEqual(42, message.DefaultInt64);
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.DefaultNestedEnum);
Assert.AreEqual(49, message.DefaultSfixed32);
Assert.AreEqual(-50, message.DefaultSfixed64);
Assert.AreEqual(-45, message.DefaultSint32);
Assert.AreEqual(46, message.DefaultSint64);
Assert.AreEqual("hello", message.DefaultString);
Assert.AreEqual("abc", message.DefaultStringPiece);
Assert.AreEqual(43, message.DefaultUint32);
Assert.AreEqual(44, message.DefaultUint64);
Assert.False(message.HasDefaultBool);
Assert.False(message.HasDefaultBytes);
Assert.False(message.HasDefaultCord);
Assert.False(message.HasDefaultDouble);
Assert.False(message.HasDefaultFixed32);
Assert.False(message.HasDefaultFixed64);
Assert.False(message.HasDefaultFloat);
Assert.False(message.HasDefaultForeignEnum);
Assert.False(message.HasDefaultImportEnum);
Assert.False(message.HasDefaultInt32);
Assert.False(message.HasDefaultInt64);
Assert.False(message.HasDefaultNestedEnum);
Assert.False(message.HasDefaultSfixed32);
Assert.False(message.HasDefaultSfixed64);
Assert.False(message.HasDefaultSint32);
Assert.False(message.HasDefaultSint64);
Assert.False(message.HasDefaultString);
Assert.False(message.HasDefaultStringPiece);
Assert.False(message.HasDefaultUint32);
Assert.False(message.HasDefaultUint64);
}
[Test]
public void DefaultExtensionValues()
{
var message = new TestAllExtensions();
Assert.AreEqual(false, message.GetExtension(OptionalBoolExtension));
Assert.AreEqual(ByteString.Empty, message.GetExtension(OptionalBytesExtension));
Assert.AreEqual(0.0, message.GetExtension(OptionalDoubleExtension));
Assert.AreEqual(0, message.GetExtension(OptionalFixed32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalFixed64Extension));
Assert.AreEqual(0.0f, message.GetExtension(OptionalFloatExtension));
Assert.AreEqual(ForeignEnum.ForeignFoo, message.GetExtension(OptionalForeignEnumExtension));
Assert.IsNull(message.GetExtension(OptionalForeignMessageExtension));
Assert.AreEqual(ImportEnum.ImportFoo, message.GetExtension(OptionalImportEnumExtension));
Assert.IsNull(message.GetExtension(OptionalImportMessageExtension));
Assert.AreEqual(0, message.GetExtension(OptionalInt32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalInt64Extension));
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.GetExtension(OptionalNestedEnumExtension));
Assert.IsNull(message.GetExtension(OptionalNestedMessageExtension));
Assert.IsNull(message.GetExtension(OptionalPublicImportMessageExtension));
Assert.AreEqual(0, message.GetExtension(OptionalSfixed32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalSfixed64Extension));
Assert.AreEqual(0, message.GetExtension(OptionalSint32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalSint64Extension));
Assert.AreEqual("", message.GetExtension(OptionalStringExtension));
Assert.AreEqual(0U, message.GetExtension(OptionalUint32Extension));
Assert.AreEqual(0UL, message.GetExtension(OptionalUint64Extension));
// Repeated fields
Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
Assert.IsNull(message.GetExtension(RepeatedBytesExtension));
Assert.IsNull(message.GetExtension(RepeatedDoubleExtension));
Assert.IsNull(message.GetExtension(RepeatedFixed32Extension));
Assert.IsNull(message.GetExtension(RepeatedFixed64Extension));
Assert.IsNull(message.GetExtension(RepeatedFloatExtension));
Assert.IsNull(message.GetExtension(RepeatedForeignEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedForeignMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedImportEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedImportMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedNestedEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedNestedMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedSfixed32Extension));
Assert.IsNull(message.GetExtension(RepeatedSfixed64Extension));
Assert.IsNull(message.GetExtension(RepeatedSint32Extension));
Assert.IsNull(message.GetExtension(RepeatedSint64Extension));
Assert.IsNull(message.GetExtension(RepeatedStringExtension));
Assert.IsNull(message.GetExtension(RepeatedUint32Extension));
Assert.IsNull(message.GetExtension(RepeatedUint64Extension));
// Oneof fields
Assert.AreEqual(0, message.GetExtension(OneofUint32Extension));
Assert.AreEqual("", message.GetExtension(OneofStringExtension));
Assert.AreEqual(ByteString.Empty, message.GetExtension(OneofBytesExtension));
Assert.IsNull(message.GetExtension(OneofNestedMessageExtension));
Assert.AreEqual(true, message.GetExtension(DefaultBoolExtension));
Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.GetExtension(DefaultBytesExtension));
Assert.AreEqual("123", message.GetExtension(DefaultCordExtension));
Assert.AreEqual(52e3, message.GetExtension(DefaultDoubleExtension));
Assert.AreEqual(47, message.GetExtension(DefaultFixed32Extension));
Assert.AreEqual(48, message.GetExtension(DefaultFixed64Extension));
Assert.AreEqual(51.5, message.GetExtension(DefaultFloatExtension));
Assert.AreEqual(ForeignEnum.ForeignBar, message.GetExtension(DefaultForeignEnumExtension));
Assert.AreEqual(ImportEnum.ImportBar, message.GetExtension(DefaultImportEnumExtension));
Assert.AreEqual(41, message.GetExtension(DefaultInt32Extension));
Assert.AreEqual(42, message.GetExtension(DefaultInt64Extension));
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.GetExtension(DefaultNestedEnumExtension));
Assert.AreEqual(49, message.GetExtension(DefaultSfixed32Extension));
Assert.AreEqual(-50, message.GetExtension(DefaultSfixed64Extension));
Assert.AreEqual(-45, message.GetExtension(DefaultSint32Extension));
Assert.AreEqual(46, message.GetExtension(DefaultSint64Extension));
Assert.AreEqual("hello", message.GetExtension(DefaultStringExtension));
Assert.AreEqual("abc", message.GetExtension(DefaultStringPieceExtension));
Assert.AreEqual(43, message.GetExtension(DefaultUint32Extension));
Assert.AreEqual(44, message.GetExtension(DefaultUint64Extension));
Assert.False(message.HasExtension(DefaultBoolExtension));
Assert.False(message.HasExtension(DefaultBytesExtension));
Assert.False(message.HasExtension(DefaultCordExtension));
Assert.False(message.HasExtension(DefaultDoubleExtension));
Assert.False(message.HasExtension(DefaultFixed32Extension));
Assert.False(message.HasExtension(DefaultFixed64Extension));
Assert.False(message.HasExtension(DefaultFloatExtension));
Assert.False(message.HasExtension(DefaultForeignEnumExtension));
Assert.False(message.HasExtension(DefaultImportEnumExtension));
Assert.False(message.HasExtension(DefaultInt32Extension));
Assert.False(message.HasExtension(DefaultInt64Extension));
Assert.False(message.HasExtension(DefaultNestedEnumExtension));
Assert.False(message.HasExtension(DefaultSfixed32Extension));
Assert.False(message.HasExtension(DefaultSfixed64Extension));
Assert.False(message.HasExtension(DefaultSint32Extension));
Assert.False(message.HasExtension(DefaultSint64Extension));
Assert.False(message.HasExtension(DefaultStringExtension));
Assert.False(message.HasExtension(DefaultStringPieceExtension));
Assert.False(message.HasExtension(DefaultUint32Extension));
Assert.False(message.HasExtension(DefaultUint64Extension));
}
[Test]
public void FieldPresence()
{
var message = new TestAllTypes();
Assert.False(message.HasOptionalBool);
Assert.False(message.OptionalBool);
message.OptionalBool = true;
Assert.True(message.HasOptionalBool);
Assert.True(message.OptionalBool);
message.OptionalBool = false;
Assert.True(message.HasOptionalBool);
Assert.False(message.OptionalBool);
message.ClearOptionalBool();
Assert.False(message.HasOptionalBool);
Assert.False(message.OptionalBool);
Assert.False(message.HasDefaultBool);
Assert.True(message.DefaultBool);
message.DefaultBool = false;
Assert.True(message.HasDefaultBool);
Assert.False(message.DefaultBool);
message.DefaultBool = true;
Assert.True(message.HasDefaultBool);
Assert.True(message.DefaultBool);
message.ClearDefaultBool();
Assert.False(message.HasDefaultBool);
Assert.True(message.DefaultBool);
}
[Test]
public void RequiredFields()
{
var message = new TestRequired();
Assert.False(message.IsInitialized());
message.A = 1;
message.B = 2;
message.C = 3;
Assert.True(message.IsInitialized());
}
/// <summary>
/// Code was accidentally left in message parser that threw exceptions when missing required fields after parsing.
/// We've decided to not throw exceptions on missing fields, instead leaving it up to the consumer how they
/// want to check and handle missing fields.
/// </summary>
[Test]
public void RequiredFieldsNoThrow()
{
Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser, new byte[0], m => { }));
Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser as MessageParser, new byte[0], m => { }));
}
[Test]
public void RequiredFieldsInExtensions()
{
var message = new TestAllExtensions();
Assert.True(message.IsInitialized());
message.SetExtension(TestRequired.Extensions.Single, new TestRequired());
Assert.False(message.IsInitialized());
var extensionMessage = message.GetExtension(TestRequired.Extensions.Single);
extensionMessage.A = 1;
extensionMessage.B = 2;
extensionMessage.C = 3;
Assert.True(message.IsInitialized());
message.GetOrInitializeExtension(TestRequired.Extensions.Multi);
Assert.True(message.IsInitialized());
message.GetExtension(TestRequired.Extensions.Multi).Add(new TestRequired());
Assert.False(message.IsInitialized());
extensionMessage = message.GetExtension(TestRequired.Extensions.Multi)[0];
extensionMessage.A = 1;
extensionMessage.B = 2;
extensionMessage.C = 3;
Assert.True(message.IsInitialized());
message.SetExtension(UnittestExtensions.OptionalBoolExtension, true);
Assert.True(message.IsInitialized());
message.GetOrInitializeExtension(UnittestExtensions.RepeatedBoolExtension).Add(true);
Assert.True(message.IsInitialized());
}
[Test]
public void RequiredFieldInNestedMessageMapValue()
{
var message = new TestRequiredMap();
message.Foo.Add(0, new TestRequiredMap.Types.NestedMessage());
Assert.False(message.IsInitialized());
message.Foo[0].RequiredInt32 = 12;
Assert.True(message.IsInitialized());
}
[Test]
public void RoundTrip_Groups()
{
var message = new TestAllTypes
{
OptionalGroup = new TestAllTypes.Types.OptionalGroup
{
A = 10
},
RepeatedGroup =
{
new TestAllTypes.Types.RepeatedGroup { A = 10 },
new TestAllTypes.Types.RepeatedGroup { A = 20 },
new TestAllTypes.Types.RepeatedGroup { A = 30 }
}
};
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertRoundtrip(Proto2.TestAllTypes.Parser, message);
}
[Test]
public void RoundTrip_ExtensionGroups()
{
var message = new TestAllExtensions();
message.SetExtension(UnittestExtensions.OptionalGroupExtension, new OptionalGroup_extension { A = 10 });
message.GetOrInitializeExtension(UnittestExtensions.RepeatedGroupExtension).AddRange(new[]
{
new RepeatedGroup_extension { A = 10 },
new RepeatedGroup_extension { A = 20 },
new RepeatedGroup_extension { A = 30 }
});
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertRoundtrip(
TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }),
message);
}
[Test]
public void RoundTrip_NestedExtensionGroup()
{
var message = new TestGroupExtension();
message.SetExtension(TestNestedExtension.Extensions.OptionalGroupExtension, new TestNestedExtension.Types.OptionalGroup_extension { A = 10 });
MessageParsingHelpers.AssertWritingMessage(message);
MessageParsingHelpers.AssertRoundtrip(
TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }),
message);
}
[Test]
public void RoundTrip_ParseUsingCodedInput()
{
var message = new TestAllExtensions();
message.SetExtension(UnittestExtensions.OptionalBoolExtension, true);
byte[] bytes = message.ToByteArray();
using (CodedInputStream input = new CodedInputStream(bytes))
{
var parsed = TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalBoolExtension }).ParseFrom(input);
Assert.AreEqual(message, parsed);
}
}
}
}

File diff suppressed because it is too large Load Diff

@ -14,14 +14,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="NUnit" Version="3.9.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.9.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
</ItemGroup>
<!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>

@ -1,116 +1,132 @@
#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 Google.Protobuf.Reflection;
using UnitTest.Issues.TestProtos;
using NUnit.Framework;
using System.IO;
using static UnitTest.Issues.TestProtos.OneofMerging.Types;
namespace Google.Protobuf
{
/// <summary>
/// Tests for issues which aren't easily compartmentalized into other unit tests.
/// </summary>
public class IssuesTest
{
// Issue 45
[Test]
public void FieldCalledItem()
{
ItemField message = new ItemField { Item = 3 };
FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
Assert.NotNull(field);
Assert.AreEqual(3, (int)field.Accessor.GetValue(message));
}
[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());
}
[Test]
public void JsonNameParseTest()
{
var settings = new JsonParser.Settings(10, TypeRegistry.FromFiles(UnittestIssuesReflection.Descriptor));
var parser = new JsonParser(settings);
// It is safe to use either original field name or explicitly specified json_name
Assert.AreEqual(new TestJsonName { Name = "test", Description = "test2", Guid = "test3" },
parser.Parse<TestJsonName>("{ \"name\": \"test\", \"desc\": \"test2\", \"guid\": \"test3\" }"));
}
[Test]
public void JsonNameFormatTest()
{
var message = new TestJsonName { Name = "test", Description = "test2", Guid = "test3" };
Assert.AreEqual("{ \"name\": \"test\", \"desc\": \"test2\", \"exid\": \"test3\" }",
JsonFormatter.Default.Format(message));
}
[Test]
public void OneofMerging()
{
var message1 = new OneofMerging { Nested = new Nested { X = 10 } };
var message2 = new OneofMerging { Nested = new Nested { Y = 20 } };
var expected = new OneofMerging { Nested = new Nested { X = 10, Y = 20 } };
var merged = message1.Clone();
merged.MergeFrom(message2);
Assert.AreEqual(expected, merged);
}
// Check that a tag immediately followed by end of limit can still be read.
[Test]
public void CodedInputStream_LimitReachedRightAfterTag()
{
MemoryStream ms = new MemoryStream();
var cos = new CodedOutputStream(ms);
cos.WriteTag(11, WireFormat.WireType.Varint);
Assert.AreEqual(1, cos.Position);
cos.WriteString("some extra padding"); // ensure is currentLimit distinct from the end of the buffer.
cos.Flush();
var cis = new CodedInputStream(ms.ToArray());
cis.PushLimit(1); // make sure we reach the limit right after reading the tag.
// we still must read the tag correctly, even though the tag is at the very end of our limited input
// (which is a corner case and will most likely result in an error when trying to read value of the field
// described by this tag, but it would be a logical error not to read the tag that's actually present).
// See https://github.com/protocolbuffers/protobuf/pull/7289
cis.AssertNextTag(WireFormat.MakeTag(11, WireFormat.WireType.Varint));
}
}
}
#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 Google.Protobuf.Reflection;
using UnitTest.Issues.TestProtos;
using NUnit.Framework;
using System.IO;
using static UnitTest.Issues.TestProtos.OneofMerging.Types;
namespace Google.Protobuf
{
/// <summary>
/// Tests for issues which aren't easily compartmentalized into other unit tests.
/// </summary>
public class IssuesTest
{
// Issue 45
[Test]
public void FieldCalledItem()
{
ItemField message = new ItemField { Item = 3 };
FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
Assert.NotNull(field);
Assert.AreEqual(3, (int)field.Accessor.GetValue(message));
}
[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());
}
[Test]
public void JsonNameParseTest()
{
var settings = new JsonParser.Settings(10, TypeRegistry.FromFiles(UnittestIssuesReflection.Descriptor));
var parser = new JsonParser(settings);
// It is safe to use either original field name or explicitly specified json_name
Assert.AreEqual(new TestJsonName { Name = "test", Description = "test2", Guid = "test3" },
parser.Parse<TestJsonName>("{ \"name\": \"test\", \"desc\": \"test2\", \"guid\": \"test3\" }"));
}
[Test]
public void JsonNameFormatTest()
{
var message = new TestJsonName { Name = "test", Description = "test2", Guid = "test3" };
Assert.AreEqual("{ \"name\": \"test\", \"desc\": \"test2\", \"exid\": \"test3\" }",
JsonFormatter.Default.Format(message));
}
[Test]
public void OneofMerging()
{
var message1 = new OneofMerging { Nested = new Nested { X = 10 } };
var message2 = new OneofMerging { Nested = new Nested { Y = 20 } };
var expected = new OneofMerging { Nested = new Nested { X = 10, Y = 20 } };
var merged = message1.Clone();
merged.MergeFrom(message2);
Assert.AreEqual(expected, merged);
}
// Check that a tag immediately followed by end of limit can still be read.
[Test]
public void CodedInputStream_LimitReachedRightAfterTag()
{
MemoryStream ms = new MemoryStream();
var cos = new CodedOutputStream(ms);
cos.WriteTag(11, WireFormat.WireType.Varint);
Assert.AreEqual(1, cos.Position);
cos.WriteString("some extra padding"); // ensure is currentLimit distinct from the end of the buffer.
cos.Flush();
var cis = new CodedInputStream(ms.ToArray());
cis.PushLimit(1); // make sure we reach the limit right after reading the tag.
// we still must read the tag correctly, even though the tag is at the very end of our limited input
// (which is a corner case and will most likely result in an error when trying to read value of the field
// described by this tag, but it would be a logical error not to read the tag that's actually present).
// See https://github.com/protocolbuffers/protobuf/pull/7289
cis.AssertNextTag(WireFormat.MakeTag(11, WireFormat.WireType.Varint));
}
[Test]
public void NoneFieldInOneof()
{
var message = new OneofWithNoneField();
var emptyHashCode = message.GetHashCode();
Assert.AreEqual(OneofWithNoneField.TestOneofCase.None, message.TestCase);
message.None = "test";
Assert.AreEqual(OneofWithNoneField.TestOneofCase.None_, message.TestCase);
Assert.AreNotEqual(emptyHashCode, message.GetHashCode());
var bytes = message.ToByteArray();
var parsed = OneofWithNoneField.Parser.ParseFrom(bytes);
Assert.AreEqual(message, parsed);
Assert.AreEqual("test", parsed.None);
}
}
}

File diff suppressed because it is too large Load Diff

@ -1,62 +1,62 @@
#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 UnitTest.Issues.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
public class TestCornerCases
{
[Test]
public void TestRoundTripNegativeEnums()
{
NegativeEnumMessage msg = new NegativeEnumMessage
{
Value = NegativeEnum.MinusOne,
Values = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
PackedValues = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
};
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);
}
}
}
#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 UnitTest.Issues.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf
{
public class TestCornerCases
{
[Test]
public void TestRoundTripNegativeEnums()
{
NegativeEnumMessage msg = new NegativeEnumMessage
{
Value = NegativeEnum.MinusOne,
Values = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
PackedValues = { NegativeEnum.Zero, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
};
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);
}
}
}

@ -1,4 +1,4 @@
#region Copyright notice and license
#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/
@ -142,16 +142,16 @@ namespace Google.Protobuf.WellKnownTypes
}
[Test]
public void IsWrongType()
{
var any = Any.Pack(SampleMessages.CreateFullTestAllTypes());
Assert.False(any.Is(TestOneof.Descriptor));
public void IsWrongType()
{
var any = Any.Pack(SampleMessages.CreateFullTestAllTypes());
Assert.False(any.Is(TestOneof.Descriptor));
}
public void IsRightType()
{
var any = Any.Pack(SampleMessages.CreateFullTestAllTypes());
Assert.True(any.Is(TestAllTypes.Descriptor));
public void IsRightType()
{
var any = Any.Pack(SampleMessages.CreateFullTestAllTypes());
Assert.True(any.Is(TestAllTypes.Descriptor));
}
}
}

@ -1,79 +1,79 @@
#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
{
/// <summary>
/// Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy
/// </summary>
internal static class ByteArray
{
/// <summary>
/// The threshold above which you should use Buffer.BlockCopy rather than ByteArray.Copy
/// </summary>
private const int CopyThreshold = 12;
/// <summary>
/// Determines which copy routine to use based on the number of bytes to be copied.
/// </summary>
internal static void Copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
{
if (count > CopyThreshold)
{
Buffer.BlockCopy(src, srcOffset, dst, dstOffset, count);
}
else
{
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>
internal static void Reverse(byte[] bytes)
{
for (int first = 0, last = bytes.Length - 1; first < last; first++, last--)
{
byte temp = bytes[first];
bytes[first] = bytes[last];
bytes[last] = temp;
}
}
}
#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
{
/// <summary>
/// Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy
/// </summary>
internal static class ByteArray
{
/// <summary>
/// The threshold above which you should use Buffer.BlockCopy rather than ByteArray.Copy
/// </summary>
private const int CopyThreshold = 12;
/// <summary>
/// Determines which copy routine to use based on the number of bytes to be copied.
/// </summary>
internal static void Copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
{
if (count > CopyThreshold)
{
Buffer.BlockCopy(src, srcOffset, dst, dstOffset, count);
}
else
{
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>
internal static void Reverse(byte[] bytes)
{
for (int first = 0, last = bytes.Length - 1; first < last; first++, last--)
{
byte temp = bytes[first];
bytes[first] = bytes[last];
bytes[last] = temp;
}
}
}
}

@ -1,434 +1,434 @@
#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.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
#if !NET35
using System.Threading;
using System.Threading.Tasks;
#endif
#if NET35
using Google.Protobuf.Compatibility;
#endif
namespace Google.Protobuf
{
/// <summary>
/// Immutable array of bytes.
/// </summary>
[SecuritySafeCritical]
public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
{
private static readonly ByteString empty = new ByteString(new byte[0]);
private readonly ReadOnlyMemory<byte> bytes;
/// <summary>
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
/// </summary>
internal static ByteString AttachBytes(ReadOnlyMemory<byte> bytes)
{
return new ByteString(bytes);
}
/// <summary>
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
/// This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical
/// in .NET Framework.
/// </summary>
internal static ByteString AttachBytes(byte[] bytes)
{
return AttachBytes(bytes.AsMemory());
}
/// <summary>
/// Constructs a new ByteString from the given memory. The memory is
/// *not* copied, and must not be modified after this constructor is called.
/// </summary>
private ByteString(ReadOnlyMemory<byte> bytes)
{
this.bytes = bytes;
}
/// <summary>
/// Returns an empty ByteString.
/// </summary>
public static ByteString Empty
{
get { return empty; }
}
/// <summary>
/// Returns the length of this ByteString in bytes.
/// </summary>
public int Length
{
get { return bytes.Length; }
}
/// <summary>
/// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
/// </summary>
public bool IsEmpty
{
get { return Length == 0; }
}
/// <summary>
/// Provides read-only access to the data of this <see cref="ByteString"/>.
/// No data is copied so this is the most efficient way of accessing.
/// </summary>
public ReadOnlySpan<byte> Span
{
get { return bytes.Span; }
}
/// <summary>
/// Provides read-only access to the data of this <see cref="ByteString"/>.
/// No data is copied so this is the most efficient way of accessing.
/// </summary>
public ReadOnlyMemory<byte> Memory
{
get { return bytes; }
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a byte array.
/// </summary>
/// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
/// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
public byte[] ToByteArray()
{
return bytes.ToArray();
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a standard base64 representation.
/// </summary>
/// <returns>A base64 representation of this <c>ByteString</c>.</returns>
public string ToBase64()
{
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array, so pass the underlying array.
return Convert.ToBase64String(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String.
return Convert.ToBase64String(bytes.ToArray());
}
}
/// <summary>
/// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
/// </summary>
public static ByteString FromBase64(string bytes)
{
// By handling the empty string explicitly, we not only optimize but we fix a
// problem on CF 2.0. See issue 61 for details.
return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes));
}
/// <summary>
/// Constructs a <see cref="ByteString"/> from data in the given stream, synchronously.
/// </summary>
/// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
/// at the start of the call.</remarks>
/// <param name="stream">The stream to copy into a ByteString.</param>
/// <returns>A ByteString with content read from the given stream.</returns>
public static ByteString FromStream(Stream stream)
{
ProtoPreconditions.CheckNotNull(stream, nameof(stream));
int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
var memoryStream = new MemoryStream(capacity);
stream.CopyTo(memoryStream);
#if NETSTANDARD1_1 || NETSTANDARD2_0
byte[] bytes = memoryStream.ToArray();
#else
// Avoid an extra copy if we can.
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
#endif
return AttachBytes(bytes);
}
#if !NET35
/// <summary>
/// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously.
/// </summary>
/// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
/// at the start of the call.</remarks>
/// <param name="stream">The stream to copy into a ByteString.</param>
/// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
/// <returns>A ByteString with content read from the given stream.</returns>
public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
ProtoPreconditions.CheckNotNull(stream, nameof(stream));
return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken);
}
#endif
/// <summary>
/// Constructs a <see cref="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(params byte[] bytes)
{
return new ByteString((byte[]) bytes.Clone());
}
/// <summary>
/// Constructs a <see cref="ByteString" /> from a portion of a byte array.
/// </summary>
public static ByteString CopyFrom(byte[] bytes, int offset, int count)
{
byte[] portion = new byte[count];
ByteArray.Copy(bytes, offset, portion, 0, count);
return new ByteString(portion);
}
/// <summary>
/// Constructs a <see cref="ByteString" /> from a read only span. The contents
/// are copied, so further modifications to the span will not
/// be reflected in the returned <see cref="ByteString" />.
/// </summary>
public static ByteString CopyFrom(ReadOnlySpan<byte> bytes)
{
return new ByteString(bytes.ToArray());
}
/// <summary>
/// Creates a new <see cref="ByteString" /> by encoding the specified text with
/// the given encoding.
/// </summary>
public static ByteString CopyFrom(string text, Encoding encoding)
{
return new ByteString(encoding.GetBytes(text));
}
/// <summary>
/// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
/// </summary>
public static ByteString CopyFromUtf8(string text)
{
return CopyFrom(text, Encoding.UTF8);
}
/// <summary>
/// Returns the byte at the given index.
/// </summary>
public byte this[int index]
{
get { return bytes.Span[index]; }
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
/// </summary>
/// <remarks>
/// This method should only be used to convert binary data which was the result of encoding
/// text with the given encoding.
/// </remarks>
/// <param name="encoding">The encoding to use to decode the binary data into text.</param>
/// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToString(Encoding encoding)
{
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array.
return encoding.GetString(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to GetString.
// TODO: Consider using GetString overload that takes a pointer.
byte[] array = bytes.ToArray();
return encoding.GetString(array, 0, array.Length);
}
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
/// </summary>
/// <remarks>
/// This method should only be used to convert binary data which was the result of encoding
/// text with UTF-8.
/// </remarks>
/// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToStringUtf8()
{
return ToString(Encoding.UTF8);
}
/// <summary>
/// Returns an iterator over the bytes in this <see cref="ByteString"/>.
/// </summary>
/// <returns>An iterator over the bytes in this object.</returns>
[SecuritySafeCritical]
public IEnumerator<byte> GetEnumerator()
{
return MemoryMarshal.ToEnumerable(bytes).GetEnumerator();
}
/// <summary>
/// Returns an iterator over the bytes in this <see cref="ByteString"/>.
/// </summary>
/// <returns>An iterator over the bytes in this object.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Creates a CodedInputStream from this ByteString's data.
/// </summary>
public CodedInputStream CreateCodedInput()
{
// We trust CodedInputStream not to reveal the provided byte array or modify it
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment) && segment.Count == bytes.Length)
{
// Fast path. ByteString was created with a complete array.
return new CodedInputStream(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array, or is a slice of an array.
// Convert memory and pass result to WriteRawBytes.
return new CodedInputStream(bytes.ToArray());
}
}
/// <summary>
/// Compares two byte strings for equality.
/// </summary>
/// <param name="lhs">The first byte string to compare.</param>
/// <param name="rhs">The second byte string to compare.</param>
/// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
public static bool operator ==(ByteString lhs, ByteString rhs)
{
if (ReferenceEquals(lhs, rhs))
{
return true;
}
if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
{
return false;
}
return lhs.bytes.Span.SequenceEqual(rhs.bytes.Span);
}
/// <summary>
/// Compares two byte strings for inequality.
/// </summary>
/// <param name="lhs">The first byte string to compare.</param>
/// <param name="rhs">The second byte string to compare.</param>
/// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
public static bool operator !=(ByteString lhs, ByteString rhs)
{
return !(lhs == rhs);
}
/// <summary>
/// Compares this byte string with another object.
/// </summary>
/// <param name="obj">The object to compare this with.</param>
/// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
[SecuritySafeCritical]
public override bool Equals(object obj)
{
return this == (obj as ByteString);
}
/// <summary>
/// Returns a hash code for this object. Two equal byte strings
/// will return the same hash code.
/// </summary>
/// <returns>A hash code for this object.</returns>
[SecuritySafeCritical]
public override int GetHashCode()
{
ReadOnlySpan<byte> b = bytes.Span;
int ret = 23;
for (int i = 0; i < b.Length; i++)
{
ret = (ret * 31) + b[i];
}
return ret;
}
/// <summary>
/// Compares this byte string with another.
/// </summary>
/// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
/// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
public bool Equals(ByteString other)
{
return this == other;
}
/// <summary>
/// Copies the entire byte array to the destination array provided at the offset specified.
/// </summary>
public void CopyTo(byte[] array, int position)
{
bytes.CopyTo(array.AsMemory(position));
}
/// <summary>
/// Writes the entire byte array to the provided stream
/// </summary>
public void WriteTo(Stream outputStream)
{
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array, so pass the underlying array.
outputStream.Write(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to WriteRawBytes.
var array = bytes.ToArray();
outputStream.Write(array, 0, array.Length);
}
}
}
#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.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
#if !NET35
using System.Threading;
using System.Threading.Tasks;
#endif
#if NET35
using Google.Protobuf.Compatibility;
#endif
namespace Google.Protobuf
{
/// <summary>
/// Immutable array of bytes.
/// </summary>
[SecuritySafeCritical]
public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
{
private static readonly ByteString empty = new ByteString(new byte[0]);
private readonly ReadOnlyMemory<byte> bytes;
/// <summary>
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
/// </summary>
internal static ByteString AttachBytes(ReadOnlyMemory<byte> bytes)
{
return new ByteString(bytes);
}
/// <summary>
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
/// This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical
/// in .NET Framework.
/// </summary>
internal static ByteString AttachBytes(byte[] bytes)
{
return AttachBytes(bytes.AsMemory());
}
/// <summary>
/// Constructs a new ByteString from the given memory. The memory is
/// *not* copied, and must not be modified after this constructor is called.
/// </summary>
private ByteString(ReadOnlyMemory<byte> bytes)
{
this.bytes = bytes;
}
/// <summary>
/// Returns an empty ByteString.
/// </summary>
public static ByteString Empty
{
get { return empty; }
}
/// <summary>
/// Returns the length of this ByteString in bytes.
/// </summary>
public int Length
{
get { return bytes.Length; }
}
/// <summary>
/// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
/// </summary>
public bool IsEmpty
{
get { return Length == 0; }
}
/// <summary>
/// Provides read-only access to the data of this <see cref="ByteString"/>.
/// No data is copied so this is the most efficient way of accessing.
/// </summary>
public ReadOnlySpan<byte> Span
{
get { return bytes.Span; }
}
/// <summary>
/// Provides read-only access to the data of this <see cref="ByteString"/>.
/// No data is copied so this is the most efficient way of accessing.
/// </summary>
public ReadOnlyMemory<byte> Memory
{
get { return bytes; }
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a byte array.
/// </summary>
/// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
/// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
public byte[] ToByteArray()
{
return bytes.ToArray();
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a standard base64 representation.
/// </summary>
/// <returns>A base64 representation of this <c>ByteString</c>.</returns>
public string ToBase64()
{
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array, so pass the underlying array.
return Convert.ToBase64String(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String.
return Convert.ToBase64String(bytes.ToArray());
}
}
/// <summary>
/// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
/// </summary>
public static ByteString FromBase64(string bytes)
{
// By handling the empty string explicitly, we not only optimize but we fix a
// problem on CF 2.0. See issue 61 for details.
return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes));
}
/// <summary>
/// Constructs a <see cref="ByteString"/> from data in the given stream, synchronously.
/// </summary>
/// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
/// at the start of the call.</remarks>
/// <param name="stream">The stream to copy into a ByteString.</param>
/// <returns>A ByteString with content read from the given stream.</returns>
public static ByteString FromStream(Stream stream)
{
ProtoPreconditions.CheckNotNull(stream, nameof(stream));
int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
var memoryStream = new MemoryStream(capacity);
stream.CopyTo(memoryStream);
#if NETSTANDARD1_1 || NETSTANDARD2_0
byte[] bytes = memoryStream.ToArray();
#else
// Avoid an extra copy if we can.
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
#endif
return AttachBytes(bytes);
}
#if !NET35
/// <summary>
/// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously.
/// </summary>
/// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
/// at the start of the call.</remarks>
/// <param name="stream">The stream to copy into a ByteString.</param>
/// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
/// <returns>A ByteString with content read from the given stream.</returns>
public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
ProtoPreconditions.CheckNotNull(stream, nameof(stream));
return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken);
}
#endif
/// <summary>
/// Constructs a <see cref="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(params byte[] bytes)
{
return new ByteString((byte[]) bytes.Clone());
}
/// <summary>
/// Constructs a <see cref="ByteString" /> from a portion of a byte array.
/// </summary>
public static ByteString CopyFrom(byte[] bytes, int offset, int count)
{
byte[] portion = new byte[count];
ByteArray.Copy(bytes, offset, portion, 0, count);
return new ByteString(portion);
}
/// <summary>
/// Constructs a <see cref="ByteString" /> from a read only span. The contents
/// are copied, so further modifications to the span will not
/// be reflected in the returned <see cref="ByteString" />.
/// </summary>
public static ByteString CopyFrom(ReadOnlySpan<byte> bytes)
{
return new ByteString(bytes.ToArray());
}
/// <summary>
/// Creates a new <see cref="ByteString" /> by encoding the specified text with
/// the given encoding.
/// </summary>
public static ByteString CopyFrom(string text, Encoding encoding)
{
return new ByteString(encoding.GetBytes(text));
}
/// <summary>
/// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
/// </summary>
public static ByteString CopyFromUtf8(string text)
{
return CopyFrom(text, Encoding.UTF8);
}
/// <summary>
/// Returns the byte at the given index.
/// </summary>
public byte this[int index]
{
get { return bytes.Span[index]; }
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
/// </summary>
/// <remarks>
/// This method should only be used to convert binary data which was the result of encoding
/// text with the given encoding.
/// </remarks>
/// <param name="encoding">The encoding to use to decode the binary data into text.</param>
/// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToString(Encoding encoding)
{
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array.
return encoding.GetString(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to GetString.
// TODO: Consider using GetString overload that takes a pointer.
byte[] array = bytes.ToArray();
return encoding.GetString(array, 0, array.Length);
}
}
/// <summary>
/// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
/// </summary>
/// <remarks>
/// This method should only be used to convert binary data which was the result of encoding
/// text with UTF-8.
/// </remarks>
/// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToStringUtf8()
{
return ToString(Encoding.UTF8);
}
/// <summary>
/// Returns an iterator over the bytes in this <see cref="ByteString"/>.
/// </summary>
/// <returns>An iterator over the bytes in this object.</returns>
[SecuritySafeCritical]
public IEnumerator<byte> GetEnumerator()
{
return MemoryMarshal.ToEnumerable(bytes).GetEnumerator();
}
/// <summary>
/// Returns an iterator over the bytes in this <see cref="ByteString"/>.
/// </summary>
/// <returns>An iterator over the bytes in this object.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Creates a CodedInputStream from this ByteString's data.
/// </summary>
public CodedInputStream CreateCodedInput()
{
// We trust CodedInputStream not to reveal the provided byte array or modify it
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment) && segment.Count == bytes.Length)
{
// Fast path. ByteString was created with a complete array.
return new CodedInputStream(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array, or is a slice of an array.
// Convert memory and pass result to WriteRawBytes.
return new CodedInputStream(bytes.ToArray());
}
}
/// <summary>
/// Compares two byte strings for equality.
/// </summary>
/// <param name="lhs">The first byte string to compare.</param>
/// <param name="rhs">The second byte string to compare.</param>
/// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
public static bool operator ==(ByteString lhs, ByteString rhs)
{
if (ReferenceEquals(lhs, rhs))
{
return true;
}
if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
{
return false;
}
return lhs.bytes.Span.SequenceEqual(rhs.bytes.Span);
}
/// <summary>
/// Compares two byte strings for inequality.
/// </summary>
/// <param name="lhs">The first byte string to compare.</param>
/// <param name="rhs">The second byte string to compare.</param>
/// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
public static bool operator !=(ByteString lhs, ByteString rhs)
{
return !(lhs == rhs);
}
/// <summary>
/// Compares this byte string with another object.
/// </summary>
/// <param name="obj">The object to compare this with.</param>
/// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
[SecuritySafeCritical]
public override bool Equals(object obj)
{
return this == (obj as ByteString);
}
/// <summary>
/// Returns a hash code for this object. Two equal byte strings
/// will return the same hash code.
/// </summary>
/// <returns>A hash code for this object.</returns>
[SecuritySafeCritical]
public override int GetHashCode()
{
ReadOnlySpan<byte> b = bytes.Span;
int ret = 23;
for (int i = 0; i < b.Length; i++)
{
ret = (ret * 31) + b[i];
}
return ret;
}
/// <summary>
/// Compares this byte string with another.
/// </summary>
/// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
/// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
public bool Equals(ByteString other)
{
return this == other;
}
/// <summary>
/// Copies the entire byte array to the destination array provided at the offset specified.
/// </summary>
public void CopyTo(byte[] array, int position)
{
bytes.CopyTo(array.AsMemory(position));
}
/// <summary>
/// Writes the entire byte array to the provided stream
/// </summary>
public void WriteTo(Stream outputStream)
{
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
{
// Fast path. ByteString was created with an array, so pass the underlying array.
outputStream.Write(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to WriteRawBytes.
var array = bytes.ToArray();
outputStream.Write(array, 0, array.Length);
}
}
}
}

File diff suppressed because it is too large Load Diff

@ -1,308 +1,308 @@
#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;
internal const int DoubleSize = LittleEndian64Size;
internal const int FloatSize = LittleEndian32Size;
internal const int BoolSize = 1;
/// <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 DoubleSize;
}
/// <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 FloatSize;
}
/// <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 BoolSize;
}
/// <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 = WritingPrimitives.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(WritingPrimitives.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(WritingPrimitives.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));
}
}
#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;
internal const int DoubleSize = LittleEndian64Size;
internal const int FloatSize = LittleEndian32Size;
internal const int BoolSize = 1;
/// <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 DoubleSize;
}
/// <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 FloatSize;
}
/// <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 BoolSize;
}
/// <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 = WritingPrimitives.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(WritingPrimitives.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(WritingPrimitives.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));
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

@ -1,428 +1,428 @@
#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 Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security;
namespace Google.Protobuf
{
/// <summary>
/// Methods for managing <see cref="ExtensionSet{TTarget}"/>s with null checking.
///
/// Most users will not use this class directly and its API is experimental and subject to change.
/// </summary>
public static class ExtensionSet
{
private static bool TryGetValue<TTarget>(ref ExtensionSet<TTarget> set, Extension extension, out IExtensionValue value) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
value = null;
return false;
}
return set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value);
}
/// <summary>
/// Gets the value of the specified extension
/// </summary>
public static TValue Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
if (TryGetValue(ref set, extension, out value))
{
// The stored ExtensionValue can be a different type to what is being requested.
// This happens when the same extension proto is compiled in different assemblies.
// To allow consuming assemblies to still get the value when the TValue type is
// different, this get method:
// 1. Attempts to cast the value to the expected ExtensionValue<TValue>.
// This is the usual case. It is used first because it avoids possibly boxing the value.
// 2. Fallback to get the value as object from IExtensionValue then casting.
// This allows for someone to specify a TValue of object. They can then convert
// the values to bytes and reparse using expected value.
// 3. If neither of these work, throw a user friendly error that the types aren't compatible.
if (value is ExtensionValue<TValue> extensionValue)
{
return extensionValue.GetValue();
}
else if (value.GetValue() is TValue underlyingValue)
{
return underlyingValue;
}
else
{
var valueType = value.GetType().GetTypeInfo();
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(ExtensionValue<>))
{
var storedType = valueType.GenericTypeArguments[0];
throw new InvalidOperationException(
"The stored extension value has a type of '" + storedType.AssemblyQualifiedName + "'. " +
"This a different from the requested type of '" + typeof(TValue).AssemblyQualifiedName + "'.");
}
else
{
throw new InvalidOperationException("Unexpected extension value type: " + valueType.AssemblyQualifiedName);
}
}
}
else
{
return extension.DefaultValue;
}
}
/// <summary>
/// Gets the value of the specified repeated extension or null if it doesn't exist in this set
/// </summary>
public static RepeatedField<TValue> Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
if (TryGetValue(ref set, extension, out value))
{
if (value is RepeatedExtensionValue<TValue> extensionValue)
{
return extensionValue.GetValue();
}
else
{
var valueType = value.GetType().GetTypeInfo();
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(RepeatedExtensionValue<>))
{
var storedType = valueType.GenericTypeArguments[0];
throw new InvalidOperationException(
"The stored extension value has a type of '" + storedType.AssemblyQualifiedName + "'. " +
"This a different from the requested type of '" + typeof(TValue).AssemblyQualifiedName + "'.");
}
else
{
throw new InvalidOperationException("Unexpected extension value type: " + valueType.AssemblyQualifiedName);
}
}
}
else
{
return null;
}
}
/// <summary>
/// Gets the value of the specified repeated extension, registering it if it doesn't exist
/// </summary>
public static RepeatedField<TValue> GetOrInitialize<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
if (set == null)
{
value = extension.CreateValue();
set = new ExtensionSet<TTarget>();
set.ValuesByNumber.Add(extension.FieldNumber, value);
}
else
{
if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value))
{
value = extension.CreateValue();
set.ValuesByNumber.Add(extension.FieldNumber, value);
}
}
return ((RepeatedExtensionValue<TValue>)value).GetValue();
}
/// <summary>
/// Sets the value of the specified extension. This will make a new instance of ExtensionSet if the set is null.
/// </summary>
public static void Set<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension, TValue value) where TTarget : IExtendableMessage<TTarget>
{
ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
IExtensionValue extensionValue;
if (set == null)
{
extensionValue = extension.CreateValue();
set = new ExtensionSet<TTarget>();
set.ValuesByNumber.Add(extension.FieldNumber, extensionValue);
}
else
{
if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out extensionValue))
{
extensionValue = extension.CreateValue();
set.ValuesByNumber.Add(extension.FieldNumber, extensionValue);
}
}
((ExtensionValue<TValue>)extensionValue).SetValue(value);
}
/// <summary>
/// Gets whether the value of the specified extension is set
/// </summary>
public static bool Has<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
return TryGetValue(ref set, extension, out value);
}
/// <summary>
/// Clears the value of the specified extension
/// </summary>
public static void Clear<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
return;
}
set.ValuesByNumber.Remove(extension.FieldNumber);
if (set.ValuesByNumber.Count == 0)
{
set = null;
}
}
/// <summary>
/// Clears the value of the specified extension
/// </summary>
public static void Clear<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
return;
}
set.ValuesByNumber.Remove(extension.FieldNumber);
if (set.ValuesByNumber.Count == 0)
{
set = null;
}
}
/// <summary>
/// Tries to merge a field from the coded input, returning true if the field was merged.
/// If the set is null or the field was not otherwise merged, this returns false.
/// </summary>
public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, CodedInputStream stream) where TTarget : IExtendableMessage<TTarget>
{
ParseContext.Initialize(stream, out ParseContext ctx);
try
{
return TryMergeFieldFrom<TTarget>(ref set, ref ctx);
}
finally
{
ctx.CopyStateTo(stream);
}
}
/// <summary>
/// Tries to merge a field from the coded input, returning true if the field was merged.
/// If the set is null or the field was not otherwise merged, this returns false.
/// </summary>
public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, ref ParseContext ctx) where TTarget : IExtendableMessage<TTarget>
{
Extension extension;
int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag);
IExtensionValue extensionValue;
if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue))
{
extensionValue.MergeFrom(ref ctx);
return true;
}
else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension))
{
IExtensionValue value = extension.CreateValue();
value.MergeFrom(ref ctx);
set = (set ?? new ExtensionSet<TTarget>());
set.ValuesByNumber.Add(extension.FieldNumber, value);
return true;
}
else
{
return false;
}
}
/// <summary>
/// Merges the second set into the first set, creating a new instance if first is null
/// </summary>
public static void MergeFrom<TTarget>(ref ExtensionSet<TTarget> first, ExtensionSet<TTarget> second) where TTarget : IExtendableMessage<TTarget>
{
if (second == null)
{
return;
}
if (first == null)
{
first = new ExtensionSet<TTarget>();
}
foreach (var pair in second.ValuesByNumber)
{
IExtensionValue value;
if (first.ValuesByNumber.TryGetValue(pair.Key, out value))
{
value.MergeFrom(pair.Value);
}
else
{
var cloned = pair.Value.Clone();
first.ValuesByNumber[pair.Key] = cloned;
}
}
}
/// <summary>
/// Clones the set into a new set. If the set is null, this returns null
/// </summary>
public static ExtensionSet<TTarget> Clone<TTarget>(ExtensionSet<TTarget> set) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
return null;
}
var newSet = new ExtensionSet<TTarget>();
foreach (var pair in set.ValuesByNumber)
{
var cloned = pair.Value.Clone();
newSet.ValuesByNumber[pair.Key] = cloned;
}
return newSet;
}
}
/// <summary>
/// Used for keeping track of extensions in messages.
/// <see cref="IExtendableMessage{T}"/> methods route to this set.
///
/// Most users will not need to use this class directly
/// </summary>
/// <typeparam name="TTarget">The message type that extensions in this set target</typeparam>
public sealed class ExtensionSet<TTarget> where TTarget : IExtendableMessage<TTarget>
{
internal Dictionary<int, IExtensionValue> ValuesByNumber { get; } = new Dictionary<int, IExtensionValue>();
/// <summary>
/// Gets a hash code of the set
/// </summary>
public override int GetHashCode()
{
int ret = typeof(TTarget).GetHashCode();
foreach (KeyValuePair<int, IExtensionValue> field in ValuesByNumber)
{
// Use ^ here to make the field order irrelevant.
int hash = field.Key.GetHashCode() ^ field.Value.GetHashCode();
ret ^= hash;
}
return ret;
}
/// <summary>
/// Returns whether this set is equal to the other object
/// </summary>
public override bool Equals(object other)
{
if (ReferenceEquals(this, other))
{
return true;
}
ExtensionSet<TTarget> otherSet = other as ExtensionSet<TTarget>;
if (ValuesByNumber.Count != otherSet.ValuesByNumber.Count)
{
return false;
}
foreach (var pair in ValuesByNumber)
{
IExtensionValue secondValue;
if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out secondValue))
{
return false;
}
if (!pair.Value.Equals(secondValue))
{
return false;
}
}
return true;
}
/// <summary>
/// Calculates the size of this extension set
/// </summary>
public int CalculateSize()
{
int size = 0;
foreach (var value in ValuesByNumber.Values)
{
size += value.CalculateSize();
}
return size;
}
/// <summary>
/// Writes the extension values in this set to the output stream
/// </summary>
public void WriteTo(CodedOutputStream stream)
{
WriteContext.Initialize(stream, out WriteContext ctx);
try
{
WriteTo(ref ctx);
}
finally
{
ctx.CopyStateTo(stream);
}
}
/// <summary>
/// Writes the extension values in this set to the write context
/// </summary>
[SecuritySafeCritical]
public void WriteTo(ref WriteContext ctx)
{
foreach (var value in ValuesByNumber.Values)
{
value.WriteTo(ref ctx);
}
}
internal bool IsInitialized()
{
return ValuesByNumber.Values.All(v => v.IsInitialized());
}
}
}
#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 Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security;
namespace Google.Protobuf
{
/// <summary>
/// Methods for managing <see cref="ExtensionSet{TTarget}"/>s with null checking.
///
/// Most users will not use this class directly and its API is experimental and subject to change.
/// </summary>
public static class ExtensionSet
{
private static bool TryGetValue<TTarget>(ref ExtensionSet<TTarget> set, Extension extension, out IExtensionValue value) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
value = null;
return false;
}
return set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value);
}
/// <summary>
/// Gets the value of the specified extension
/// </summary>
public static TValue Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
if (TryGetValue(ref set, extension, out value))
{
// The stored ExtensionValue can be a different type to what is being requested.
// This happens when the same extension proto is compiled in different assemblies.
// To allow consuming assemblies to still get the value when the TValue type is
// different, this get method:
// 1. Attempts to cast the value to the expected ExtensionValue<TValue>.
// This is the usual case. It is used first because it avoids possibly boxing the value.
// 2. Fallback to get the value as object from IExtensionValue then casting.
// This allows for someone to specify a TValue of object. They can then convert
// the values to bytes and reparse using expected value.
// 3. If neither of these work, throw a user friendly error that the types aren't compatible.
if (value is ExtensionValue<TValue> extensionValue)
{
return extensionValue.GetValue();
}
else if (value.GetValue() is TValue underlyingValue)
{
return underlyingValue;
}
else
{
var valueType = value.GetType().GetTypeInfo();
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(ExtensionValue<>))
{
var storedType = valueType.GenericTypeArguments[0];
throw new InvalidOperationException(
"The stored extension value has a type of '" + storedType.AssemblyQualifiedName + "'. " +
"This a different from the requested type of '" + typeof(TValue).AssemblyQualifiedName + "'.");
}
else
{
throw new InvalidOperationException("Unexpected extension value type: " + valueType.AssemblyQualifiedName);
}
}
}
else
{
return extension.DefaultValue;
}
}
/// <summary>
/// Gets the value of the specified repeated extension or null if it doesn't exist in this set
/// </summary>
public static RepeatedField<TValue> Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
if (TryGetValue(ref set, extension, out value))
{
if (value is RepeatedExtensionValue<TValue> extensionValue)
{
return extensionValue.GetValue();
}
else
{
var valueType = value.GetType().GetTypeInfo();
if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(RepeatedExtensionValue<>))
{
var storedType = valueType.GenericTypeArguments[0];
throw new InvalidOperationException(
"The stored extension value has a type of '" + storedType.AssemblyQualifiedName + "'. " +
"This a different from the requested type of '" + typeof(TValue).AssemblyQualifiedName + "'.");
}
else
{
throw new InvalidOperationException("Unexpected extension value type: " + valueType.AssemblyQualifiedName);
}
}
}
else
{
return null;
}
}
/// <summary>
/// Gets the value of the specified repeated extension, registering it if it doesn't exist
/// </summary>
public static RepeatedField<TValue> GetOrInitialize<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
if (set == null)
{
value = extension.CreateValue();
set = new ExtensionSet<TTarget>();
set.ValuesByNumber.Add(extension.FieldNumber, value);
}
else
{
if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value))
{
value = extension.CreateValue();
set.ValuesByNumber.Add(extension.FieldNumber, value);
}
}
return ((RepeatedExtensionValue<TValue>)value).GetValue();
}
/// <summary>
/// Sets the value of the specified extension. This will make a new instance of ExtensionSet if the set is null.
/// </summary>
public static void Set<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension, TValue value) where TTarget : IExtendableMessage<TTarget>
{
ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
IExtensionValue extensionValue;
if (set == null)
{
extensionValue = extension.CreateValue();
set = new ExtensionSet<TTarget>();
set.ValuesByNumber.Add(extension.FieldNumber, extensionValue);
}
else
{
if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out extensionValue))
{
extensionValue = extension.CreateValue();
set.ValuesByNumber.Add(extension.FieldNumber, extensionValue);
}
}
((ExtensionValue<TValue>)extensionValue).SetValue(value);
}
/// <summary>
/// Gets whether the value of the specified extension is set
/// </summary>
public static bool Has<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
return TryGetValue(ref set, extension, out value);
}
/// <summary>
/// Clears the value of the specified extension
/// </summary>
public static void Clear<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
return;
}
set.ValuesByNumber.Remove(extension.FieldNumber);
if (set.ValuesByNumber.Count == 0)
{
set = null;
}
}
/// <summary>
/// Clears the value of the specified extension
/// </summary>
public static void Clear<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
return;
}
set.ValuesByNumber.Remove(extension.FieldNumber);
if (set.ValuesByNumber.Count == 0)
{
set = null;
}
}
/// <summary>
/// Tries to merge a field from the coded input, returning true if the field was merged.
/// If the set is null or the field was not otherwise merged, this returns false.
/// </summary>
public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, CodedInputStream stream) where TTarget : IExtendableMessage<TTarget>
{
ParseContext.Initialize(stream, out ParseContext ctx);
try
{
return TryMergeFieldFrom<TTarget>(ref set, ref ctx);
}
finally
{
ctx.CopyStateTo(stream);
}
}
/// <summary>
/// Tries to merge a field from the coded input, returning true if the field was merged.
/// If the set is null or the field was not otherwise merged, this returns false.
/// </summary>
public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, ref ParseContext ctx) where TTarget : IExtendableMessage<TTarget>
{
Extension extension;
int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag);
IExtensionValue extensionValue;
if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue))
{
extensionValue.MergeFrom(ref ctx);
return true;
}
else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension))
{
IExtensionValue value = extension.CreateValue();
value.MergeFrom(ref ctx);
set = (set ?? new ExtensionSet<TTarget>());
set.ValuesByNumber.Add(extension.FieldNumber, value);
return true;
}
else
{
return false;
}
}
/// <summary>
/// Merges the second set into the first set, creating a new instance if first is null
/// </summary>
public static void MergeFrom<TTarget>(ref ExtensionSet<TTarget> first, ExtensionSet<TTarget> second) where TTarget : IExtendableMessage<TTarget>
{
if (second == null)
{
return;
}
if (first == null)
{
first = new ExtensionSet<TTarget>();
}
foreach (var pair in second.ValuesByNumber)
{
IExtensionValue value;
if (first.ValuesByNumber.TryGetValue(pair.Key, out value))
{
value.MergeFrom(pair.Value);
}
else
{
var cloned = pair.Value.Clone();
first.ValuesByNumber[pair.Key] = cloned;
}
}
}
/// <summary>
/// Clones the set into a new set. If the set is null, this returns null
/// </summary>
public static ExtensionSet<TTarget> Clone<TTarget>(ExtensionSet<TTarget> set) where TTarget : IExtendableMessage<TTarget>
{
if (set == null)
{
return null;
}
var newSet = new ExtensionSet<TTarget>();
foreach (var pair in set.ValuesByNumber)
{
var cloned = pair.Value.Clone();
newSet.ValuesByNumber[pair.Key] = cloned;
}
return newSet;
}
}
/// <summary>
/// Used for keeping track of extensions in messages.
/// <see cref="IExtendableMessage{T}"/> methods route to this set.
///
/// Most users will not need to use this class directly
/// </summary>
/// <typeparam name="TTarget">The message type that extensions in this set target</typeparam>
public sealed class ExtensionSet<TTarget> where TTarget : IExtendableMessage<TTarget>
{
internal Dictionary<int, IExtensionValue> ValuesByNumber { get; } = new Dictionary<int, IExtensionValue>();
/// <summary>
/// Gets a hash code of the set
/// </summary>
public override int GetHashCode()
{
int ret = typeof(TTarget).GetHashCode();
foreach (KeyValuePair<int, IExtensionValue> field in ValuesByNumber)
{
// Use ^ here to make the field order irrelevant.
int hash = field.Key.GetHashCode() ^ field.Value.GetHashCode();
ret ^= hash;
}
return ret;
}
/// <summary>
/// Returns whether this set is equal to the other object
/// </summary>
public override bool Equals(object other)
{
if (ReferenceEquals(this, other))
{
return true;
}
ExtensionSet<TTarget> otherSet = other as ExtensionSet<TTarget>;
if (ValuesByNumber.Count != otherSet.ValuesByNumber.Count)
{
return false;
}
foreach (var pair in ValuesByNumber)
{
IExtensionValue secondValue;
if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out secondValue))
{
return false;
}
if (!pair.Value.Equals(secondValue))
{
return false;
}
}
return true;
}
/// <summary>
/// Calculates the size of this extension set
/// </summary>
public int CalculateSize()
{
int size = 0;
foreach (var value in ValuesByNumber.Values)
{
size += value.CalculateSize();
}
return size;
}
/// <summary>
/// Writes the extension values in this set to the output stream
/// </summary>
public void WriteTo(CodedOutputStream stream)
{
WriteContext.Initialize(stream, out WriteContext ctx);
try
{
WriteTo(ref ctx);
}
finally
{
ctx.CopyStateTo(stream);
}
}
/// <summary>
/// Writes the extension values in this set to the write context
/// </summary>
[SecuritySafeCritical]
public void WriteTo(ref WriteContext ctx)
{
foreach (var value in ValuesByNumber.Values)
{
value.WriteTo(ref ctx);
}
}
internal bool IsInitialized()
{
return ValuesByNumber.Values.All(v => v.IsInitialized());
}
}
}

@ -1,49 +1,49 @@
#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.Text.RegularExpressions;
namespace Google.Protobuf
{
/// <summary>
/// Class containing helpful workarounds for various platform compatibility
/// </summary>
internal static class FrameworkPortability
{
// 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. (RegexOptions.Compiled isn't supported by PCLs.)
internal static readonly RegexOptions CompiledRegexWhereAvailable =
Enum.IsDefined(typeof(RegexOptions), 8) ? (RegexOptions)8 : RegexOptions.None;
}
#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.Text.RegularExpressions;
namespace Google.Protobuf
{
/// <summary>
/// Class containing helpful workarounds for various platform compatibility
/// </summary>
internal static class FrameworkPortability
{
// 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. (RegexOptions.Compiled isn't supported by PCLs.)
internal static readonly RegexOptions CompiledRegexWhereAvailable =
Enum.IsDefined(typeof(RegexOptions), 8) ? (RegexOptions)8 : RegexOptions.None;
}
}

@ -4,7 +4,7 @@
<Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
<Copyright>Copyright 2015, Google Inc.</Copyright>
<AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
<VersionPrefix>3.20.0-rc1</VersionPrefix>
<VersionPrefix>3.20.0</VersionPrefix>
<!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
<LangVersion>7.2</LangVersion>
<Authors>Google Inc.</Authors>

@ -1,87 +1,87 @@
#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
{
/// <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);
}
}
#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
{
/// <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);
}
}

@ -1,140 +1,140 @@
#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.Protobuf
{
/// <summary>
/// Thrown when a protocol message being parsed is invalid in some way,
/// e.g. it contains a malformed varint or a negative byte length.
/// </summary>
public sealed class InvalidProtocolBufferException : IOException
{
internal InvalidProtocolBufferException(string message)
: base(message)
{
}
internal InvalidProtocolBufferException(string message, Exception innerException)
: base(message, innerException)
{
}
internal static InvalidProtocolBufferException MoreDataAvailable()
{
return new InvalidProtocolBufferException(
"Completed reading a message while more data was available in the stream.");
}
internal static InvalidProtocolBufferException TruncatedMessage()
{
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
"in the middle of a field. This could mean either that the " +
"input has been truncated or that an embedded message " +
"misreported its own length.");
}
internal static InvalidProtocolBufferException NegativeSize()
{
return new InvalidProtocolBufferException(
"CodedInputStream encountered an embedded string or message " +
"which claimed to have negative size.");
}
internal static InvalidProtocolBufferException MalformedVarint()
{
return new InvalidProtocolBufferException(
"CodedInputStream encountered a malformed varint.");
}
/// <summary>
/// Creates an exception for an error condition of an invalid tag being encountered.
/// </summary>
internal static InvalidProtocolBufferException InvalidTag()
{
return new InvalidProtocolBufferException(
"Protocol message contained an invalid tag (zero).");
}
internal static InvalidProtocolBufferException InvalidWireType()
{
return new InvalidProtocolBufferException(
"Protocol message contained a tag with an invalid wire type.");
}
internal static InvalidProtocolBufferException InvalidBase64(Exception innerException)
{
return new InvalidProtocolBufferException("Invalid base64 data", innerException);
}
internal static InvalidProtocolBufferException InvalidEndTag()
{
return new InvalidProtocolBufferException(
"Protocol message end-group tag did not match expected tag.");
}
internal static InvalidProtocolBufferException RecursionLimitExceeded()
{
return new InvalidProtocolBufferException(
"Protocol message had too many levels of nesting. May be malicious. " +
"Use CodedInputStream.SetRecursionLimit() to increase the depth limit.");
}
internal static InvalidProtocolBufferException JsonRecursionLimitExceeded()
{
return new InvalidProtocolBufferException(
"Protocol message had too many levels of nesting. May be malicious. " +
"Use JsonParser.Settings to increase the depth limit.");
}
internal static InvalidProtocolBufferException SizeLimitExceeded()
{
return new InvalidProtocolBufferException(
"Protocol message was too large. May be malicious. " +
"Use CodedInputStream.SetSizeLimit() to increase the size limit.");
}
internal static InvalidProtocolBufferException InvalidMessageStreamTag()
{
return new InvalidProtocolBufferException(
"Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1.");
}
internal static InvalidProtocolBufferException MissingFields()
{
return new InvalidProtocolBufferException("Message was missing required fields");
}
}
#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.Protobuf
{
/// <summary>
/// Thrown when a protocol message being parsed is invalid in some way,
/// e.g. it contains a malformed varint or a negative byte length.
/// </summary>
public sealed class InvalidProtocolBufferException : IOException
{
internal InvalidProtocolBufferException(string message)
: base(message)
{
}
internal InvalidProtocolBufferException(string message, Exception innerException)
: base(message, innerException)
{
}
internal static InvalidProtocolBufferException MoreDataAvailable()
{
return new InvalidProtocolBufferException(
"Completed reading a message while more data was available in the stream.");
}
internal static InvalidProtocolBufferException TruncatedMessage()
{
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
"in the middle of a field. This could mean either that the " +
"input has been truncated or that an embedded message " +
"misreported its own length.");
}
internal static InvalidProtocolBufferException NegativeSize()
{
return new InvalidProtocolBufferException(
"CodedInputStream encountered an embedded string or message " +
"which claimed to have negative size.");
}
internal static InvalidProtocolBufferException MalformedVarint()
{
return new InvalidProtocolBufferException(
"CodedInputStream encountered a malformed varint.");
}
/// <summary>
/// Creates an exception for an error condition of an invalid tag being encountered.
/// </summary>
internal static InvalidProtocolBufferException InvalidTag()
{
return new InvalidProtocolBufferException(
"Protocol message contained an invalid tag (zero).");
}
internal static InvalidProtocolBufferException InvalidWireType()
{
return new InvalidProtocolBufferException(
"Protocol message contained a tag with an invalid wire type.");
}
internal static InvalidProtocolBufferException InvalidBase64(Exception innerException)
{
return new InvalidProtocolBufferException("Invalid base64 data", innerException);
}
internal static InvalidProtocolBufferException InvalidEndTag()
{
return new InvalidProtocolBufferException(
"Protocol message end-group tag did not match expected tag.");
}
internal static InvalidProtocolBufferException RecursionLimitExceeded()
{
return new InvalidProtocolBufferException(
"Protocol message had too many levels of nesting. May be malicious. " +
"Use CodedInputStream.SetRecursionLimit() to increase the depth limit.");
}
internal static InvalidProtocolBufferException JsonRecursionLimitExceeded()
{
return new InvalidProtocolBufferException(
"Protocol message had too many levels of nesting. May be malicious. " +
"Use JsonParser.Settings to increase the depth limit.");
}
internal static InvalidProtocolBufferException SizeLimitExceeded()
{
return new InvalidProtocolBufferException(
"Protocol message was too large. May be malicious. " +
"Use CodedInputStream.SetSizeLimit() to increase the size limit.");
}
internal static InvalidProtocolBufferException InvalidMessageStreamTag()
{
return new InvalidProtocolBufferException(
"Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1.");
}
internal static InvalidProtocolBufferException MissingFields()
{
return new InvalidProtocolBufferException("Message was missing required fields");
}
}
}

@ -1,4 +1,4 @@
#region Copyright notice and license
#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/
@ -233,13 +233,13 @@ namespace Google.Protobuf
writer.Write(PropertySeparator);
}
if (settings.PreserveProtoFieldNames)
{
WriteString(writer, accessor.Descriptor.Name);
if (settings.PreserveProtoFieldNames)
{
WriteString(writer, accessor.Descriptor.Name);
}
else
{
WriteString(writer, accessor.Descriptor.JsonName);
else
{
WriteString(writer, accessor.Descriptor.JsonName);
}
writer.Write(NameValueSeparator);
WriteValue(writer, value);
@ -823,8 +823,8 @@ namespace Google.Protobuf
/// </summary>
public bool FormatEnumsAsIntegers { get; }
/// <summary>
/// Whether to use the original proto field names as defined in the .proto file. Defaults to false.
/// <summary>
/// Whether to use the original proto field names as defined in the .proto file. Defaults to false.
/// </summary>
public bool PreserveProtoFieldNames { get; }
@ -884,9 +884,9 @@ namespace Google.Protobuf
/// <param name="formatEnumsAsIntegers"><c>true</c> to format the enums as integers; <c>false</c> to format enums as enum names.</param>
public Settings WithFormatEnumsAsIntegers(bool formatEnumsAsIntegers) => new Settings(FormatDefaultValues, TypeRegistry, formatEnumsAsIntegers, PreserveProtoFieldNames);
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified field name formatting option and the current settings.
/// </summary>
/// <summary>
/// Creates a new <see cref="Settings"/> object with the specified field name formatting option and the current settings.
/// </summary>
/// <param name="preserveProtoFieldNames"><c>true</c> to preserve proto field names; <c>false</c> to convert them to lowerCamelCase.</param>
public Settings WithPreserveProtoFieldNames(bool preserveProtoFieldNames) => new Settings(FormatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, preserveProtoFieldNames);
}

@ -1,40 +1,40 @@
using System;
namespace Google.Protobuf
{
using System;
namespace Google.Protobuf
{
/// <summary>
/// Struct used to hold the keys for the fieldByNumber table in DescriptorPool and the keys for the
/// extensionByNumber table in ExtensionRegistry.
/// </summary>
internal struct ObjectIntPair<T> : IEquatable<ObjectIntPair<T>> where T : class
{
private readonly int number;
private readonly T obj;
internal ObjectIntPair(T obj, int number)
{
this.number = number;
this.obj = obj;
}
public bool Equals(ObjectIntPair<T> other)
{
return obj == other.obj
&& number == other.number;
}
public override bool Equals(object obj)
{
if (obj is ObjectIntPair<T>)
{
return Equals((ObjectIntPair<T>)obj);
}
return false;
}
public override int GetHashCode()
{
return obj.GetHashCode() * ((1 << 16) - 1) + number;
}
}
}
/// </summary>
internal struct ObjectIntPair<T> : IEquatable<ObjectIntPair<T>> where T : class
{
private readonly int number;
private readonly T obj;
internal ObjectIntPair(T obj, int number)
{
this.number = number;
this.obj = obj;
}
public bool Equals(ObjectIntPair<T> other)
{
return obj == other.obj
&& number == other.number;
}
public override bool Equals(object obj)
{
if (obj is ObjectIntPair<T>)
{
return Equals((ObjectIntPair<T>)obj);
}
return false;
}
public override int GetHashCode()
{
return obj.GetHashCode() * ((1 << 16) - 1) + number;
}
}
}

@ -1,56 +1,56 @@
#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.Runtime.CompilerServices;
using System.Security;
// 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.
#if !NCRUNCH
[assembly: AllowPartiallyTrustedCallers]
#endif
[assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" +
"002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
"7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
"981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
"b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
"c5ae9cb6")]
[assembly: InternalsVisibleTo("Google.Protobuf.Benchmarks, PublicKey=" +
"002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
"7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
"981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
"b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
"c5ae9cb6")]
#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.Runtime.CompilerServices;
using System.Security;
// 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.
#if !NCRUNCH
[assembly: AllowPartiallyTrustedCallers]
#endif
[assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" +
"002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
"7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
"981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
"b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
"c5ae9cb6")]
[assembly: InternalsVisibleTo("Google.Protobuf.Benchmarks, PublicKey=" +
"002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
"7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
"981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
"b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
"c5ae9cb6")]

@ -1,79 +1,79 @@
#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
{
/// <summary>
/// Helper methods for throwing exceptions when preconditions are not met.
/// </summary>
/// <remarks>
/// This class is used internally and by generated code; it is not particularly
/// expected to be used from application code, although nothing prevents it
/// from being used that way.
/// </remarks>
public static class ProtoPreconditions
{
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
public static T CheckNotNull<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
/// <remarks>
/// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter
/// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull
/// with a value type - but it gets in the way if either you want to use it with a nullable
/// value type, or you want to use it with an unconstrained type parameter.
/// </remarks>
internal static T CheckNotNullUnconstrained<T>(T value, string name)
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
}
#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
{
/// <summary>
/// Helper methods for throwing exceptions when preconditions are not met.
/// </summary>
/// <remarks>
/// This class is used internally and by generated code; it is not particularly
/// expected to be used from application code, although nothing prevents it
/// from being used that way.
/// </remarks>
public static class ProtoPreconditions
{
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
public static T CheckNotNull<T>(T value, string name) where T : class
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
/// <summary>
/// Throws an ArgumentNullException if the given value is null, otherwise
/// return the value to the caller.
/// </summary>
/// <remarks>
/// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter
/// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull
/// with a value type - but it gets in the way if either you want to use it with a nullable
/// value type, or you want to use it with an unconstrained type parameter.
/// </remarks>
internal static T CheckNotNullUnconstrained<T>(T value, string name)
{
if (value == null)
{
throw new ArgumentNullException(name);
}
return value;
}
}
}

@ -9611,8 +9611,8 @@ namespace Google.Protobuf.Reflection {
/// The name of the uninterpreted option. Each string represents a segment in
/// a dot-separated name. is_extension is true iff a segment represents an
/// extension (denoted with parentheses in options specs in .proto files).
/// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
/// "foo.(bar.baz).qux".
/// E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents
/// "foo.(bar.baz).moo".
/// </summary>
public sealed partial class NamePart : pb::IMessage<NamePart>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
@ -10241,13 +10241,13 @@ namespace Google.Protobuf.Reflection {
/// // Comment attached to baz.
/// // Another line attached to baz.
///
/// // Comment attached to qux.
/// // Comment attached to moo.
/// //
/// // Another line attached to qux.
/// optional double qux = 4;
/// // Another line attached to moo.
/// optional double moo = 4;
///
/// // Detached comment for corge. This is not leading or trailing comments
/// // to qux or corge because there are blank lines separating it from
/// // to moo or corge because there are blank lines separating it from
/// // both.
///
/// // Detached comment for corge paragraph 2.

@ -1,4 +1,4 @@
#region Copyright notice and license
#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/
@ -67,15 +67,15 @@ namespace Google.Protobuf.WellKnownTypes
return lastSlash == -1 ? "" : typeUrl.Substring(lastSlash + 1);
}
/// <summary>
/// Returns a bool indictating whether this Any message is of the target message type
/// </summary>
/// <param name="descriptor">The descriptor of the message type</param>
/// <summary>
/// Returns a bool indictating whether this Any message is of the target message type
/// </summary>
/// <param name="descriptor">The descriptor of the message type</param>
/// <returns><c>true</c> if the type name matches the descriptor's full name or <c>false</c> otherwise</returns>
public bool Is(MessageDescriptor descriptor)
{
ProtoPreconditions.CheckNotNull(descriptor, nameof(descriptor));
return GetTypeName(TypeUrl) == descriptor.FullName;
public bool Is(MessageDescriptor descriptor)
{
ProtoPreconditions.CheckNotNull(descriptor, nameof(descriptor));
return GetTypeName(TypeUrl) == descriptor.FullName;
}
/// <summary>

@ -1,104 +1,104 @@
#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
namespace Google.Protobuf
{
/// <summary>
/// This class is used internally by the Protocol Buffer Library and generated
/// message implementations. It is public only for the sake of those generated
/// messages. Others should not use this class directly.
/// <para>
/// This class contains constants and helper functions useful for dealing with
/// the Protocol Buffer wire format.
/// </para>
/// </summary>
public static class WireFormat
{
/// <summary>
/// Wire types within protobuf encoding.
/// </summary>
public enum WireType : uint
{
/// <summary>
/// Variable-length integer.
/// </summary>
Varint = 0,
/// <summary>
/// A fixed-length 64-bit value.
/// </summary>
Fixed64 = 1,
/// <summary>
/// A length-delimited value, i.e. a length followed by that many bytes of data.
/// </summary>
LengthDelimited = 2,
/// <summary>
/// A "start group" value
/// </summary>
StartGroup = 3,
/// <summary>
/// An "end group" value
/// </summary>
EndGroup = 4,
/// <summary>
/// A fixed-length 32-bit value.
/// </summary>
Fixed32 = 5
}
private const int TagTypeBits = 3;
private const uint TagTypeMask = (1 << TagTypeBits) - 1;
/// <summary>
/// Given a tag value, determines the wire type (lower 3 bits).
/// </summary>
public static WireType GetTagWireType(uint tag)
{
return (WireType) (tag & TagTypeMask);
}
/// <summary>
/// Given a tag value, determines the field number (the upper 29 bits).
/// </summary>
public static int GetTagFieldNumber(uint tag)
{
return (int) (tag >> TagTypeBits);
}
/// <summary>
/// Makes a tag value given a field number and wire type.
/// </summary>
public static uint MakeTag(int fieldNumber, WireType wireType)
{
return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
}
}
#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
namespace Google.Protobuf
{
/// <summary>
/// This class is used internally by the Protocol Buffer Library and generated
/// message implementations. It is public only for the sake of those generated
/// messages. Others should not use this class directly.
/// <para>
/// This class contains constants and helper functions useful for dealing with
/// the Protocol Buffer wire format.
/// </para>
/// </summary>
public static class WireFormat
{
/// <summary>
/// Wire types within protobuf encoding.
/// </summary>
public enum WireType : uint
{
/// <summary>
/// Variable-length integer.
/// </summary>
Varint = 0,
/// <summary>
/// A fixed-length 64-bit value.
/// </summary>
Fixed64 = 1,
/// <summary>
/// A length-delimited value, i.e. a length followed by that many bytes of data.
/// </summary>
LengthDelimited = 2,
/// <summary>
/// A "start group" value
/// </summary>
StartGroup = 3,
/// <summary>
/// An "end group" value
/// </summary>
EndGroup = 4,
/// <summary>
/// A fixed-length 32-bit value.
/// </summary>
Fixed32 = 5
}
private const int TagTypeBits = 3;
private const uint TagTypeMask = (1 << TagTypeBits) - 1;
/// <summary>
/// Given a tag value, determines the wire type (lower 3 bits).
/// </summary>
public static WireType GetTagWireType(uint tag)
{
return (WireType) (tag & TagTypeMask);
}
/// <summary>
/// Given a tag value, determines the field number (the upper 29 bits).
/// </summary>
public static int GetTagFieldNumber(uint tag)
{
return (int) (tag >> TagTypeBits);
}
/// <summary>
/// Makes a tag value given a field number and wire type.
/// </summary>
public static uint MakeTag(int fieldNumber, WireType wireType)
{
return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
}
}
}

@ -71,6 +71,7 @@ These are projects we know about implementing Protocol Buffers for other program
* Kotlin: https://github.com/Kotlin/kotlinx.serialization
* Kotlin: https://github.com/ButterCam/sisyphus
* Kotlin: https://github.com/open-toast/protokt
* Kotlin Multiplatform: https://github.com/streem/pbandk
* Lua: https://code.google.com/p/protoc-gen-lua/
* Lua: http://github.com/indygreg/lua-protobuf
* Lua: https://github.com/Neopallium/lua-pb

@ -23,7 +23,7 @@ If you are using Maven, use the following:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</dependency>
```
@ -37,7 +37,7 @@ protobuf-java-util package:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</dependency>
```
@ -45,7 +45,7 @@ protobuf-java-util package:
If you are using Gradle, add the following to your `build.gradle` file's dependencies:
```
implementation 'com.google.protobuf:protobuf-java:3.20.0-rc-1'
implementation 'com.google.protobuf:protobuf-java:3.20.0'
```
Again, be sure to check that the version number matches (or is newer than) the version number of protoc that you are using.

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-bom</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [BOM]</name>

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</parent>
<artifactId>protobuf-java</artifactId>

@ -1295,13 +1295,13 @@ public final class Descriptors {
* }
* message Bar {
* extend Foo {
* optional int32 qux = 4321;
* optional int32 moo = 4321;
* }
* }
* </pre>
*
* Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}. However, {@code baz}'s
* extension scope is {@code null} while {@code qux}'s extension scope is {@code Bar}.
* Both {@code baz}'s and {@code moo}'s containing type is {@code Foo}. However, {@code baz}'s
* extension scope is {@code null} while {@code moo}'s extension scope is {@code Bar}.
*/
public Descriptor getExtensionScope() {
if (!isExtension()) {

@ -472,7 +472,7 @@ public final class TextFormat {
private final FieldDescriptor.JavaType fieldType;
public MapEntryAdapter(Object entry, FieldDescriptor fieldDescriptor) {
MapEntryAdapter(Object entry, FieldDescriptor fieldDescriptor) {
if (entry instanceof MapEntry) {
this.mapEntry = (MapEntry) entry;
} else {
@ -485,14 +485,14 @@ public final class TextFormat {
return fieldDescriptor.getMessageType().getFields().get(0).getJavaType();
}
public Object getKey() {
Object getKey() {
if (mapEntry != null) {
return mapEntry.getKey();
}
return null;
}
public Object getEntry() {
Object getEntry() {
if (mapEntry != null) {
return mapEntry;
}
@ -1557,13 +1557,13 @@ public final class TextFormat {
/**
* Determines if repeated values for non-repeated fields and oneofs are permitted. For example,
* given required/optional field "foo" and a oneof containing "baz" and "qux":
* given required/optional field "foo" and a oneof containing "baz" and "moo":
*
* <ul>
* <li>"foo: 1 foo: 2"
* <li>"baz: 1 qux: 2"
* <li>"baz: 1 moo: 2"
* <li>merging "foo: 2" into a proto in which foo is already set, or
* <li>merging "qux: 2" into a proto in which baz is already set.
* <li>merging "moo: 2" into a proto in which baz is already set.
* </ul>
*/
public enum SingularOverwritePolicy {

@ -1498,7 +1498,7 @@ public class GeneratedMessageTest {
assertThat(message.hasFooStringPiece()).isTrue();
TestUtil.assertAtMostOneFieldSetOneof(message);
message = builder.setFooBytes(TestUtil.toBytes("qux")).buildPartial();
message = builder.setFooBytes(TestUtil.toBytes("moo")).buildPartial();
assertThat(message.hasFooBytes()).isTrue();
TestUtil.assertAtMostOneFieldSetOneof(message);
@ -1508,7 +1508,7 @@ public class GeneratedMessageTest {
message =
builder
.setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build())
.setFooMessage(TestOneof2.NestedMessage.newBuilder().setMooInt(234).build())
.buildPartial();
assertThat(message.hasFooMessage()).isTrue();
TestUtil.assertAtMostOneFieldSetOneof(message);
@ -1625,31 +1625,31 @@ public class GeneratedMessageTest {
{
// set
TestOneof2.Builder builder = TestOneof2.newBuilder();
assertThat(builder.getFooMessage().getQuxInt()).isEqualTo(0);
builder.setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build());
assertThat(builder.getFooMessage().getMooInt()).isEqualTo(0);
builder.setFooMessage(TestOneof2.NestedMessage.newBuilder().setMooInt(234).build());
assertThat(builder.hasFooMessage()).isTrue();
assertThat(builder.getFooMessage().getQuxInt()).isEqualTo(234);
assertThat(builder.getFooMessage().getMooInt()).isEqualTo(234);
TestOneof2 message = builder.buildPartial();
assertThat(message.hasFooMessage()).isTrue();
assertThat(message.getFooMessage().getQuxInt()).isEqualTo(234);
assertThat(message.getFooMessage().getMooInt()).isEqualTo(234);
// clear
assertThat(builder.clearFooMessage().hasFooString()).isFalse();
message = builder.build();
assertThat(message.hasFooMessage()).isFalse();
assertThat(message.getFooMessage().getQuxInt()).isEqualTo(0);
assertThat(message.getFooMessage().getMooInt()).isEqualTo(0);
// nested builder
builder = TestOneof2.newBuilder();
assertThat(builder.getFooMessageOrBuilder())
.isSameInstanceAs(TestOneof2.NestedMessage.getDefaultInstance());
assertThat(builder.hasFooMessage()).isFalse();
builder.getFooMessageBuilder().setQuxInt(123);
builder.getFooMessageBuilder().setMooInt(123);
assertThat(builder.hasFooMessage()).isTrue();
assertThat(builder.getFooMessage().getQuxInt()).isEqualTo(123);
assertThat(builder.getFooMessage().getMooInt()).isEqualTo(123);
message = builder.build();
assertThat(message.hasFooMessage()).isTrue();
assertThat(message.getFooMessage().getQuxInt()).isEqualTo(123);
assertThat(message.getFooMessage().getMooInt()).isEqualTo(123);
}
// LazyMessage is tested in LazyMessageLiteTest.java
@ -1689,10 +1689,10 @@ public class GeneratedMessageTest {
public void testOneofMergeMessage_mergeIntoNewBuilder() {
TestOneof2.Builder builder = TestOneof2.newBuilder();
TestOneof2 message =
builder.setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
builder.setFooMessage(TestOneof2.NestedMessage.newBuilder().setMooInt(234).build()).build();
TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
assertThat(message2.hasFooMessage()).isTrue();
assertThat(message2.getFooMessage().getQuxInt()).isEqualTo(234);
assertThat(message2.getFooMessage().getMooInt()).isEqualTo(234);
}
@Test
@ -1755,12 +1755,12 @@ public class GeneratedMessageTest {
TestOneof2.Builder builder = TestOneof2.newBuilder();
TestOneof2 message =
builder
.setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build())
.setFooMessage(TestOneof2.NestedMessage.newBuilder().setMooInt(234).build())
.build();
ByteString serialized = message.toByteString();
TestOneof2 message2 = TestOneof2.parseFrom(serialized);
assertThat(message2.hasFooMessage()).isTrue();
assertThat(message2.getFooMessage().getQuxInt()).isEqualTo(234);
assertThat(message2.getFooMessage().getMooInt()).isEqualTo(234);
}
}

@ -2537,7 +2537,7 @@ public final class TestUtil {
// ===================================================================
// oneof
public static void setOneof(TestOneof2.Builder message) {
message.setFooLazyMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(100).build());
message.setFooLazyMessage(TestOneof2.NestedMessage.newBuilder().setMooInt(100).build());
message.setBarString("101");
message.setBazInt(102);
message.setBazString("103");
@ -2545,13 +2545,13 @@ public final class TestUtil {
public static void assertOneofSet(TestOneof2 message) {
Assert.assertTrue(message.hasFooLazyMessage());
Assert.assertTrue(message.getFooLazyMessage().hasQuxInt());
Assert.assertTrue(message.getFooLazyMessage().hasMooInt());
Assert.assertTrue(message.hasBarString());
Assert.assertTrue(message.hasBazInt());
Assert.assertTrue(message.hasBazString());
Assert.assertEquals(100, message.getFooLazyMessage().getQuxInt());
Assert.assertEquals(100, message.getFooLazyMessage().getMooInt());
Assert.assertEquals("101", message.getBarString());
Assert.assertEquals(102, message.getBazInt());
Assert.assertEquals("103", message.getBazString());

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</parent>
<artifactId>protobuf-kotlin-lite</artifactId>

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</parent>
<artifactId>protobuf-kotlin</artifactId>

@ -29,7 +29,7 @@ protobuf Java Lite runtime. If you are using Maven, include the following:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-javalite</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</dependency>
```

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</parent>
<artifactId>protobuf-javalite</artifactId>

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [Parent]</name>

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
</parent>
<artifactId>protobuf-java-util</artifactId>

@ -142,7 +142,7 @@ final class FieldMaskTree {
* <li>If all children of a node have been removed, the node itself will be removed as well.
* That is, if "foo" only has one child "bar" and "foo.bar" only has one child "baz",
* removing "foo.bar.barz" would remove both "foo" and "foo.bar". If "foo" has both "bar"
* and "qux" as children, removing "foo.bar" would leave the path "foo.qux" intact.
* and "moo" as children, removing "foo.bar" would leave the path "foo.moo" intact.
* <li>If the field path to remove is a non-exist sub-path, nothing will be changed.
* </ul>
*/

@ -1718,7 +1718,8 @@ public class JsonFormat {
FieldDescriptor field, JsonElement json, Message.Builder builder)
throws InvalidProtocolBufferException {
if (!(json instanceof JsonArray)) {
throw new InvalidProtocolBufferException("Expect an array but found: " + json);
throw new InvalidProtocolBufferException(
"Expected an array for " + field.getName() + " but found " + json);
}
JsonArray array = (JsonArray) json;
for (int i = 0; i < array.size(); ++i) {

@ -820,6 +820,23 @@ public class JsonFormatTest {
assertThat(map.getInt32ToEnumMapMap()).isEmpty();
}
@Test
// https://github.com/protocolbuffers/protobuf/issues/7456
public void testArrayTypeMismatch() throws IOException {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
try {
mergeFromJson(
"{\n"
+ " \"repeated_int32\": 5\n"
+ "}",
builder);
assertWithMessage("should have thrown exception for incorrect type").fail();
} catch (InvalidProtocolBufferException expected) {
assertThat(expected).hasMessageThat()
.isEqualTo("Expected an array for repeated_int32 but found 5");
}
}
@Test
public void testParserAcceptNonQuotedObjectKey() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();

@ -57,8 +57,8 @@ describe('binaryReaderTest', function() {
it('testInstanceCaches', /** @suppress {visibility} */ function() {
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
writer.writeMessage(1, dummyMessage, goog.nullFunction);
writer.writeMessage(2, dummyMessage, goog.nullFunction);
writer.writeMessage(1, dummyMessage, () => {});
writer.writeMessage(2, dummyMessage, () => {});
var buffer = writer.getResultBuffer();
@ -139,7 +139,7 @@ describe('binaryReaderTest', function() {
var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
reader.nextField();
assertThrows(function() {
reader.readMessage(dummyMessage, goog.nullFunction);
reader.readMessage(dummyMessage, () => {});
});
// Reading past the end of the stream should trigger an assertion.
@ -651,7 +651,7 @@ describe('binaryReaderTest', function() {
});
// Add one empty message.
writer.writeMessage(6, dummyMessage, goog.nullFunction);
writer.writeMessage(6, dummyMessage, () => {});
writer.writeInt32(7, 700);

@ -65,7 +65,7 @@ describe('binaryWriterTest', function() {
var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
assertFails(function() {
writer.writeMessage(-1, dummyMessage, goog.nullFunction);
writer.writeMessage(-1, dummyMessage, () => {});
});
// Writing invalid field indices should assert.

@ -56,8 +56,8 @@ describe('binaryReaderTest', function() {
it('testInstanceCaches', /** @suppress {visibility} */ function() {
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
writer.writeMessage(1, dummyMessage, goog.nullFunction);
writer.writeMessage(2, dummyMessage, goog.nullFunction);
writer.writeMessage(1, dummyMessage, () => {});
writer.writeMessage(2, dummyMessage, () => {});
var buffer = writer.getResultBuffer();
@ -138,7 +138,7 @@ describe('binaryReaderTest', function() {
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
reader.nextField();
assertThrows(function() {
reader.readMessage(dummyMessage, goog.nullFunction);
reader.readMessage(dummyMessage, () => {});
});
// Reading past the end of the stream should trigger an assertion.
@ -596,7 +596,7 @@ describe('binaryReaderTest', function() {
});
// Add one empty message.
writer.writeMessage(6, dummyMessage, goog.nullFunction);
writer.writeMessage(6, dummyMessage, () => {});
writer.writeInt32(7, 700);

@ -62,7 +62,7 @@ describe('binaryWriterTest', function() {
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
assertFails(function() {
writer.writeMessage(-1, dummyMessage, goog.nullFunction);
writer.writeMessage(-1, dummyMessage, () => {});
});
// Writing invalid field indices should assert.

@ -56,8 +56,8 @@ describe('binaryReaderTest', function() {
it('testInstanceCaches', /** @suppress {visibility} */ function() {
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
writer.writeMessage(1, dummyMessage, goog.nullFunction);
writer.writeMessage(2, dummyMessage, goog.nullFunction);
writer.writeMessage(1, dummyMessage, () => {});
writer.writeMessage(2, dummyMessage, () => {});
var buffer = writer.getResultBuffer();
@ -138,7 +138,7 @@ describe('binaryReaderTest', function() {
var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
reader.nextField();
assertThrows(function() {
reader.readMessage(dummyMessage, goog.nullFunction);
reader.readMessage(dummyMessage, () => {});
});
// Reading past the end of the stream should trigger an assertion.
@ -620,7 +620,7 @@ describe('binaryReaderTest', function() {
});
// Add one empty message.
writer.writeMessage(6, dummyMessage, goog.nullFunction);
writer.writeMessage(6, dummyMessage, () => {});
writer.writeInt32(7, 700);

@ -62,7 +62,7 @@ describe('binaryWriterTest', function() {
var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
assertFails(function() {
writer.writeMessage(-1, dummyMessage, goog.nullFunction);
writer.writeMessage(-1, dummyMessage, () => {});
});
// Writing invalid field indices should assert.

@ -0,0 +1,92 @@
# Log capturing for the Kokoro runtime environment.
#
# This script should be `source`d from Kokoro build scripts to configure log
# capturing when running under Kokoro.
#
# When not running under Kokoro, no logs will be collected. If you want to run
# locally and collect logs anyway, set the KOKORO_ARTIFACTS_DIR environment
# variable to a directory where the logs should go.
#
# The job `.cfg` file needs the following stanzas to declare the captured logs
# as outputs (yes, these are globs, not regexes):
#
# action: {
# define_artifacts: {
# regex: "**/*sponge_log.log"
# regex: "**/*sponge_log.xml"
# }
# }
#
# Use the provided functions below as build/test fixtures, e.g.:
#
# source kokoro/capture_logs.sh
# caplog build/step1 <build command>
# caplog tests/step2 <test command>
#
# If log capturing is enabled, this script will set some variables that can be
# used if necessary:
#
# CAPLOG_DIR is used for logs
# CAPLOG_CMAKE_ARGS contains extra cmake args to enable test XML output
# CAPLOG_CTEST_ARGS contains extra ctest args to capture combined test logs
#
# For example:
#
# if [[ -v CAPLOG_DIR_BUILD ]]; then
# cp extra_diagnostics.log "${CAPLOG_DIR_BUILD}/diagnostics.log"
# fi
#
# # Use ${...:-} form under `set -u`:
# caplog build/01_configure cmake -G Ninja ${CAPLOG_CMAKE_ARGS:-}
# caplog build/02_build cmake --build
# caplog test/03_test ctest ${CAPLOG_CTEST_ARGS:-}
if [[ -z ${KOKORO_ARTIFACTS_DIR:-} ]]; then
function caplog() { shift; "$@"; }
else
CAPLOG_DIR="$(mktemp -d)"
CAPLOG_CMAKE_ARGS="-Dprotobuf_TEST_XML_OUTDIR=${CAPLOG_DIR}/tests/"
CAPLOG_CTEST_ARGS="--verbose"
# Captures the stdout/stderr of a command to a named log file.
# Usage: caplog NAME COMMAND [ARGS...]
function caplog() {
_name="${CAPLOG_DIR}/${1%.log}.log"; shift
mkdir -p "${_name%/*}"
date
time ( "$@" 2>&1 | tee "${_name}" )
if [[ $? != 0 ]] ; then
cat "${_name}"
return 1
fi
}
# Trap handler: renames logs on script exit so they will be found by Kokoro.
function _caplog_onexit() {
_rc=$?
set +x
echo "Collecting logs [${BASH_SOURCE}]"
find "${CAPLOG_DIR}" -type f -name '*.log' \
| while read _textlog; do
# Ensure an XML file exists for each .log file.
touch ${_textlog%.log}.xml
done
find "${CAPLOG_DIR}" -type f \( -name '*.xml' -or -name '*.log' \) \
| while read _src; do
# Move to artifacts dir, preserving the path relative to CAPLOG_DIR.
# The filename changes from foo/bar.log to foo/bar/sponge_log.log.
_logfile=${_src/${CAPLOG_DIR}\//}
_stem=${KOKORO_ARTIFACTS_DIR}/${_logfile%.*}
_ext=${_logfile##*.}
mkdir -p ${_stem}
mv -v "${_src}" "${_stem}/sponge_log.${_ext}"
done
rm -rv "${CAPLOG_DIR}"
exit ${_rc}
}
trap _caplog_onexit EXIT
fi

@ -38,6 +38,7 @@ RUN /bin/bash -l -c "rvm install 3.0.0"
RUN /bin/bash -l -c "rvm install 3.1.0"
RUN /bin/bash -l -c "rvm install jruby-9.2.20.1"
RUN /bin/bash -l -c "rvm install jruby-9.3.3.0"
RUN /bin/bash -l -c "rvm install jruby-9.3.4.0"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"

@ -0,0 +1,4 @@
# macOS-next
This builder is temporary for developing and testing builds using the "next"
macOS version without affecting the ordinary builds.

@ -0,0 +1,55 @@
#!/bin/bash -eux
#
# Build file to set up and run tests
set -o pipefail
if [[ -h /tmpfs ]] && [[ ${PWD} == /tmpfs/src ]]; then
# Workaround for internal Kokoro bug: b/227401944
cd /Volumes/BuildData/tmpfs/src
fi
# These vars can be changed when running manually, e.g.:
#
# % BUILD_CONFIG=RelWithDebInfo path/to/build.sh
# By default, build using Debug config.
: ${BUILD_CONFIG:=Debug}
# By default, find the sources based on this script path.
: ${SOURCE_DIR:=$(cd $(dirname $0)/../../..; pwd)}
# By default, put outputs under <git root>/cmake/build.
: ${BUILD_DIR:=${SOURCE_DIR}/cmake/build}
source ${SOURCE_DIR}/kokoro/caplog.sh
#
# Update submodules
#
git -C "${SOURCE_DIR}" submodule update --init --recursive
#
# Configure and build in a separate directory
#
mkdir -p "${BUILD_DIR}"
caplog 01_configure \
cmake -S "${SOURCE_DIR}" -B "${BUILD_DIR}" ${CAPLOG_CMAKE_ARGS:-}
if [[ -n ${CAPLOG_DIR:-} ]]; then
mkdir -p "${CAPLOG_DIR}/CMakeFiles"
cp "${BUILD_DIR}"/CMakeFiles/CMake*.log "${CAPLOG_DIR}/CMakeFiles"
fi
caplog 02_build \
cmake --build "${BUILD_DIR}" --config "${BUILD_CONFIG}"
#
# Run tests
#
(
cd "${BUILD_DIR}"
caplog 03_combined_testlog \
ctest -C "${BUILD_CONFIG}" -j4 ${CAPLOG_CTEST_ARGS:-}
)

@ -0,0 +1,13 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/macos-next/cpp/build.sh"
timeout_mins: 1440
# Upload logs
action: {
define_artifacts: {
regex: "**/*sponge_log.log"
regex: "**/*sponge_log.xml"
}
}

@ -0,0 +1,13 @@
# Config file for running tests in Kokoro
# Location of the build script in repository
build_file: "protobuf/kokoro/macos-next/cpp/build.sh"
timeout_mins: 1440
# Upload logs
action: {
define_artifacts: {
regex: "**/*sponge_log.log"
regex: "**/*sponge_log.xml"
}
}

@ -1,10 +1,10 @@
{
"dependency_tree": {
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
"__INPUT_ARTIFACTS_HASH": -1867950668,
"__RESOLVED_ARTIFACTS_HASH": 1254982283,
"__INPUT_ARTIFACTS_HASH": -228414992,
"__RESOLVED_ARTIFACTS_HASH": -722345565,
"conflict_resolution": {
"com.google.errorprone:error_prone_annotations:2.3.2": "com.google.errorprone:error_prone_annotations:2.5.1",
"com.google.errorprone:error_prone_annotations:2.3.2": "com.google.errorprone:error_prone_annotations:2.11.0",
"junit:junit:4.12": "junit:junit:4.13.2"
},
"dependencies": [
@ -45,16 +45,16 @@
"url": "https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.9/gson-2.8.9.jar"
},
{
"coord": "com.google.errorprone:error_prone_annotations:2.5.1",
"coord": "com.google.errorprone:error_prone_annotations:2.11.0",
"dependencies": [],
"directDependencies": [],
"file": "v1/https/repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar",
"file": "v1/https/repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.11.0/error_prone_annotations-2.11.0.jar",
"mirror_urls": [
"https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar",
"https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar"
"https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.11.0/error_prone_annotations-2.11.0.jar",
"https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.11.0/error_prone_annotations-2.11.0.jar"
],
"sha256": "ff80626baaf12a09342befd4e84cba9d50662f5fcd7f7a9b3490a6b7cf87e66c",
"url": "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.5.1/error_prone_annotations-2.5.1.jar"
"sha256": "721cb91842b46fa056847d104d5225c8b8e1e8b62263b993051e1e5a0137b7ec",
"url": "https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.11.0/error_prone_annotations-2.11.0.jar"
},
{
"coord": "com.google.guava:failureaccess:1.0.1",
@ -69,59 +69,59 @@
"url": "https://repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar"
},
{
"coord": "com.google.guava:guava-testlib:30.1.1-jre",
"coord": "com.google.guava:guava-testlib:31.1-jre",
"dependencies": [
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.errorprone:error_prone_annotations:2.5.1",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.guava:failureaccess:1.0.1",
"com.google.guava:guava:30.1.1-jre",
"com.google.guava:guava:31.1-jre",
"com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
"com.google.j2objc:j2objc-annotations:1.3",
"junit:junit:4.13.2",
"org.checkerframework:checker-qual:3.9.1",
"org.checkerframework:checker-qual:3.12.0",
"org.hamcrest:hamcrest-core:1.3"
],
"directDependencies": [
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.errorprone:error_prone_annotations:2.5.1",
"com.google.guava:guava:30.1.1-jre",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.guava:guava:31.1-jre",
"com.google.j2objc:j2objc-annotations:1.3",
"junit:junit:4.13.2",
"org.checkerframework:checker-qual:3.9.1"
"org.checkerframework:checker-qual:3.12.0"
],
"file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava-testlib/30.1.1-jre/guava-testlib-30.1.1-jre.jar",
"file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava-testlib/31.1-jre/guava-testlib-31.1-jre.jar",
"mirror_urls": [
"https://repo1.maven.org/maven2/com/google/guava/guava-testlib/30.1.1-jre/guava-testlib-30.1.1-jre.jar",
"https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/30.1.1-jre/guava-testlib-30.1.1-jre.jar"
"https://repo1.maven.org/maven2/com/google/guava/guava-testlib/31.1-jre/guava-testlib-31.1-jre.jar",
"https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/31.1-jre/guava-testlib-31.1-jre.jar"
],
"sha256": "8a7fc9adfa1e7441d1d30ca288c593ebc7c4a24c601d01169b781c398f24099b",
"url": "https://repo1.maven.org/maven2/com/google/guava/guava-testlib/30.1.1-jre/guava-testlib-30.1.1-jre.jar"
"sha256": "aadc71b10d5c3ac474dd16be84cfb18d257e584d1e0a59f8cab64ef4376226ce",
"url": "https://repo1.maven.org/maven2/com/google/guava/guava-testlib/31.1-jre/guava-testlib-31.1-jre.jar"
},
{
"coord": "com.google.guava:guava:30.1.1-jre",
"coord": "com.google.guava:guava:31.1-jre",
"dependencies": [
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.errorprone:error_prone_annotations:2.5.1",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.guava:failureaccess:1.0.1",
"com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
"com.google.j2objc:j2objc-annotations:1.3",
"org.checkerframework:checker-qual:3.9.1"
"org.checkerframework:checker-qual:3.12.0"
],
"directDependencies": [
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.errorprone:error_prone_annotations:2.5.1",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.guava:failureaccess:1.0.1",
"com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
"com.google.j2objc:j2objc-annotations:1.3",
"org.checkerframework:checker-qual:3.9.1"
"org.checkerframework:checker-qual:3.12.0"
],
"file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar",
"file": "v1/https/repo1.maven.org/maven2/com/google/guava/guava/31.1-jre/guava-31.1-jre.jar",
"mirror_urls": [
"https://repo1.maven.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar",
"https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar"
"https://repo1.maven.org/maven2/com/google/guava/guava/31.1-jre/guava-31.1-jre.jar",
"https://repo.maven.apache.org/maven2/com/google/guava/guava/31.1-jre/guava-31.1-jre.jar"
],
"sha256": "44ce229ce26d880bf3afc362bbfcec34d7e6903d195bbb1db9f3b6e0d9834f06",
"url": "https://repo1.maven.org/maven2/com/google/guava/guava/30.1.1-jre/guava-30.1.1-jre.jar"
"sha256": "a42edc9cab792e39fe39bb94f3fca655ed157ff87a8af78e1d6ba5b07c4a00ab",
"url": "https://repo1.maven.org/maven2/com/google/guava/guava/31.1-jre/guava-31.1-jre.jar"
},
{
"coord": "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava",
@ -151,18 +151,18 @@
"coord": "com.google.truth:truth:1.1.2",
"dependencies": [
"com.google.auto.value:auto-value-annotations:1.7.4",
"com.google.errorprone:error_prone_annotations:2.5.1",
"com.google.guava:guava:30.1.1-jre",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.guava:guava:31.1-jre",
"junit:junit:4.13.2",
"org.checkerframework:checker-qual:3.9.1",
"org.checkerframework:checker-qual:3.12.0",
"org.ow2.asm:asm:9.0"
],
"directDependencies": [
"com.google.auto.value:auto-value-annotations:1.7.4",
"com.google.errorprone:error_prone_annotations:2.5.1",
"com.google.guava:guava:30.1.1-jre",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.guava:guava:31.1-jre",
"junit:junit:4.13.2",
"org.checkerframework:checker-qual:3.9.1",
"org.checkerframework:checker-qual:3.12.0",
"org.ow2.asm:asm:9.0"
],
"file": "v1/https/repo1.maven.org/maven2/com/google/truth/truth/1.1.2/truth-1.1.2.jar",
@ -214,16 +214,16 @@
"url": "https://repo1.maven.org/maven2/net/bytebuddy/byte-buddy/1.12.7/byte-buddy-1.12.7.jar"
},
{
"coord": "org.checkerframework:checker-qual:3.9.1",
"coord": "org.checkerframework:checker-qual:3.12.0",
"dependencies": [],
"directDependencies": [],
"file": "v1/https/repo1.maven.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar",
"file": "v1/https/repo1.maven.org/maven2/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar",
"mirror_urls": [
"https://repo1.maven.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar",
"https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar"
"https://repo1.maven.org/maven2/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar",
"https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar"
],
"sha256": "ab0468b1ba35bb2ae45f61a60dc4960bd887660ab8f05113a662a7e675eae776",
"url": "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/3.9.1/checker-qual-3.9.1.jar"
"sha256": "ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb",
"url": "https://repo1.maven.org/maven2/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar"
},
{
"coord": "org.hamcrest:hamcrest-core:1.3",

@ -10,15 +10,15 @@
<email>protobuf-opensource@google.com</email>
<active>yes</active>
</lead>
<date>2022-03-04</date>
<time>16:28:14</time>
<date>2022-03-25</date>
<time>19:17:44</time>
<version>
<release>3.20.0RC1</release>
<release>3.20.0</release>
<api>3.20.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
@ -46,10 +46,12 @@
<file baseinstalldir="/" name="protobuf.c" role="src"/>
<file baseinstalldir="/" name="protobuf.h" role="src"/>
<file baseinstalldir="/" name="wkt.inc" role="src"/>
<file baseinstalldir="/" name="third_party/utf8_range/naive.c" role="doc"/>
<file baseinstalldir="/" name="third_party/utf8_range/range2-neon.c" role="doc"/>
<file baseinstalldir="/" name="third_party/utf8_range/range2-sse.c" role="doc"/>
<file baseinstalldir="/" name="LICENSE" role="doc"/>
<file baseinstalldir="/" name="third_party/utf8_range/naive.c" role="src"/>
<file baseinstalldir="/" name="third_party/utf8_range/range2-neon.c" role="src"/>
<file baseinstalldir="/" name="third_party/utf8_range/range2-sse.c" role="src"/>
<file baseinstalldir="/" name="third_party/utf8_range/utf8_range.h" role="src"/>
<file baseinstalldir="/" name="third_party/utf8_range/LICENSE" role="doc"/>
</dir>
</contents>
<dependencies>
@ -1221,5 +1223,35 @@ G A release.
<notes>
</notes>
</release>
<release>
<version>
<release>3.20.0RC2</release>
<api>3.20.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2022-03-15</date>
<time>21:10:15</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
</notes>
</release>
<release>
<version>
<release>3.20.0</release>
<api>3.20.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2022-03-25</date>
<time>19:17:44</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
<notes>
</notes>
</release>
</changelog>
</package>

@ -127,7 +127,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setter, 0, 0, 1)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
#define PHP_PROTOBUF_VERSION "3.20.0RC1"
#define PHP_PROTOBUF_VERSION "3.20.0"
// ptr -> PHP object cache. This is a weak map that caches lazily-created
// wrapper objects around upb types:

@ -30,7 +30,11 @@ mv ../protobuf/composer.json composer.json
sed -i 's|php/src|src|g' composer.json
git add .
git commit -m "$VERSION"
git tag "$VERSION"
if [ $(git tag -l "$VERSION") ]; then
echo "tag $VERSION already exists"
else
git tag "$VERSION"
fi
popd
# Clean up

@ -72,12 +72,12 @@ class Location extends \Google\Protobuf\Internal\Message
* optional string baz = 3;
* // Comment attached to baz.
* // Another line attached to baz.
* // Comment attached to qux.
* // Comment attached to moo.
* //
* // Another line attached to qux.
* optional double qux = 4;
* // Another line attached to moo.
* optional double moo = 4;
* // Detached comment for corge. This is not leading or trailing comments
* // to qux or corge because there are blank lines separating it from
* // to moo or corge because there are blank lines separating it from
* // both.
* // Detached comment for corge paragraph 2.
* optional string corge = 5;
@ -156,12 +156,12 @@ class Location extends \Google\Protobuf\Internal\Message
* optional string baz = 3;
* // Comment attached to baz.
* // Another line attached to baz.
* // Comment attached to qux.
* // Comment attached to moo.
* //
* // Another line attached to qux.
* optional double qux = 4;
* // Another line attached to moo.
* optional double moo = 4;
* // Detached comment for corge. This is not leading or trailing comments
* // to qux or corge because there are blank lines separating it from
* // to moo or corge because there are blank lines separating it from
* // both.
* // Detached comment for corge paragraph 2.
* optional string corge = 5;
@ -302,12 +302,12 @@ class Location extends \Google\Protobuf\Internal\Message
* optional string baz = 3;
* // Comment attached to baz.
* // Another line attached to baz.
* // Comment attached to qux.
* // Comment attached to moo.
* //
* // Another line attached to qux.
* optional double qux = 4;
* // Another line attached to moo.
* optional double moo = 4;
* // Detached comment for corge. This is not leading or trailing comments
* // to qux or corge because there are blank lines separating it from
* // to moo or corge because there are blank lines separating it from
* // both.
* // Detached comment for corge paragraph 2.
* optional string corge = 5;
@ -358,12 +358,12 @@ class Location extends \Google\Protobuf\Internal\Message
* optional string baz = 3;
* // Comment attached to baz.
* // Another line attached to baz.
* // Comment attached to qux.
* // Comment attached to moo.
* //
* // Another line attached to qux.
* optional double qux = 4;
* // Another line attached to moo.
* optional double moo = 4;
* // Detached comment for corge. This is not leading or trailing comments
* // to qux or corge because there are blank lines separating it from
* // to moo or corge because there are blank lines separating it from
* // both.
* // Detached comment for corge paragraph 2.
* optional string corge = 5;

@ -14,8 +14,8 @@ use Google\Protobuf\Internal\GPBUtil;
* The name of the uninterpreted option. Each string represents a segment in
* a dot-separated name. is_extension is true iff a segment represents an
* extension (denoted with parentheses in options specs in .proto files).
* E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
* "foo.(bar.baz).qux".
* E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents
* "foo.(bar.baz).moo".
*
* Generated from protobuf message <code>google.protobuf.UninterpretedOption.NamePart</code>
*/

@ -266,9 +266,9 @@ def cc_proto_library(
deps = [],
cc_libs = [],
include = None,
protoc = Label("//:protoc"),
protoc = "@com_google_protobuf//:protoc",
use_grpc_plugin = False,
default_runtime = Label("//:protobuf"),
default_runtime = "@com_google_protobuf//:protobuf",
**kargs):
"""Bazel rule to create a C++ protobuf library from proto source files
@ -386,7 +386,7 @@ internal_gen_well_known_protos_java = rule(
"_protoc": attr.label(
executable = True,
cfg = "exec",
default = "//:protoc",
default = "@com_google_protobuf//:protoc",
),
},
)
@ -493,8 +493,8 @@ def py_proto_library(
py_libs = [],
py_extra_srcs = [],
include = None,
default_runtime = Label("//:protobuf_python"),
protoc = Label("//:protoc"),
default_runtime = "@com_google_protobuf//:protobuf_python",
protoc = "@com_google_protobuf//:protoc",
use_grpc_plugin = False,
**kargs):
"""Bazel rule to create a Python protobuf library from proto source files

@ -7,8 +7,8 @@ PROTOBUF_MAVEN_ARTIFACTS = [
"com.google.code.gson:gson:2.8.9",
"com.google.errorprone:error_prone_annotations:2.3.2",
"com.google.j2objc:j2objc-annotations:1.3",
"com.google.guava:guava:30.1.1-jre",
"com.google.guava:guava-testlib:30.1.1-jre",
"com.google.guava:guava:31.1-jre",
"com.google.guava:guava-testlib:31.1-jre",
"com.google.truth:truth:1.1.2",
"junit:junit:4.13.2",
"org.mockito:mockito-core:4.3.1",
@ -30,7 +30,7 @@ def protobuf_deps():
if not native.existing_rule("zlib"):
http_archive(
name = "zlib",
build_file = Label("//:third_party/zlib.BUILD"),
build_file = "@com_google_protobuf//:third_party/zlib.BUILD",
sha256 = "629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff",
strip_prefix = "zlib-1.2.11",
urls = ["https://github.com/madler/zlib/archive/v1.2.11.tar.gz"],

@ -1 +1 @@
PROTOBUF_VERSION = '3.20.0-rc-1'
PROTOBUF_VERSION = '3.20.0'

@ -8,7 +8,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protoc</artifactId>
<version>3.20.0-rc-1</version>
<version>3.20.0</version>
<packaging>pom</packaging>
<name>Protobuf Compiler</name>
<description>

@ -328,10 +328,10 @@ class DescriptorTest(unittest.TestCase):
unittest_custom_options_pb2.complex_opt1].foo)
self.assertEqual(324, options.Extensions[
unittest_custom_options_pb2.complex_opt1].Extensions[
unittest_custom_options_pb2.quux])
unittest_custom_options_pb2.mooo])
self.assertEqual(876, options.Extensions[
unittest_custom_options_pb2.complex_opt1].Extensions[
unittest_custom_options_pb2.corge].qux)
unittest_custom_options_pb2.corge].moo)
self.assertEqual(987, options.Extensions[
unittest_custom_options_pb2.complex_opt2].baz)
self.assertEqual(654, options.Extensions[
@ -341,28 +341,28 @@ class DescriptorTest(unittest.TestCase):
unittest_custom_options_pb2.complex_opt2].bar.foo)
self.assertEqual(1999, options.Extensions[
unittest_custom_options_pb2.complex_opt2].bar.Extensions[
unittest_custom_options_pb2.quux])
unittest_custom_options_pb2.mooo])
self.assertEqual(2008, options.Extensions[
unittest_custom_options_pb2.complex_opt2].bar.Extensions[
unittest_custom_options_pb2.corge].qux)
unittest_custom_options_pb2.corge].moo)
self.assertEqual(741, options.Extensions[
unittest_custom_options_pb2.complex_opt2].Extensions[
unittest_custom_options_pb2.garply].foo)
self.assertEqual(1998, options.Extensions[
unittest_custom_options_pb2.complex_opt2].Extensions[
unittest_custom_options_pb2.garply].Extensions[
unittest_custom_options_pb2.quux])
unittest_custom_options_pb2.mooo])
self.assertEqual(2121, options.Extensions[
unittest_custom_options_pb2.complex_opt2].Extensions[
unittest_custom_options_pb2.garply].Extensions[
unittest_custom_options_pb2.corge].qux)
unittest_custom_options_pb2.corge].moo)
self.assertEqual(1971, options.Extensions[
unittest_custom_options_pb2.ComplexOptionType2
.ComplexOptionType4.complex_opt4].waldo)
self.assertEqual(321, options.Extensions[
unittest_custom_options_pb2.complex_opt2].fred.waldo)
self.assertEqual(9, options.Extensions[
unittest_custom_options_pb2.complex_opt3].qux)
unittest_custom_options_pb2.complex_opt3].moo)
self.assertEqual(22, options.Extensions[
unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh)
self.assertEqual(24, options.Extensions[

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

Loading…
Cancel
Save