diff options
author | Jon Skeet <skeet@pobox.com> | 2015-07-17 07:29:50 +0100 |
---|---|---|
committer | Jon Skeet <skeet@pobox.com> | 2015-07-17 07:29:50 +0100 |
commit | 0f442a7533b1d06ce0092b28f10af481b99e1369 (patch) | |
tree | 4f9cb3ecb2d8ab4f9c138a06d645a3cc3dcdeef3 /src/google | |
parent | fa544f4835623be66d73e1d984121ab4a92e1650 (diff) | |
parent | 34878cb14eba4578d1d67d2dc93250729d492774 (diff) | |
download | protobuf-0f442a7533b1d06ce0092b28f10af481b99e1369.tar.gz protobuf-0f442a7533b1d06ce0092b28f10af481b99e1369.tar.bz2 protobuf-0f442a7533b1d06ce0092b28f10af481b99e1369.zip |
Merge pull request #611 from jskeet/csharp-wrappers
C# wrapper types
Diffstat (limited to 'src/google')
9 files changed, 463 insertions, 34 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index c9791c1d..89d4eb18 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -169,6 +169,18 @@ std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) { return GetClassName(descriptor->enum_type()); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: + if (IsWrapperType(descriptor)) { + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + string wrapped_field_type_name = type_name(wrapped_field); + // String and ByteString go to the same type; other wrapped types go to the + // nullable equivalent. + if (wrapped_field->type() == FieldDescriptor::TYPE_STRING || + wrapped_field->type() == FieldDescriptor::TYPE_BYTES) { + return wrapped_field_type_name; + } else { + return wrapped_field_type_name + "?"; + } + } return GetClassName(descriptor->message_type()); case FieldDescriptor::TYPE_DOUBLE: return "double"; @@ -298,14 +310,23 @@ std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { } std::string FieldGeneratorBase::default_value() { - switch (descriptor_->type()) { + return default_value(descriptor_); +} + +std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) { + switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - return type_name() + "." + descriptor_->default_value_enum()->name(); + return type_name() + "." + descriptor->default_value_enum()->name(); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: - return type_name() + ".DefaultInstance"; + if (IsWrapperType(descriptor)) { + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + return default_value(wrapped_field); + } else { + return "null"; + } case FieldDescriptor::TYPE_DOUBLE: { - double value = descriptor_->default_value_double(); + double value = descriptor->default_value_double(); if (value == numeric_limits<double>::infinity()) { return "double.PositiveInfinity"; } else if (value == -numeric_limits<double>::infinity()) { @@ -316,7 +337,7 @@ std::string FieldGeneratorBase::default_value() { return SimpleDtoa(value) + "D"; } case FieldDescriptor::TYPE_FLOAT: { - float value = descriptor_->default_value_float(); + float value = descriptor->default_value_float(); if (value == numeric_limits<float>::infinity()) { return "float.PositiveInfinity"; } else if (value == -numeric_limits<float>::infinity()) { @@ -327,17 +348,17 @@ std::string FieldGeneratorBase::default_value() { return SimpleFtoa(value) + "F"; } case FieldDescriptor::TYPE_INT64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_UINT64: - return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + return SimpleItoa(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_INT32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_FIXED64: - return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + return SimpleItoa(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_FIXED32: - return SimpleItoa(descriptor_->default_value_uint32()); + return SimpleItoa(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_BOOL: - if (descriptor_->default_value_bool()) { + if (descriptor->default_value_bool()) { return "true"; } else { return "false"; @@ -347,15 +368,15 @@ std::string FieldGeneratorBase::default_value() { case FieldDescriptor::TYPE_BYTES: return GetBytesDefaultValueInternal(); case FieldDescriptor::TYPE_UINT32: - return SimpleItoa(descriptor_->default_value_uint32()); + return SimpleItoa(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_SFIXED32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SFIXED64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_SINT32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SINT64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; default: GOOGLE_LOG(FATAL)<< "Unknown field type."; return ""; diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index bffa2062..4761dc49 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -82,6 +82,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { bool has_default_value(); bool is_nullable_type(); std::string default_value(); + std::string default_value(const FieldDescriptor* descriptor); std::string number(); std::string capitalized_type_name(); std::string field_ordinal(); diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 8ecd1dc2..1c7a24a9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -52,6 +52,7 @@ #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> namespace google { namespace protobuf { @@ -366,31 +367,39 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal); } } else { - if (descriptor->containing_oneof()) { - return new MessageOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new MessageFieldGenerator(descriptor, fieldOrdinal); - } + if (IsWrapperType(descriptor)) { + if (descriptor->containing_oneof()) { + return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new WrapperFieldGenerator(descriptor, fieldOrdinal); + } + } else { + if (descriptor->containing_oneof()) { + return new MessageOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new MessageFieldGenerator(descriptor, fieldOrdinal); + } + } } case FieldDescriptor::TYPE_ENUM: if (descriptor->is_repeated()) { return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal); } else { - if (descriptor->containing_oneof()) { - return new EnumOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new EnumFieldGenerator(descriptor, fieldOrdinal); - } + if (descriptor->containing_oneof()) { + return new EnumOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new EnumFieldGenerator(descriptor, fieldOrdinal); + } } default: if (descriptor->is_repeated()) { return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal); } else { - if (descriptor->containing_oneof()) { - return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); - } + if (descriptor->containing_oneof()) { + return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); + } } } } diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index 111feabd..653ff992 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -119,6 +119,15 @@ inline bool IsDescriptorProto(const FileDescriptor* descriptor) { return descriptor->name() == "google/protobuf/descriptor_proto_file.proto"; } +inline bool IsMapEntry(const Descriptor* descriptor) { + return descriptor->options().map_entry(); +} + +inline bool IsWrapperType(const FieldDescriptor* descriptor) { + return descriptor->type() == FieldDescriptor::TYPE_MESSAGE && + descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc index 32c05232..cba24a59 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -61,6 +61,7 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) { descriptor_->message_type()->FindFieldByName("value"); variables_["key_type_name"] = type_name(key_descriptor); variables_["value_type_name"] = type_name(value_descriptor); + variables_["true_for_wrappers"] = IsWrapperType(value_descriptor) ? "true" : ""; scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1)); scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2)); @@ -74,7 +75,7 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, ", $tag$);\n" - "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n"); + "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>($true_for_wrappers$);\n"); AddDeprecatedFlag(printer); printer->Print( variables_, diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 6d4e6984..d939fc79 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -39,6 +39,8 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> +#include <google/protobuf/compiler/csharp/csharp_message_field.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> namespace google { namespace protobuf { @@ -58,7 +60,18 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n" - " = pb::FieldCodec.ForMessage($tag$, $type_name$.Parser);\n"); + " = "); + // Don't want to duplicate the codec code here... maybe we should have a + // "create single field generator for this repeated field" + // function, but it doesn't seem worth it for just this. + if (IsWrapperType(descriptor_)) { + scoped_ptr<FieldGeneratorBase> single_generator(new WrapperFieldGenerator(descriptor_, fieldOrdinal_)); + single_generator->GenerateCodecCode(printer); + } else { + scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_)); + single_generator->GenerateCodecCode(printer); + } + printer->Print(";\n"); printer->Print( variables_, "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc new file mode 100644 index 00000000..75ef5e50 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -0,0 +1,209 @@ +// 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. + +#include <sstream> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/plugin.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> + +#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING && + wrapped_field->type() != FieldDescriptor::TYPE_BYTES; + if (is_value_type) { + variables_["nonnullable_type_name"] = type_name(wrapped_field); + } +} + +WrapperFieldGenerator::~WrapperFieldGenerator() { +} + +void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = "); + GenerateCodecCode(printer); + printer->Print( + variables_, + ";\n" + "private $type_name$ $name$_;\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + " set {\n" + " pb::Freezable.CheckMutable(this);\n" + " $name$_ = value;\n" + " }\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$has_property_check$) {\n" + " if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n" + " $property_name$ = other.$property_name$;\n" + " }\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$ value = _single_$name$_codec.Read(input);\n" + "if ($has_not_property_check$ || value != $default_value$) {\n" + " $property_name$ = value;\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n" + "}\n"); +} + +void WrapperFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); +} + +void WrapperFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if ($property_name$ != other.$property_name$) return false;\n"); +} + +void WrapperFieldGenerator::WriteToString(io::Printer* printer) { + // TODO: Implement if we ever actually need it... +} + +void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$property_name$;\n"); +} + +void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) { + if (is_value_type) { + printer->Print( + variables_, + "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)"); + } else { + printer->Print( + variables_, + "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)"); + } +} + +WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : WrapperFieldGenerator(descriptor, fieldOrdinal) { + SetCommonOneofFieldVariables(&variables_); +} + +WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() { +} + +void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { + // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field. + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = "); + GenerateCodecCode(printer); + printer->Print(";\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n" + " set {\n" + " pb::Freezable.CheckMutable(this);\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" + "}\n"); +} + +void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$property_name$ = _oneof_$name$_codec.Read(input);\n"); +} + +void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + // TODO: I suspect this is wrong... + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" + "}\n"); +} + +void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + // TODO: I suspect this is wrong... + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n" + "}\n"); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h new file mode 100644 index 00000000..6e2414af --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h @@ -0,0 +1,85 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ + +#include <string> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/csharp/csharp_field_base.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class WrapperFieldGenerator : public FieldGeneratorBase { + public: + WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~WrapperFieldGenerator(); + + virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); + + private: + bool is_value_type; // True for int32 etc; false for bytes and string + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperFieldGenerator); +}; + +class WrapperOneofFieldGenerator : public WrapperFieldGenerator { + public: + WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~WrapperOneofFieldGenerator(); + + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperOneofFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ diff --git a/src/google/protobuf/unittest_well_known_types.proto b/src/google/protobuf/unittest_well_known_types.proto index e157260e..2cb7775c 100644 --- a/src/google/protobuf/unittest_well_known_types.proto +++ b/src/google/protobuf/unittest_well_known_types.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package protobuf_unittest; +option csharp_namespace = "Google.Protobuf.TestProtos"; option java_multiple_files = true; option java_package = "com.google.protobuf.test"; @@ -17,6 +18,8 @@ import "google/protobuf/type.proto"; import "google/protobuf/wrappers.proto"; // Test that we can include all well-known types. +// Each wrapper type is included separately, as languages +// map handle different wrappers in different ways. message TestWellKnownTypes { google.protobuf.Any any_field = 1; google.protobuf.Api api_field = 2; @@ -27,5 +30,83 @@ message TestWellKnownTypes { google.protobuf.Struct struct_field = 7; google.protobuf.Timestamp timestamp_field = 8; google.protobuf.Type type_field = 9; - google.protobuf.Int32Value int32_field = 10; + google.protobuf.DoubleValue double_field = 10; + google.protobuf.FloatValue float_field = 11; + google.protobuf.Int64Value int64_field = 12; + google.protobuf.UInt64Value uint64_field = 13; + google.protobuf.Int32Value int32_field = 14; + google.protobuf.UInt32Value uint32_field = 15; + google.protobuf.BoolValue bool_field = 16; + google.protobuf.StringValue string_field = 17; + google.protobuf.BytesValue bytes_field = 18; +} + +// A repeated field for each well-known type. +message RepeatedWellKnownTypes { + repeated google.protobuf.Any any_field = 1; + repeated google.protobuf.Api api_field = 2; + repeated google.protobuf.Duration duration_field = 3; + repeated google.protobuf.Empty empty_field = 4; + repeated google.protobuf.FieldMask field_mask_field = 5; + repeated google.protobuf.SourceContext source_context_field = 6; + repeated google.protobuf.Struct struct_field = 7; + repeated google.protobuf.Timestamp timestamp_field = 8; + repeated google.protobuf.Type type_field = 9; + // These don't actually make a lot of sense, but they're not prohibited... + repeated google.protobuf.DoubleValue double_field = 10; + repeated google.protobuf.FloatValue float_field = 11; + repeated google.protobuf.Int64Value int64_field = 12; + repeated google.protobuf.UInt64Value uint64_field = 13; + repeated google.protobuf.Int32Value int32_field = 14; + repeated google.protobuf.UInt32Value uint32_field = 15; + repeated google.protobuf.BoolValue bool_field = 16; + repeated google.protobuf.StringValue string_field = 17; + repeated google.protobuf.BytesValue bytes_field = 18; +} + +message OneofWellKnownTypes { + oneof oneof_field { + google.protobuf.Any any_field = 1; + google.protobuf.Api api_field = 2; + google.protobuf.Duration duration_field = 3; + google.protobuf.Empty empty_field = 4; + google.protobuf.FieldMask field_mask_field = 5; + google.protobuf.SourceContext source_context_field = 6; + google.protobuf.Struct struct_field = 7; + google.protobuf.Timestamp timestamp_field = 8; + google.protobuf.Type type_field = 9; + google.protobuf.DoubleValue double_field = 10; + google.protobuf.FloatValue float_field = 11; + google.protobuf.Int64Value int64_field = 12; + google.protobuf.UInt64Value uint64_field = 13; + google.protobuf.Int32Value int32_field = 14; + google.protobuf.UInt32Value uint32_field = 15; + google.protobuf.BoolValue bool_field = 16; + google.protobuf.StringValue string_field = 17; + google.protobuf.BytesValue bytes_field = 18; + } +} + +// A map field for each well-known type. We only +// need to worry about the value part of the map being the +// well-known types, as messages can't be map keys. +message MapWellKnownTypes { + map<int32,google.protobuf.Any> any_field = 1; + map<int32,google.protobuf.Api> api_field = 2; + map<int32,google.protobuf.Duration> duration_field = 3; + map<int32,google.protobuf.Empty> empty_field = 4; + map<int32,google.protobuf.FieldMask> field_mask_field = 5; + map<int32,google.protobuf.SourceContext> source_context_field = 6; + map<int32,google.protobuf.Struct> struct_field = 7; + map<int32,google.protobuf.Timestamp> timestamp_field = 8; + map<int32,google.protobuf.Type> type_field = 9; + map<int32,google.protobuf.DoubleValue> double_field = 10; + map<int32,google.protobuf.FloatValue> float_field = 11; + map<int32,google.protobuf.Int64Value> int64_field = 12; + map<int32,google.protobuf.UInt64Value> uint64_field = 13; + map<int32,google.protobuf.Int32Value> int32_field = 14; + map<int32,google.protobuf.UInt32Value> uint32_field = 15; + map<int32,google.protobuf.BoolValue> bool_field = 16; + map<int32,google.protobuf.StringValue> string_field = 17; + map<int32,google.protobuf.BytesValue> bytes_field = 18; } |