Change the Ruby code generator to emit a serialized proto instead of the DSL (#12319)

This PR removes the DSL from the code generator, in anticipation of splitting the DSL out into a separate package.

Given a .proto file like:

```proto
syntax = "proto3";

package pkg;

message TestMessage {
  optional int32 i32 = 1;
  optional TestMessage msg = 2;
}
```

Generated code before:

```ruby
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: protoc_explorer/main.proto

require 'google/protobuf'

Google::Protobuf::DescriptorPool.generated_pool.build do
  add_file("test.proto", :syntax => :proto3) do
    add_message "pkg.TestMessage" do
      proto3_optional :i32, :int32, 1
      proto3_optional :msg, :message, 2, "pkg.TestMessage"
    end
  end
end

module Pkg
  TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pkg.TestMessage").msgclass
end
```

Generated code after:

```ruby
# frozen_string_literal: true
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: test.proto

require 'google/protobuf'

descriptor_data = "\n\ntest.proto\x12\x03pkg\"S\n\x0bTestMessage\x12\x10\n\x03i32\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\"\n\x03msg\x18\x02 \x01(\x0b\x32\x10.pkg.TestMessageH\x01\x88\x01\x01\x42\x06\n\x04_i32B\x06\n\x04_msgb\x06proto3"
begin
  Google::Protobuf::DescriptorPool.generated_pool.add_serialized_file(descriptor_data)
rescue TypeError => e
  # <compatibility code, see below>
end

module Pkg
  TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pkg.TestMessage").msgclass
end
```

This change fixes nearly all remaining conformance problems that existed previously. This is a side effect of moving from the DSL (which is lossy) to a serialized descriptor (which preserves all information).

## Backward Compatibility

This change should be 100% compatible with Ruby Protobuf >= 3.18.0, released in Sept 2021. Additionally, it should be compatible with all existing users and deployments. However there is some special compatibility code I inserted to achieve this level of backward compatibility.

Without the compatibility code, there is an edge case that could break backward compatibility. The existing code is lax in a way that the new code would be more strict.

When we use a full serialized descriptor, it will contain a list of all `.proto` files imported by this file (whereas the DSL never added dependencies properly): dfb71558a2/src/google/protobuf/descriptor.proto (L65-L66)

`add_serialized_file` will verify that all dependencies listed in the descriptor were previously added with `add_serialized_file`.  Generally that should be fine, because the generated code will contain Ruby `require` statements for all dependencies, and the descriptor will fail to load anyway if the types we depend on were not previously defined in the DescriptorPool.

But there is a potential for problems if there are ambiguities around file paths. For example, consider the following scenario:

```proto
// foo/bar.proto

syntax = "proto2";

message Bar {}
```

```proto
// foo/baz.proto

syntax = "proto2";

import "bar.proto";

message Baz {
  optional Bar bar = 1;
}
```

If you invoke `protoc` like so, it will work correctly:

```
$ protoc --ruby_out=. -Ifoo foo/bar.proto foo/baz.proto
$ RUBYLIB=. ruby baz_pb.rb
```

However if you invoke `protoc` like so, and didn't have any compatibility code, it would fail to load:

```
$ protoc --ruby_out=. -I. -Ifoo foo/baz.proto
$ protoc --ruby_out=. -I. -Ifoo foo/bar.proto
$ RUBYLIB=foo ruby foo/baz_pb.rb
foo/baz_pb.rb:10:in `add_serialized_file': Unable to build file to DescriptorPool: Depends on file 'bar.proto', but it has not been loaded (Google::Protobuf::TypeError)
	from foo/baz_pb.rb:10:in `<main>'
```

The problem is that `bar.proto` is being referred to by two different canonical names: `bar.proto` and `foo/bar.proto`. This is a user error: each import should always be referred to by a consistent full path. Hopefully user errors of this sort are rare, but it is hard to know without trying.

The code in this PR prints a warning using `warn` if we detect that this edge case has occurred. We will plan to remove this compatibility code in the next major version.

Closes #12319

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/12319 from haberman:ruby-gencode-binary 5c0e8f20b1
PiperOrigin-RevId: 524129023
pull/12466/head
Joshua Haberman 2 years ago committed by Copybara-Service
parent 21256b86a9
commit bd52d04839
  1. 57
      conformance/failure_list_jruby.txt
  2. 58
      conformance/failure_list_ruby.txt
  3. 5
      ruby/src/main/java/com/google/protobuf/jruby/Utils.java
  4. 84
      src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb
  5. 85
      src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb
  6. 28
      src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb
  7. 28
      src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb
  8. 28
      src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb
  9. 357
      src/google/protobuf/compiler/ruby/ruby_generator.cc

@ -2,34 +2,6 @@ Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue
Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse
@ -57,35 +29,6 @@ Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Required.Proto3.JsonInput.EnumFieldNotQuoted
Required.Proto3.JsonInput.Int32FieldLeadingZero
Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero

@ -1,60 +1,2 @@
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput

@ -44,6 +44,7 @@ import org.jruby.runtime.Block;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
public class Utils {
public static FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) {
@ -263,7 +264,9 @@ public class Utils {
IRubyObject wrapped =
encodeBytes
? RubyString.newString(
runtime, ((ByteString) value).toStringUtf8(), ASCIIEncoding.INSTANCE)
runtime,
new ByteList(((ByteString) value).toByteArray()),
ASCIIEncoding.INSTANCE)
: RubyString.newString(runtime, ((ByteString) value).toByteArray());
wrapped.setFrozen(true);
return wrapped;

@ -1,3 +1,4 @@
# frozen_string_literal: true
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: ruby_generated_code.proto
@ -5,67 +6,32 @@ 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
descriptor_data = "\n\x19ruby_generated_code.proto\x12\x05\x41.B.C\x1a\'ruby_generated_code_proto2_import.proto\"\x86\x12\n\x0bTestMessage\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x15\n\roptional_bool\x18\x05 \x01(\x08\x12\x17\n\x0foptional_double\x18\x06 \x01(\x01\x12\x16\n\x0eoptional_float\x18\x07 \x01(\x02\x12\x17\n\x0foptional_string\x18\x08 \x01(\t\x12\x16\n\x0eoptional_bytes\x18\t \x01(\x0c\x12&\n\roptional_enum\x18\n \x01(\x0e\x32\x0f.A.B.C.TestEnum\x12(\n\x0coptional_msg\x18\x0b \x01(\x0b\x32\x12.A.B.C.TestMessage\x12>\n\x1aoptional_proto2_submessage\x18\x0c \x01(\x0b\x32\x1a.A.B.C.TestImportedMessage\x12\x16\n\x0erepeated_int32\x18\x15 \x03(\x05\x12\x16\n\x0erepeated_int64\x18\x16 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18\x17 \x03(\r\x12\x17\n\x0frepeated_uint64\x18\x18 \x03(\x04\x12\x15\n\rrepeated_bool\x18\x19 \x03(\x08\x12\x17\n\x0frepeated_double\x18\x1a \x03(\x01\x12\x16\n\x0erepeated_float\x18\x1b \x03(\x02\x12\x17\n\x0frepeated_string\x18\x1c \x03(\t\x12\x16\n\x0erepeated_bytes\x18\x1d \x03(\x0c\x12&\n\rrepeated_enum\x18\x1e \x03(\x0e\x32\x0f.A.B.C.TestEnum\x12(\n\x0crepeated_msg\x18\x1f \x03(\x0b\x32\x12.A.B.C.TestMessage\x12\x15\n\x0boneof_int32\x18) \x01(\x05H\x00\x12\x15\n\x0boneof_int64\x18* \x01(\x03H\x00\x12\x16\n\x0coneof_uint32\x18+ \x01(\rH\x00\x12\x16\n\x0coneof_uint64\x18, \x01(\x04H\x00\x12\x14\n\noneof_bool\x18- \x01(\x08H\x00\x12\x16\n\x0coneof_double\x18. \x01(\x01H\x00\x12\x15\n\x0boneof_float\x18/ \x01(\x02H\x00\x12\x16\n\x0coneof_string\x18\x30 \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18\x31 \x01(\x0cH\x00\x12%\n\noneof_enum\x18\x32 \x01(\x0e\x32\x0f.A.B.C.TestEnumH\x00\x12\'\n\toneof_msg\x18\x33 \x01(\x0b\x32\x12.A.B.C.TestMessageH\x00\x12@\n\x10map_int32_string\x18= \x03(\x0b\x32&.A.B.C.TestMessage.MapInt32StringEntry\x12@\n\x10map_int64_string\x18> \x03(\x0b\x32&.A.B.C.TestMessage.MapInt64StringEntry\x12\x42\n\x11map_uint32_string\x18? \x03(\x0b\x32\'.A.B.C.TestMessage.MapUint32StringEntry\x12\x42\n\x11map_uint64_string\x18@ \x03(\x0b\x32\'.A.B.C.TestMessage.MapUint64StringEntry\x12>\n\x0fmap_bool_string\x18\x41 \x03(\x0b\x32%.A.B.C.TestMessage.MapBoolStringEntry\x12\x42\n\x11map_string_string\x18\x42 \x03(\x0b\x32\'.A.B.C.TestMessage.MapStringStringEntry\x12<\n\x0emap_string_msg\x18\x43 \x03(\x0b\x32$.A.B.C.TestMessage.MapStringMsgEntry\x12>\n\x0fmap_string_enum\x18\x44 \x03(\x0b\x32%.A.B.C.TestMessage.MapStringEnumEntry\x12@\n\x10map_string_int32\x18\x45 \x03(\x0b\x32&.A.B.C.TestMessage.MapStringInt32Entry\x12>\n\x0fmap_string_bool\x18\x46 \x03(\x0b\x32%.A.B.C.TestMessage.MapStringBoolEntry\x12\x38\n\x0enested_message\x18P \x01(\x0b\x32 .A.B.C.TestMessage.NestedMessage\x1a\x35\n\x13MapInt32StringEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x35\n\x13MapInt64StringEntry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x36\n\x14MapUint32StringEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x36\n\x14MapUint64StringEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12MapBoolStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1aG\n\x11MapStringMsgEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.A.B.C.TestMessage:\x02\x38\x01\x1a\x45\n\x12MapStringEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1e\n\x05value\x18\x02 \x01(\x0e\x32\x0f.A.B.C.TestEnum:\x02\x38\x01\x1a\x35\n\x13MapStringInt32Entry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapStringBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x1c\n\rNestedMessage\x12\x0b\n\x03\x66oo\x18\x01 \x01(\x05\x42\n\n\x08my_oneof*,\n\x08TestEnum\x12\x0b\n\x07\x44\x65\x66\x61ult\x10\x00\x12\x05\n\x01\x41\x10\x01\x12\x05\n\x01\x42\x10\x02\x12\x05\n\x01\x43\x10\x03\x62\x06proto3"
pool = Google::Protobuf::DescriptorPool.generated_pool
begin
pool.add_serialized_file(descriptor_data)
rescue TypeError => e
# Compatibility code: will be removed in the next major version.
require 'google/protobuf/descriptor_pb'
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
parsed.clear_dependency
serialized = parsed.class.encode(parsed)
file = pool.add_serialized_file(serialized)
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
imports = [
["A.B.C.TestImportedMessage", "ruby_generated_code_proto2_import.proto"],
]
imports.each do |type_name, expected_filename|
import_file = pool.lookup(type_name).file_descriptor
if import_file.name != expected_filename
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
end
end
warn "Each proto file must use a consistent fully-qualified name."
warn "This will become an error in the next major version."
end
module A

@ -1,3 +1,4 @@
# frozen_string_literal: true
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: ruby_generated_code_proto2.proto
@ -5,68 +6,32 @@ 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
descriptor_data = "\n ruby_generated_code_proto2.proto\x12\x05\x41.B.C\x1a\'ruby_generated_code_proto2_import.proto\"\x96\x0b\n\x0bTestMessage\x12\x19\n\x0eoptional_int32\x18\x01 \x01(\x05:\x01\x31\x12\x19\n\x0eoptional_int64\x18\x02 \x01(\x03:\x01\x32\x12\x1a\n\x0foptional_uint32\x18\x03 \x01(\r:\x01\x33\x12\x1a\n\x0foptional_uint64\x18\x04 \x01(\x04:\x01\x34\x12\x1b\n\roptional_bool\x18\x05 \x01(\x08:\x04true\x12\x1a\n\x0foptional_double\x18\x06 \x01(\x01:\x01\x36\x12\x19\n\x0eoptional_float\x18\x07 \x01(\x02:\x01\x37\x12$\n\x0foptional_string\x18\x08 \x01(\t:\x0b\x64\x65\x66\x61ult str\x12*\n\x0eoptional_bytes\x18\t \x01(\x0c:\x12\\000\\001\\002@fubar\x12)\n\roptional_enum\x18\n \x01(\x0e\x32\x0f.A.B.C.TestEnum:\x01\x41\x12(\n\x0coptional_msg\x18\x0b \x01(\x0b\x32\x12.A.B.C.TestMessage\x12>\n\x1aoptional_proto2_submessage\x18\x0c \x01(\x0b\x32\x1a.A.B.C.TestImportedMessage\x12\x16\n\x0erepeated_int32\x18\x15 \x03(\x05\x12\x16\n\x0erepeated_int64\x18\x16 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18\x17 \x03(\r\x12\x17\n\x0frepeated_uint64\x18\x18 \x03(\x04\x12\x15\n\rrepeated_bool\x18\x19 \x03(\x08\x12\x17\n\x0frepeated_double\x18\x1a \x03(\x01\x12\x16\n\x0erepeated_float\x18\x1b \x03(\x02\x12\x17\n\x0frepeated_string\x18\x1c \x03(\t\x12\x16\n\x0erepeated_bytes\x18\x1d \x03(\x0c\x12&\n\rrepeated_enum\x18\x1e \x03(\x0e\x32\x0f.A.B.C.TestEnum\x12(\n\x0crepeated_msg\x18\x1f \x03(\x0b\x32\x12.A.B.C.TestMessage\x12\x16\n\x0erequired_int32\x18) \x02(\x05\x12\x16\n\x0erequired_int64\x18* \x02(\x03\x12\x17\n\x0frequired_uint32\x18+ \x02(\r\x12\x17\n\x0frequired_uint64\x18, \x02(\x04\x12\x15\n\rrequired_bool\x18- \x02(\x08\x12\x17\n\x0frequired_double\x18. \x02(\x01\x12\x16\n\x0erequired_float\x18/ \x02(\x02\x12\x17\n\x0frequired_string\x18\x30 \x02(\t\x12\x16\n\x0erequired_bytes\x18\x31 \x02(\x0c\x12&\n\rrequired_enum\x18\x32 \x02(\x0e\x32\x0f.A.B.C.TestEnum\x12(\n\x0crequired_msg\x18\x33 \x02(\x0b\x32\x12.A.B.C.TestMessage\x12\x15\n\x0boneof_int32\x18= \x01(\x05H\x00\x12\x15\n\x0boneof_int64\x18> \x01(\x03H\x00\x12\x16\n\x0coneof_uint32\x18? \x01(\rH\x00\x12\x16\n\x0coneof_uint64\x18@ \x01(\x04H\x00\x12\x14\n\noneof_bool\x18\x41 \x01(\x08H\x00\x12\x16\n\x0coneof_double\x18\x42 \x01(\x01H\x00\x12\x15\n\x0boneof_float\x18\x43 \x01(\x02H\x00\x12\x16\n\x0coneof_string\x18\x44 \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18\x45 \x01(\x0cH\x00\x12%\n\noneof_enum\x18\x46 \x01(\x0e\x32\x0f.A.B.C.TestEnumH\x00\x12\'\n\toneof_msg\x18G \x01(\x0b\x32\x12.A.B.C.TestMessageH\x00\x12\x38\n\x0enested_message\x18P \x01(\x0b\x32 .A.B.C.TestMessage.NestedMessage\x1a\x1c\n\rNestedMessage\x12\x0b\n\x03\x66oo\x18\x01 \x01(\x05\x42\n\n\x08my_oneof*,\n\x08TestEnum\x12\x0b\n\x07\x44\x65\x66\x61ult\x10\x00\x12\x05\n\x01\x41\x10\x01\x12\x05\n\x01\x42\x10\x02\x12\x05\n\x01\x43\x10\x03"
pool = Google::Protobuf::DescriptorPool.generated_pool
begin
pool.add_serialized_file(descriptor_data)
rescue TypeError => e
# Compatibility code: will be removed in the next major version.
require 'google/protobuf/descriptor_pb'
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
parsed.clear_dependency
serialized = parsed.class.encode(parsed)
file = pool.add_serialized_file(serialized)
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
imports = [
["A.B.C.TestImportedMessage", "ruby_generated_code_proto2_import.proto"],
]
imports.each do |type_name, expected_filename|
import_file = pool.lookup(type_name).file_descriptor
if import_file.name != expected_filename
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
end
end
warn "Each proto file must use a consistent fully-qualified name."
warn "This will become an error in the next major version."
end
module A

@ -1,14 +1,34 @@
# frozen_string_literal: true
# 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
descriptor_data = "\n(ruby_generated_pkg_explicit_legacy.proto\x12\x13one.two.a_three.and\"\x1e\n\x04\x46our\x12\x16\n\x0e\x61nother_string\x18\x01 \x01(\tB\x0b\xea\x02\x08\x41\x41.BB.CCb\x06proto3"
pool = Google::Protobuf::DescriptorPool.generated_pool
begin
pool.add_serialized_file(descriptor_data)
rescue TypeError => e
# Compatibility code: will be removed in the next major version.
require 'google/protobuf/descriptor_pb'
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
parsed.clear_dependency
serialized = parsed.class.encode(parsed)
file = pool.add_serialized_file(serialized)
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
imports = [
]
imports.each do |type_name, expected_filename|
import_file = pool.lookup(type_name).file_descriptor
if import_file.name != expected_filename
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
end
end
warn "Each proto file must use a consistent fully-qualified name."
warn "This will become an error in the next major version."
end
module AA

@ -1,14 +1,34 @@
# frozen_string_literal: true
# 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
descriptor_data = "\n!ruby_generated_pkg_explicit.proto\x12\x0fone.two.a_three\"\x18\n\x04\x46our\x12\x10\n\x08\x61_string\x18\x01 \x01(\tB\n\xea\x02\x07\x41::B::Cb\x06proto3"
pool = Google::Protobuf::DescriptorPool.generated_pool
begin
pool.add_serialized_file(descriptor_data)
rescue TypeError => e
# Compatibility code: will be removed in the next major version.
require 'google/protobuf/descriptor_pb'
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
parsed.clear_dependency
serialized = parsed.class.encode(parsed)
file = pool.add_serialized_file(serialized)
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
imports = [
]
imports.each do |type_name, expected_filename|
import_file = pool.lookup(type_name).file_descriptor
if import_file.name != expected_filename
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
end
end
warn "Each proto file must use a consistent fully-qualified name."
warn "This will become an error in the next major version."
end
module A

@ -1,14 +1,34 @@
# frozen_string_literal: true
# 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
descriptor_data = "\n!ruby_generated_pkg_implicit.proto\x12\x0fone.two.a_three\"\x18\n\x04\x46our\x12\x10\n\x08\x61_string\x18\x01 \x01(\tb\x06proto3"
pool = Google::Protobuf::DescriptorPool.generated_pool
begin
pool.add_serialized_file(descriptor_data)
rescue TypeError => e
# Compatibility code: will be removed in the next major version.
require 'google/protobuf/descriptor_pb'
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
parsed.clear_dependency
serialized = parsed.class.encode(parsed)
file = pool.add_serialized_file(serialized)
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
imports = [
]
imports.each do |type_name, expected_filename|
import_file = pool.lookup(type_name).file_descriptor
if import_file.name != expected_filename
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
end
end
warn "Each proto file must use a consistent fully-qualified name."
warn "This will become an error in the next major version."
end
module One

@ -35,7 +35,9 @@
#include <sstream>
#include "google/protobuf/compiler/code_generator.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/absl_log.h"
#include "absl/strings/escaping.h"
#include "google/protobuf/compiler/plugin.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h"
@ -54,9 +56,6 @@ std::string NumberToString(numeric_type value);
std::string GetRequireName(absl::string_view 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(absl::string_view prefix,
const Descriptor* message, io::Printer* printer);
void GenerateEnumAssignment(absl::string_view prefix, const EnumDescriptor* en,
@ -79,238 +78,6 @@ std::string GetOutputFilename(absl::string_view proto_file) {
return absl::StrCat(GetRequireName(proto_file), ".rb");
}
std::string LabelForField(const FieldDescriptor* field) {
if (FieldDescriptorLegacy(field).has_optional_keyword() &&
field->containing_oneof() != nullptr) {
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(FileDescriptorLegacy::Syntax syntax) {
switch (syntax) {
case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2:
return "proto2";
case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3:
return "proto3";
case FileDescriptorLegacy::Syntax::SYNTAX_UNKNOWN:
default:
ABSL_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_t)((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) {
ABSL_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'; }
@ -470,47 +237,91 @@ void EndPackageModules(int levels, io::Printer* printer) {
}
}
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(FileDescriptorLegacy(file).syntax()));
printer->Indent();
std::string SerializedDescriptor(const FileDescriptor* file) {
FileDescriptorProto file_proto;
file->CopyTo(&file_proto);
std::string file_data;
file_proto.SerializeToString(&file_data);
return file_data;
}
template <class F>
void ForEachField(const Descriptor* d, F&& func) {
for (int i = 0; i < d->field_count(); i++) {
func(d->field(i));
}
for (int i = 0; i < d->nested_type_count(); i++) {
ForEachField(d->nested_type(i), func);
}
}
template <class F>
void ForEachField(const FileDescriptor* file, F&& func) {
for (int i = 0; i < file->message_type_count(); i++) {
if (!GenerateMessage(file->message_type(i), printer, error)) {
return false;
}
ForEachField(file->message_type(i), func);
}
for (int i = 0; i < file->enum_type_count(); i++) {
GenerateEnum(file->enum_type(i), printer);
for (int i = 0; i < file->extension_count(); i++) {
func(file->extension(i));
}
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 DumpImportList(const FileDescriptor* file) {
// For each import, find a symbol that comes from that file.
absl::flat_hash_set<const FileDescriptor*> seen{file};
std::string ret;
ForEachField(file, [&](const FieldDescriptor* field) {
if (!field->message_type()) return;
const FileDescriptor* f = field->message_type()->file();
if (!seen.insert(f).second) return;
absl::StrAppend(&ret, " [\"", field->message_type()->full_name(),
"\", \"", f->name(), "\"],\n");
});
return ret;
}
void 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;
printer->Print(R"(
descriptor_data = "$descriptor_data$"
pool = Google::Protobuf::DescriptorPool.generated_pool
begin
pool.add_serialized_file(descriptor_data)
rescue TypeError => e
# Compatibility code: will be removed in the next major version.
require 'google/protobuf/descriptor_pb'
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
parsed.clear_dependency
serialized = parsed.class.encode(parsed)
file = pool.add_serialized_file(serialized)
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
imports = [
$imports$ ]
imports.each do |type_name, expected_filename|
import_file = pool.lookup(type_name).file_descriptor
if import_file.name != expected_filename
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
end
end
warn "Each proto file must use a consistent fully-qualified name."
warn "This will become an error in the next major version."
end
)",
"descriptor_data",
absl::CHexEscape(SerializedDescriptor(file)), "imports",
DumpImportList(file));
}
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());
"# frozen_string_literal: true\n"
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"# source: $filename$\n"
"\n",
"filename", file->name());
printer->Print("require 'google/protobuf'\n\n");
@ -526,13 +337,7 @@ bool GenerateFile(const FileDescriptor* file, io::Printer* printer,
ABSL_LOG(WARNING) << "Extensions are not yet supported in Ruby.";
}
bool use_raw_descriptor = file->name() == "google/protobuf/descriptor.proto";
if (use_raw_descriptor) {
GenerateBinaryDescriptor(file, printer, error);
} else {
GenerateDslDescriptor(file, printer, error);
}
GenerateBinaryDescriptor(file, printer, error);
int levels = GeneratePackageModules(file, printer);
for (int i = 0; i < file->message_type_count(); i++) {
@ -543,14 +348,6 @@ bool GenerateFile(const FileDescriptor* file, io::Printer* 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;
}

Loading…
Cancel
Save