First part of implementing wrapper types. Not ready yet!

pull/611/head
Jon Skeet 10 years ago
parent 7ea5239792
commit b2ac868493
  1. 4
      BUILD
  2. 1
      cmake/libprotoc.cmake
  3. 3
      csharp/generate_protos.sh
  4. 2
      csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  5. 2335
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestWellKnownTypes.cs
  6. 85
      csharp/src/ProtocolBuffers.Test/WellKnownTypes/WrappersTest.cs
  7. 4
      src/Makefile.am
  8. 12
      src/google/protobuf/compiler/csharp/csharp_field_base.cc
  9. 39
      src/google/protobuf/compiler/csharp/csharp_helpers.cc
  10. 9
      src/google/protobuf/compiler/csharp/csharp_helpers.h
  11. 210
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
  12. 86
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
  13. 83
      src/google/protobuf/unittest_well_known_types.proto

@ -162,10 +162,10 @@ cc_library(
"src/google/protobuf/compiler/cpp/cpp_string_field.cc",
"src/google/protobuf/compiler/csharp/csharp_enum.cc",
"src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
"src/google/protobuf/compiler/csharp/csharp_extension.cc",
"src/google/protobuf/compiler/csharp/csharp_field_base.cc",
"src/google/protobuf/compiler/csharp/csharp_generator.cc",
"src/google/protobuf/compiler/csharp/csharp_helpers.cc",
"src/google/protobuf/compiler/csharp/csharp_map_field.cc",
"src/google/protobuf/compiler/csharp/csharp_message.cc",
"src/google/protobuf/compiler/csharp/csharp_message_field.cc",
"src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
@ -174,7 +174,7 @@ cc_library(
"src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
"src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
"src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc",
"src/google/protobuf/compiler/csharp/csharp_writer.cc",
"src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
"src/google/protobuf/compiler/java/java_context.cc",
"src/google/protobuf/compiler/java/java_doc_comment.cc",
"src/google/protobuf/compiler/java/java_enum.cc",

@ -28,6 +28,7 @@ set(libprotoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_context.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment.cc
${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum.cc

@ -58,7 +58,8 @@ $PROTOC -Isrc --csharp_out=csharp/src/ProtocolBuffers.Test/TestProtos \
src/google/protobuf/map_unittest_proto3.proto \
src/google/protobuf/unittest_proto3.proto \
src/google/protobuf/unittest_import_proto3.proto \
src/google/protobuf/unittest_import_public_proto3.proto
src/google/protobuf/unittest_import_public_proto3.proto \
src/google/protobuf/unittest_well_known_types.proto
$PROTOC -Icsharp/protos/extest --csharp_out=csharp/src/ProtocolBuffers.Test/TestProtos \

@ -93,6 +93,8 @@
<Compile Include="IssuesTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestCornerCases.cs" />
<Compile Include="TestProtos\UnittestWellKnownTypes.cs" />
<Compile Include="WellKnownTypes\WrappersTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProtocolBuffers\ProtocolBuffers.csproj">

@ -0,0 +1,85 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using Google.Protobuf.TestProtos;
using NUnit.Framework;
namespace Google.Protobuf.WellKnownTypes
{
public class WrappersTest
{
[Test]
public void NullIsDefault()
{
var message = new TestWellKnownTypes();
Assert.IsNull(message.StringField);
Assert.IsNull(message.BytesField);
Assert.IsNull(message.BoolField);
Assert.IsNull(message.FloatField);
Assert.IsNull(message.DoubleField);
Assert.IsNull(message.Int32Field);
Assert.IsNull(message.Int64Field);
Assert.IsNull(message.Uint32Field);
Assert.IsNull(message.Uint64Field);
}
[Test]
public void NonNullDefaultIsPreservedThroughSerialization()
{
var message = new TestWellKnownTypes
{
StringField = "",
BytesField = ByteString.Empty,
BoolField = false,
FloatField = 0f,
DoubleField = 0d,
Int32Field = 0,
Int64Field = 0,
Uint32Field = 0,
Uint64Field = 0
};
var bytes = message.ToByteArray();
var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
Assert.AreEqual("", message.StringField);
Assert.AreEqual(ByteString.Empty, message.BytesField);
Assert.AreEqual(false, message.BoolField);
Assert.AreEqual(0f, message.FloatField);
Assert.AreEqual(0d, message.DoubleField);
Assert.AreEqual(0, message.Int32Field);
Assert.AreEqual(0L, message.Int64Field);
Assert.AreEqual(0U, message.Uint32Field);
Assert.AreEqual(0UL, message.Uint64Field);
}
}
}

@ -441,7 +441,9 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/csharp/csharp_source_generator_base.cc \
google/protobuf/compiler/csharp/csharp_source_generator_base.h \
google/protobuf/compiler/csharp/csharp_umbrella_class.cc \
google/protobuf/compiler/csharp/csharp_umbrella_class.h
google/protobuf/compiler/csharp/csharp_umbrella_class.h \
google/protobuf/compiler/csharp/csharp_wrapper_field.cc \
google/protobuf/compiler/csharp/csharp_wrapper_field.h
bin_PROGRAMS = protoc
protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la

@ -168,6 +168,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";

@ -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);
}
}
}
}

