diff options
Diffstat (limited to 'NorthstarDedicatedTest/include/protobuf/compiler/ruby')
14 files changed, 1177 insertions, 0 deletions
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code.proto new file mode 100644 index 00000000..70ec9f17 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code.proto @@ -0,0 +1,70 @@ +syntax = "proto3"; + +package A.B.C; + +import "ruby_generated_code_proto2_import.proto"; + +message TestMessage { + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + bool optional_bool = 5; + double optional_double = 6; + float optional_float = 7; + string optional_string = 8; + bytes optional_bytes = 9; + TestEnum optional_enum = 10; + TestMessage optional_msg = 11; + TestImportedMessage optional_proto2_submessage = 12; + + repeated int32 repeated_int32 = 21; + repeated int64 repeated_int64 = 22; + repeated uint32 repeated_uint32 = 23; + repeated uint64 repeated_uint64 = 24; + repeated bool repeated_bool = 25; + repeated double repeated_double = 26; + repeated float repeated_float = 27; + repeated string repeated_string = 28; + repeated bytes repeated_bytes = 29; + repeated TestEnum repeated_enum = 30; + repeated TestMessage repeated_msg = 31; + + oneof my_oneof { + int32 oneof_int32 = 41; + int64 oneof_int64 = 42; + uint32 oneof_uint32 = 43; + uint64 oneof_uint64 = 44; + bool oneof_bool = 45; + double oneof_double = 46; + float oneof_float = 47; + string oneof_string = 48; + bytes oneof_bytes = 49; + TestEnum oneof_enum = 50; + TestMessage oneof_msg = 51; + } + + map<int32, string> map_int32_string = 61; + map<int64, string> map_int64_string = 62; + map<uint32, string> map_uint32_string = 63; + map<uint64, string> map_uint64_string = 64; + map<bool, string> map_bool_string = 65; + map<string, string> map_string_string = 66; + map<string, TestMessage> map_string_msg = 67; + map<string, TestEnum> map_string_enum = 68; + map<string, int32> map_string_int32 = 69; + map<string, bool> map_string_bool = 70; + + message NestedMessage { + int32 foo = 1; + } + + NestedMessage nested_message = 80; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_pb.rb new file mode 100644 index 00000000..256ac7c1 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_pb.rb @@ -0,0 +1,79 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_code.proto + +require 'google/protobuf' + +require 'ruby_generated_code_proto2_import_pb' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_code.proto", :syntax => :proto3) do + add_message "A.B.C.TestMessage" do + optional :optional_int32, :int32, 1 + optional :optional_int64, :int64, 2 + optional :optional_uint32, :uint32, 3 + optional :optional_uint64, :uint64, 4 + optional :optional_bool, :bool, 5 + optional :optional_double, :double, 6 + optional :optional_float, :float, 7 + optional :optional_string, :string, 8 + optional :optional_bytes, :bytes, 9 + optional :optional_enum, :enum, 10, "A.B.C.TestEnum" + optional :optional_msg, :message, 11, "A.B.C.TestMessage" + optional :optional_proto2_submessage, :message, 12, "A.B.C.TestImportedMessage" + repeated :repeated_int32, :int32, 21 + repeated :repeated_int64, :int64, 22 + repeated :repeated_uint32, :uint32, 23 + repeated :repeated_uint64, :uint64, 24 + repeated :repeated_bool, :bool, 25 + repeated :repeated_double, :double, 26 + repeated :repeated_float, :float, 27 + repeated :repeated_string, :string, 28 + repeated :repeated_bytes, :bytes, 29 + repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" + repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" + map :map_int32_string, :int32, :string, 61 + map :map_int64_string, :int64, :string, 62 + map :map_uint32_string, :uint32, :string, 63 + map :map_uint64_string, :uint64, :string, 64 + map :map_bool_string, :bool, :string, 65 + map :map_string_string, :string, :string, 66 + map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage" + map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum" + map :map_string_int32, :string, :int32, 69 + map :map_string_bool, :string, :bool, 70 + optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" + oneof :my_oneof do + optional :oneof_int32, :int32, 41 + optional :oneof_int64, :int64, 42 + optional :oneof_uint32, :uint32, 43 + optional :oneof_uint64, :uint64, 44 + optional :oneof_bool, :bool, 45 + optional :oneof_double, :double, 46 + optional :oneof_float, :float, 47 + optional :oneof_string, :string, 48 + optional :oneof_bytes, :bytes, 49 + optional :oneof_enum, :enum, 50, "A.B.C.TestEnum" + optional :oneof_msg, :message, 51, "A.B.C.TestMessage" + end + end + add_message "A.B.C.TestMessage.NestedMessage" do + optional :foo, :int32, 1 + end + add_enum "A.B.C.TestEnum" do + value :Default, 0 + value :A, 1 + value :B, 2 + value :C, 3 + end + end +end + +module A + module B + module C + TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass + TestMessage::NestedMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass + TestEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule + end + end +end diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2.proto new file mode 100644 index 00000000..ea7f7836 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2.proto @@ -0,0 +1,71 @@ +syntax = "proto2"; + +package A.B.C; + +import "ruby_generated_code_proto2_import.proto"; + +message TestMessage { + optional int32 optional_int32 = 1 [default = 1]; + optional int64 optional_int64 = 2 [default = 2]; + optional uint32 optional_uint32 = 3 [default = 3]; + optional uint64 optional_uint64 = 4 [default = 4]; + optional bool optional_bool = 5 [default = true]; + optional double optional_double = 6 [default = 6.0]; + optional float optional_float = 7 [default = 7.0]; + optional string optional_string = 8 [default = "default str"]; + optional bytes optional_bytes = 9 [default = "\0\1\2\100fubar"]; + optional TestEnum optional_enum = 10 [default = A]; + optional TestMessage optional_msg = 11; + optional TestImportedMessage optional_proto2_submessage = 12; + + repeated int32 repeated_int32 = 21; + repeated int64 repeated_int64 = 22; + repeated uint32 repeated_uint32 = 23; + repeated uint64 repeated_uint64 = 24; + repeated bool repeated_bool = 25; + repeated double repeated_double = 26; + repeated float repeated_float = 27; + repeated string repeated_string = 28; + repeated bytes repeated_bytes = 29; + repeated TestEnum repeated_enum = 30; + repeated TestMessage repeated_msg = 31; + + required int32 required_int32 = 41; + required int64 required_int64 = 42; + required uint32 required_uint32 = 43; + required uint64 required_uint64 = 44; + required bool required_bool = 45; + required double required_double = 46; + required float required_float = 47; + required string required_string = 48; + required bytes required_bytes = 49; + required TestEnum required_enum = 50; + required TestMessage required_msg = 51; + + oneof my_oneof { + int32 oneof_int32 = 61; + int64 oneof_int64 = 62; + uint32 oneof_uint32 = 63; + uint64 oneof_uint64 = 64; + bool oneof_bool = 65; + double oneof_double = 66; + float oneof_float = 67; + string oneof_string = 68; + bytes oneof_bytes = 69; + TestEnum oneof_enum = 70; + TestMessage oneof_msg = 71; + } + + message NestedMessage { + optional int32 foo = 1; + } + + optional NestedMessage nested_message = 80; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto new file mode 100644 index 00000000..9ec07381 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +package A.B.C; + +message TestImportedMessage {} diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb new file mode 100644 index 00000000..44d31969 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb @@ -0,0 +1,80 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_code_proto2.proto + +require 'google/protobuf' + +require 'ruby_generated_code_proto2_import_pb' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_code_proto2.proto", :syntax => :proto2) do + add_message "A.B.C.TestMessage" do + optional :optional_int32, :int32, 1, default: 1 + optional :optional_int64, :int64, 2, default: 2 + optional :optional_uint32, :uint32, 3, default: 3 + optional :optional_uint64, :uint64, 4, default: 4 + optional :optional_bool, :bool, 5, default: true + optional :optional_double, :double, 6, default: 6 + optional :optional_float, :float, 7, default: 7 + optional :optional_string, :string, 8, default: "default str" + optional :optional_bytes, :bytes, 9, default: "\x00\x01\x02\x40\x66\x75\x62\x61\x72".force_encoding("ASCII-8BIT") + optional :optional_enum, :enum, 10, "A.B.C.TestEnum", default: 1 + optional :optional_msg, :message, 11, "A.B.C.TestMessage" + optional :optional_proto2_submessage, :message, 12, "A.B.C.TestImportedMessage" + repeated :repeated_int32, :int32, 21 + repeated :repeated_int64, :int64, 22 + repeated :repeated_uint32, :uint32, 23 + repeated :repeated_uint64, :uint64, 24 + repeated :repeated_bool, :bool, 25 + repeated :repeated_double, :double, 26 + repeated :repeated_float, :float, 27 + repeated :repeated_string, :string, 28 + repeated :repeated_bytes, :bytes, 29 + repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" + repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" + required :required_int32, :int32, 41 + required :required_int64, :int64, 42 + required :required_uint32, :uint32, 43 + required :required_uint64, :uint64, 44 + required :required_bool, :bool, 45 + required :required_double, :double, 46 + required :required_float, :float, 47 + required :required_string, :string, 48 + required :required_bytes, :bytes, 49 + required :required_enum, :enum, 50, "A.B.C.TestEnum" + required :required_msg, :message, 51, "A.B.C.TestMessage" + optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" + oneof :my_oneof do + optional :oneof_int32, :int32, 61 + optional :oneof_int64, :int64, 62 + optional :oneof_uint32, :uint32, 63 + optional :oneof_uint64, :uint64, 64 + optional :oneof_bool, :bool, 65 + optional :oneof_double, :double, 66 + optional :oneof_float, :float, 67 + optional :oneof_string, :string, 68 + optional :oneof_bytes, :bytes, 69 + optional :oneof_enum, :enum, 70, "A.B.C.TestEnum" + optional :oneof_msg, :message, 71, "A.B.C.TestMessage" + end + end + add_message "A.B.C.TestMessage.NestedMessage" do + optional :foo, :int32, 1 + end + add_enum "A.B.C.TestEnum" do + value :Default, 0 + value :A, 1 + value :B, 2 + value :C, 3 + end + end +end + +module A + module B + module C + TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass + TestMessage::NestedMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass + TestEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule + end + end +end diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto new file mode 100644 index 00000000..8d7c948a --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package one.two.a_three; + +option ruby_package = "A::B::C"; + +message Four { + string a_string = 1; +} diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto new file mode 100644 index 00000000..7a0d2608 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package one.two.a_three.and; + +option ruby_package = "AA.BB.CC"; + +message Four { + string another_string = 1; +} diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb new file mode 100644 index 00000000..cdbbe891 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb @@ -0,0 +1,20 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_pkg_explicit_legacy.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_pkg_explicit_legacy.proto", :syntax => :proto3) do + add_message "one.two.a_three.and.Four" do + optional :another_string, :string, 1 + end + end +end + +module AA + module BB + module CC + Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.and.Four").msgclass + end + end +end diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb new file mode 100644 index 00000000..e6d47011 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb @@ -0,0 +1,20 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_pkg_explicit.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_pkg_explicit.proto", :syntax => :proto3) do + add_message "one.two.a_three.Four" do + optional :a_string, :string, 1 + end + end +end + +module A + module B + module C + Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.Four").msgclass + end + end +end diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto new file mode 100644 index 00000000..544db64d --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package one.two.a_three; + +message Four { + string a_string = 1; +} diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb new file mode 100644 index 00000000..1ac0ef7a --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb @@ -0,0 +1,20 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_pkg_implicit.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_pkg_implicit.proto", :syntax => :proto3) do + add_message "one.two.a_three.Four" do + optional :a_string, :string, 1 + end + end +end + +module One + module Two + module AThree + Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.Four").msgclass + end + end +end diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.cc new file mode 100644 index 00000000..7d6d5032 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.cc @@ -0,0 +1,575 @@ +// 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 <iomanip> +#include <sstream> + +#include <compiler/code_generator.h> +#include <compiler/plugin.h> +#include <descriptor.h> +#include <descriptor.pb.h> +#include <io/printer.h> +#include <io/zero_copy_stream.h> + +#include <compiler/ruby/ruby_generator.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace ruby { + +// Forward decls. +template <class numeric_type> +std::string NumberToString(numeric_type value); +std::string GetRequireName(const std::string& proto_file); +std::string LabelForField(FieldDescriptor* field); +std::string TypeName(FieldDescriptor* field); +bool GenerateMessage(const Descriptor* message, io::Printer* printer, + std::string* error); +void GenerateEnum(const EnumDescriptor* en, io::Printer* printer); +void GenerateMessageAssignment(const std::string& prefix, + const Descriptor* message, io::Printer* printer); +void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en, + io::Printer* printer); +std::string DefaultValueForField(const FieldDescriptor* field); + +template<class numeric_type> +std::string NumberToString(numeric_type value) { + std::ostringstream os; + os << value; + return os.str(); +} + +std::string GetRequireName(const std::string& proto_file) { + int lastindex = proto_file.find_last_of("."); + return proto_file.substr(0, lastindex) + "_pb"; +} + +std::string GetOutputFilename(const std::string& proto_file) { + return GetRequireName(proto_file) + ".rb"; +} + +std::string LabelForField(const FieldDescriptor* field) { + if (field->has_optional_keyword() && + field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + return "proto3_optional"; + } + switch (field->label()) { + case FieldDescriptor::LABEL_OPTIONAL: return "optional"; + case FieldDescriptor::LABEL_REQUIRED: return "required"; + case FieldDescriptor::LABEL_REPEATED: return "repeated"; + default: assert(false); return ""; + } +} + +std::string TypeName(const FieldDescriptor* field) { + switch (field->type()) { + case FieldDescriptor::TYPE_INT32: return "int32"; + case FieldDescriptor::TYPE_INT64: return "int64"; + case FieldDescriptor::TYPE_UINT32: return "uint32"; + case FieldDescriptor::TYPE_UINT64: return "uint64"; + case FieldDescriptor::TYPE_SINT32: return "sint32"; + case FieldDescriptor::TYPE_SINT64: return "sint64"; + case FieldDescriptor::TYPE_FIXED32: return "fixed32"; + case FieldDescriptor::TYPE_FIXED64: return "fixed64"; + case FieldDescriptor::TYPE_SFIXED32: return "sfixed32"; + case FieldDescriptor::TYPE_SFIXED64: return "sfixed64"; + case FieldDescriptor::TYPE_DOUBLE: return "double"; + case FieldDescriptor::TYPE_FLOAT: return "float"; + case FieldDescriptor::TYPE_BOOL: return "bool"; + case FieldDescriptor::TYPE_ENUM: return "enum"; + case FieldDescriptor::TYPE_STRING: return "string"; + case FieldDescriptor::TYPE_BYTES: return "bytes"; + case FieldDescriptor::TYPE_MESSAGE: return "message"; + case FieldDescriptor::TYPE_GROUP: return "group"; + default: assert(false); return ""; + } +} + +std::string StringifySyntax(FileDescriptor::Syntax syntax) { + switch (syntax) { + case FileDescriptor::SYNTAX_PROTO2: + return "proto2"; + case FileDescriptor::SYNTAX_PROTO3: + return "proto3"; + case FileDescriptor::SYNTAX_UNKNOWN: + default: + GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports " + "proto2 and proto3 syntax."; + return ""; + } +} + +std::string DefaultValueForField(const FieldDescriptor* field) { + switch(field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return NumberToString(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_INT64: + return NumberToString(field->default_value_int64()); + case FieldDescriptor::CPPTYPE_UINT32: + return NumberToString(field->default_value_uint32()); + case FieldDescriptor::CPPTYPE_UINT64: + return NumberToString(field->default_value_uint64()); + case FieldDescriptor::CPPTYPE_FLOAT: + return NumberToString(field->default_value_float()); + case FieldDescriptor::CPPTYPE_DOUBLE: + return NumberToString(field->default_value_double()); + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "true" : "false"; + case FieldDescriptor::CPPTYPE_ENUM: + return NumberToString(field->default_value_enum()->number()); + case FieldDescriptor::CPPTYPE_STRING: { + std::ostringstream os; + std::string default_str = field->default_value_string(); + + if (field->type() == FieldDescriptor::TYPE_STRING) { + os << "\"" << default_str << "\""; + } else if (field->type() == FieldDescriptor::TYPE_BYTES) { + os << "\""; + + os.fill('0'); + for (int i = 0; i < default_str.length(); ++i) { + // Write the hex form of each byte. + os << "\\x" << std::hex << std::setw(2) + << ((uint16)((unsigned char)default_str.at(i))); + } + os << "\".force_encoding(\"ASCII-8BIT\")"; + } + + return os.str(); + } + default: assert(false); return ""; + } +} + +void GenerateField(const FieldDescriptor* field, io::Printer* printer) { + if (field->is_map()) { + const FieldDescriptor* key_field = + field->message_type()->FindFieldByNumber(1); + const FieldDescriptor* value_field = + field->message_type()->FindFieldByNumber(2); + + printer->Print( + "map :$name$, :$key_type$, :$value_type$, $number$", + "name", field->name(), + "key_type", TypeName(key_field), + "value_type", TypeName(value_field), + "number", NumberToString(field->number())); + + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->message_type()->full_name()); + } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } + } else { + + printer->Print( + "$label$ :$name$, ", + "label", LabelForField(field), + "name", field->name()); + printer->Print( + ":$type$, $number$", + "type", TypeName(field), + "number", NumberToString(field->number())); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"", + "subtype", field->message_type()->full_name()); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"", + "subtype", field->enum_type()->full_name()); + } + + if (field->has_default_value()) { + printer->Print(", default: $default$", "default", + DefaultValueForField(field)); + } + + if (field->has_json_name()) { + printer->Print(", json_name: \"$json_name$\"", "json_name", + field->json_name()); + } + + printer->Print("\n"); + } +} + +void GenerateOneof(const OneofDescriptor* oneof, io::Printer* printer) { + printer->Print( + "oneof :$name$ do\n", + "name", oneof->name()); + printer->Indent(); + + for (int i = 0; i < oneof->field_count(); i++) { + const FieldDescriptor* field = oneof->field(i); + GenerateField(field, printer); + } + + printer->Outdent(); + printer->Print("end\n"); +} + +bool GenerateMessage(const Descriptor* message, io::Printer* printer, + std::string* error) { + if (message->extension_range_count() > 0 || message->extension_count() > 0) { + GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files."; + } + + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return true; + } + + printer->Print( + "add_message \"$name$\" do\n", + "name", message->full_name()); + printer->Indent(); + + for (int i = 0; i < message->field_count(); i++) { + const FieldDescriptor* field = message->field(i); + if (!field->real_containing_oneof()) { + GenerateField(field, printer); + } + } + + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + GenerateOneof(oneof, printer); + } + + printer->Outdent(); + printer->Print("end\n"); + + for (int i = 0; i < message->nested_type_count(); i++) { + if (!GenerateMessage(message->nested_type(i), printer, error)) { + return false; + } + } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateEnum(message->enum_type(i), printer); + } + + return true; +} + +void GenerateEnum(const EnumDescriptor* en, io::Printer* printer) { + printer->Print( + "add_enum \"$name$\" do\n", + "name", en->full_name()); + printer->Indent(); + + for (int i = 0; i < en->value_count(); i++) { + const EnumValueDescriptor* value = en->value(i); + printer->Print( + "value :$name$, $number$\n", + "name", value->name(), + "number", NumberToString(value->number())); + } + + printer->Outdent(); + printer->Print( + "end\n"); +} + +// Locale-agnostic utility functions. +bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; } + +bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; } + +bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); } + +char UpperChar(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } + + +// Package names in protobuf are snake_case by convention, but Ruby module +// names must be PascalCased. +// +// foo_bar_baz -> FooBarBaz +std::string PackageToModule(const std::string& name) { + bool next_upper = true; + std::string result; + result.reserve(name.size()); + + for (int i = 0; i < name.size(); i++) { + if (name[i] == '_') { + next_upper = true; + } else { + if (next_upper) { + result.push_back(UpperChar(name[i])); + } else { + result.push_back(name[i]); + } + next_upper = false; + } + } + + return result; +} + +// Class and enum names in protobuf should be PascalCased by convention, but +// since there is nothing enforcing this we need to ensure that they are valid +// Ruby constants. That mainly means making sure that the first character is +// an upper-case letter. +std::string RubifyConstant(const std::string& name) { + std::string ret = name; + if (!ret.empty()) { + if (IsLower(ret[0])) { + // If it starts with a lowercase letter, capitalize it. + ret[0] = UpperChar(ret[0]); + } else if (!IsAlpha(ret[0])) { + // Otherwise (e.g. if it begins with an underscore), we need to come up + // with some prefix that starts with a capital letter. We could be smarter + // here, e.g. try to strip leading underscores, but this may cause other + // problems if the user really intended the name. So let's just prepend a + // well-known suffix. + ret = "PB_" + ret; + } + } + + return ret; +} + +void GenerateMessageAssignment(const std::string& prefix, + const Descriptor* message, + io::Printer* printer) { + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return; + } + + printer->Print( + "$prefix$$name$ = ", + "prefix", prefix, + "name", RubifyConstant(message->name())); + printer->Print( + "::Google::Protobuf::DescriptorPool.generated_pool." + "lookup(\"$full_name$\").msgclass\n", + "full_name", message->full_name()); + + std::string nested_prefix = prefix + RubifyConstant(message->name()) + "::"; + for (int i = 0; i < message->nested_type_count(); i++) { + GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer); + } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateEnumAssignment(nested_prefix, message->enum_type(i), printer); + } +} + +void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en, + io::Printer* printer) { + printer->Print( + "$prefix$$name$ = ", + "prefix", prefix, + "name", RubifyConstant(en->name())); + printer->Print( + "::Google::Protobuf::DescriptorPool.generated_pool." + "lookup(\"$full_name$\").enummodule\n", + "full_name", en->full_name()); +} + +int GeneratePackageModules(const FileDescriptor* file, io::Printer* printer) { + int levels = 0; + bool need_change_to_module = true; + std::string package_name; + + // Determine the name to use in either format: + // proto package: one.two.three + // option ruby_package: One::Two::Three + if (file->options().has_ruby_package()) { + package_name = file->options().ruby_package(); + + // If :: is in the package use the Ruby formatted name as-is + // -> A::B::C + // otherwise, use the dot separator + // -> A.B.C + if (package_name.find("::") != std::string::npos) { + need_change_to_module = false; + } else { + GOOGLE_LOG(WARNING) << "ruby_package option should be in the form of:" + << " 'A::B::C' and not 'A.B.C'"; + } + } else { + package_name = file->package(); + } + + // Use the appropriate delimiter + std::string delimiter = need_change_to_module ? "." : "::"; + int delimiter_size = need_change_to_module ? 1 : 2; + + // Extract each module name and indent + while (!package_name.empty()) { + size_t dot_index = package_name.find(delimiter); + std::string component; + if (dot_index == std::string::npos) { + component = package_name; + package_name = ""; + } else { + component = package_name.substr(0, dot_index); + package_name = package_name.substr(dot_index + delimiter_size); + } + if (need_change_to_module) { + component = PackageToModule(component); + } + printer->Print( + "module $name$\n", + "name", component); + printer->Indent(); + levels++; + } + return levels; +} + +void EndPackageModules(int levels, io::Printer* printer) { + while (levels > 0) { + levels--; + printer->Outdent(); + printer->Print( + "end\n"); + } +} + +bool GenerateDslDescriptor(const FileDescriptor* file, io::Printer* printer, + std::string* error) { + printer->Print("Google::Protobuf::DescriptorPool.generated_pool.build do\n"); + printer->Indent(); + printer->Print("add_file(\"$filename$\", :syntax => :$syntax$) do\n", + "filename", file->name(), "syntax", + StringifySyntax(file->syntax())); + printer->Indent(); + for (int i = 0; i < file->message_type_count(); i++) { + if (!GenerateMessage(file->message_type(i), printer, error)) { + return false; + } + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnum(file->enum_type(i), printer); + } + printer->Outdent(); + printer->Print("end\n"); + printer->Outdent(); + printer->Print( + "end\n\n"); + return true; +} + +bool GenerateBinaryDescriptor(const FileDescriptor* file, io::Printer* printer, + std::string* error) { + printer->Print( + R"(descriptor_data = File.binread(__FILE__).split("\n__END__\n", 2)[1])"); + printer->Print( + "\nGoogle::Protobuf::DescriptorPool.generated_pool.add_serialized_file(" + "descriptor_data)\n\n"); + return true; +} + +bool GenerateFile(const FileDescriptor* file, io::Printer* printer, + std::string* error) { + printer->Print( + "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "# source: $filename$\n" + "\n", + "filename", file->name()); + + printer->Print("require 'google/protobuf'\n\n"); + + if (file->dependency_count() != 0) { + for (int i = 0; i < file->dependency_count(); i++) { + printer->Print("require '$name$'\n", "name", GetRequireName(file->dependency(i)->name())); + } + printer->Print("\n"); + } + + // TODO: Remove this when ruby supports extensions for proto2 syntax. + if (file->syntax() == FileDescriptor::SYNTAX_PROTO2 && + file->extension_count() > 0) { + GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files."; + } + + bool use_raw_descriptor = file->name() == "google/protobuf/descriptor.proto"; + + if (use_raw_descriptor) { + GenerateBinaryDescriptor(file, printer, error); + } else { + GenerateDslDescriptor(file, printer, error); + } + + int levels = GeneratePackageModules(file, printer); + for (int i = 0; i < file->message_type_count(); i++) { + GenerateMessageAssignment("", file->message_type(i), printer); + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnumAssignment("", file->enum_type(i), printer); + } + EndPackageModules(levels, printer); + + if (use_raw_descriptor) { + printer->Print("\n__END__\n"); + FileDescriptorProto file_proto; + file->CopyTo(&file_proto); + std::string file_data; + file_proto.SerializeToString(&file_data); + printer->Print("$raw_descriptor$", "raw_descriptor", file_data); + } + return true; +} + +bool Generator::Generate( + const FileDescriptor* file, + const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const { + + if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && + file->syntax() != FileDescriptor::SYNTAX_PROTO2) { + *error = "Invalid or unsupported proto syntax"; + return false; + } + + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(GetOutputFilename(file->name()))); + io::Printer printer(output.get(), '$'); + + return GenerateFile(file, &printer, error); +} + +} // namespace ruby +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.h new file mode 100644 index 00000000..e8e6e566 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator.h @@ -0,0 +1,67 @@ +// 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. + +// Generates Ruby code for a given .proto file. + +#ifndef GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ + +#include <string> + +#include <compiler/code_generator.h> + +#include <port_def.inc> + +namespace google { +namespace protobuf { +namespace compiler { +namespace ruby { + +// CodeGenerator implementation for generated Ruby protocol buffer classes. +// If you create your own protocol compiler binary and you want it to support +// Ruby output, you can do so by registering an instance of this +// CodeGenerator with the CommandLineInterface in your main() function. +class PROTOC_EXPORT Generator : public CodeGenerator { + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const override; + uint64_t GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } +}; + +} // namespace ruby +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include <port_undef.inc> + +#endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator_unittest.cc new file mode 100644 index 00000000..cc72c1e6 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -0,0 +1,145 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 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 <memory> +#include <list> + +#include <compiler/ruby/ruby_generator.h> +#include <compiler/command_line_interface.h> +#include <io/zero_copy_stream.h> +#include <io/printer.h> + +#include <testing/googletest.h> +#include <gtest/gtest.h> +#include <testing/file.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace ruby { +namespace { + +std::string FindRubyTestDir() { + return TestSourceDir() + "/google/protobuf/compiler/ruby"; +} + +// This test is a simple golden-file test over the output of the Ruby code +// generator. When we make changes to the Ruby extension and alter the Ruby code +// generator to use those changes, we should (i) manually test the output of the +// code generator with the extension, and (ii) update the golden output above. +// Some day, we may integrate build systems between protoc and the language +// extensions to the point where we can do this test in a more automated way. + +void RubyTest(string proto_file, string import_proto_file = "") { + std::string ruby_tests = FindRubyTestDir(); + + google::protobuf::compiler::CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + + ruby::Generator ruby_generator; + cli.RegisterGenerator("--ruby_out", &ruby_generator, ""); + + // Copy generated_code.proto to the temporary test directory. + std::string test_input; + GOOGLE_CHECK_OK(File::GetContents( + ruby_tests + proto_file + ".proto", + &test_input, + true)); + GOOGLE_CHECK_OK(File::SetContents( + TestTempDir() + proto_file + ".proto", + test_input, + true)); + + // Copy generated_code_import.proto to the temporary test directory. + std::string test_import; + if (!import_proto_file.empty()) { + GOOGLE_CHECK_OK(File::GetContents( + ruby_tests + import_proto_file + ".proto", + &test_import, + true)); + GOOGLE_CHECK_OK(File::SetContents( + TestTempDir() + import_proto_file + ".proto", + test_import, + true)); + } + + // Invoke the proto compiler (we will be inside TestTempDir() at this point). + std::string ruby_out = "--ruby_out=" + TestTempDir(); + std::string proto_path = "--proto_path=" + TestTempDir(); + + std::string proto_target = TestTempDir() + proto_file + ".proto"; + const char* argv[] = { + "protoc", + ruby_out.c_str(), + proto_path.c_str(), + proto_target.c_str(), + }; + + EXPECT_EQ(0, cli.Run(4, argv)); + + // Load the generated output and compare to the expected result. + std::string output; + GOOGLE_CHECK_OK(File::GetContentsAsText( + TestTempDir() + proto_file + "_pb.rb", + &output, + true)); + std::string expected_output; + GOOGLE_CHECK_OK(File::GetContentsAsText( + ruby_tests + proto_file + "_pb.rb", + &expected_output, + true)); + EXPECT_EQ(expected_output, output); +} + +TEST(RubyGeneratorTest, Proto3GeneratorTest) { + RubyTest("/ruby_generated_code", "/ruby_generated_code_proto2_import"); +} + +TEST(RubyGeneratorTest, Proto2GeneratorTest) { + RubyTest("/ruby_generated_code_proto2", "/ruby_generated_code_proto2_import"); +} + +TEST(RubyGeneratorTest, Proto3ImplicitPackageTest) { + RubyTest("/ruby_generated_pkg_implicit"); +} + +TEST(RubyGeneratorTest, Proto3ExplictPackageTest) { + RubyTest("/ruby_generated_pkg_explicit"); +} + +TEST(RubyGeneratorTest, Proto3ExplictLegacyPackageTest) { + RubyTest("/ruby_generated_pkg_explicit_legacy"); +} + +} // namespace +} // namespace ruby +} // namespace compiler +} // namespace protobuf +} // namespace google |