@ -120,6 +120,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

@ -0,0 +1,210 @@
// 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";
variables_["message_type_name"] = GetClassName(descriptor->message_type());
const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING &&
wrapped_field->type() != FieldDescriptor::TYPE_BYTES;
variables_["deref"] = is_value_type ? ".Value" : "";
// This will always be a single byte, because it's always field 1.
variables_["message_tag_bytes"] = SimpleItoa(FixedMakeTag(wrapped_field));
}
WrapperFieldGenerator::~WrapperFieldGenerator() {
}
void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
// Back the underlying property with an underlying message. This isn't efficient,
// but it makes it easier to be compliant with what platforms which don't support wrapper
// types would do. Currently, each time the value is changed, we create a new instance.
// With suitable care to avoid aliasing, we could probably check whether or not we've already
// got an instance, and simply mutate the existing one.
printer->Print(
variables_,
"private $message_type_name$ $name$_;\n");
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $name$_ == null ? ($type_name$) null : $name$_.Value; }\n"
" set {\n"
" pb::Freezable.CheckMutable(this);\n"
" $name$_ = value == null ? null : new $message_type_name$ { Value = value$deref$ };\n"
" }\n"
"}\n");
}
void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"if (other.$has_property_check$) {\n"
" if ($has_not_property_check$) {\n"
" $name$_ = new $message_type_name$();\n"
" }\n"
" $name$_.MergeFrom(other.$name$_);\n"
"}\n");
}
void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_not_property_check$) {\n"
" $name$_ = new $message_type_name$();\n"
"}\n"
"input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
}
void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteMessage($name$_);\n"
"}\n");
}
void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($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) {
// This will effectively perform a deep clone - it will create a new
// underlying message if necessary
printer->Print(variables_,
"$property_name$ = other.$property_name$;\n");
}
void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
printer->Print(
variables_,
"pb::FieldCodec.ForWrapperType<$type_name$, $message_type_name$>($tag$, $message_type_name$.Parser)");
}
WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal)
: WrapperFieldGenerator(descriptor, fieldOrdinal) {
SetCommonOneofFieldVariables(&variables_);
}
WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() {
}
void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? (($message_type_name$) $oneof_name$_).Value : ($type_name$) null; }\n"
" set {\n"
" pb::Freezable.CheckMutable(this);\n"
" $oneof_name$_ = value == null ? null : new $message_type_name$ { Value = value$deref$ };\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_,
"$message_type_name$ subBuilder = new $message_type_name$();\n"
"if ($has_property_check$) {\n"
" subBuilder.MergeFrom(($message_type_name$) $oneof_name$_);\n"
"}\n"
"input.ReadMessage(subBuilder);\n"
// Don't set the property, which would create a new and equivalent message; just set the two fields.
"$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
"$oneof_name$_ = subBuilder;\n");
}
void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.WriteRawTag($tag_bytes$);\n"
" output.WriteMessage(($message_type_name$) $oneof_name$_);\n"
"}\n");
}
void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize((($message_type_name$) $oneof_name$_));\n"
"}\n");
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google

@ -0,0 +1,86 @@
// 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__

@ -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;
// TODO: Do these even make sense? Should they be 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;
}

Loading…
Cancel
Save