protobuf-core 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +18 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +23 -0
  8. data/Rakefile +5 -0
  9. data/bin/protoc-gen-ruby +16 -0
  10. data/lib/protobuf.rb +27 -0
  11. data/lib/protobuf/code_generator.rb +44 -0
  12. data/lib/protobuf/core.rb +2 -0
  13. data/lib/protobuf/core/version.rb +5 -0
  14. data/lib/protobuf/decoder.rb +73 -0
  15. data/lib/protobuf/deprecation.rb +112 -0
  16. data/lib/protobuf/descriptors.rb +3 -0
  17. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +54 -0
  18. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +251 -0
  19. data/lib/protobuf/encoder.rb +67 -0
  20. data/lib/protobuf/enum.rb +303 -0
  21. data/lib/protobuf/exceptions.rb +9 -0
  22. data/lib/protobuf/field.rb +74 -0
  23. data/lib/protobuf/field/base_field.rb +267 -0
  24. data/lib/protobuf/field/bool_field.rb +59 -0
  25. data/lib/protobuf/field/bytes_field.rb +82 -0
  26. data/lib/protobuf/field/double_field.rb +25 -0
  27. data/lib/protobuf/field/enum_field.rb +68 -0
  28. data/lib/protobuf/field/field_array.rb +87 -0
  29. data/lib/protobuf/field/fixed32_field.rb +25 -0
  30. data/lib/protobuf/field/fixed64_field.rb +28 -0
  31. data/lib/protobuf/field/float_field.rb +41 -0
  32. data/lib/protobuf/field/int32_field.rb +21 -0
  33. data/lib/protobuf/field/int64_field.rb +21 -0
  34. data/lib/protobuf/field/integer_field.rb +23 -0
  35. data/lib/protobuf/field/message_field.rb +65 -0
  36. data/lib/protobuf/field/sfixed32_field.rb +27 -0
  37. data/lib/protobuf/field/sfixed64_field.rb +28 -0
  38. data/lib/protobuf/field/signed_integer_field.rb +29 -0
  39. data/lib/protobuf/field/sint32_field.rb +21 -0
  40. data/lib/protobuf/field/sint64_field.rb +21 -0
  41. data/lib/protobuf/field/string_field.rb +34 -0
  42. data/lib/protobuf/field/uint32_field.rb +21 -0
  43. data/lib/protobuf/field/uint64_field.rb +21 -0
  44. data/lib/protobuf/field/varint_field.rb +73 -0
  45. data/lib/protobuf/generators/base.rb +70 -0
  46. data/lib/protobuf/generators/enum_generator.rb +41 -0
  47. data/lib/protobuf/generators/extension_generator.rb +27 -0
  48. data/lib/protobuf/generators/field_generator.rb +131 -0
  49. data/lib/protobuf/generators/file_generator.rb +132 -0
  50. data/lib/protobuf/generators/group_generator.rb +105 -0
  51. data/lib/protobuf/generators/message_generator.rb +98 -0
  52. data/lib/protobuf/generators/printable.rb +160 -0
  53. data/lib/protobuf/logging.rb +39 -0
  54. data/lib/protobuf/message.rb +193 -0
  55. data/lib/protobuf/message/fields.rb +133 -0
  56. data/lib/protobuf/message/serialization.rb +89 -0
  57. data/lib/protobuf/optionable.rb +23 -0
  58. data/lib/protobuf/wire_type.rb +10 -0
  59. data/proto/dynamic_discovery.proto +44 -0
  60. data/proto/google/protobuf/compiler/plugin.proto +147 -0
  61. data/proto/google/protobuf/descriptor.proto +620 -0
  62. data/proto/rpc.proto +62 -0
  63. data/protobuf-core.gemspec +31 -0
  64. data/spec/bin/protoc-gen-ruby_spec.rb +23 -0
  65. data/spec/data/data.bin +3 -0
  66. data/spec/data/types.bin +0 -0
  67. data/spec/encoding/all_types_spec.rb +105 -0
  68. data/spec/encoding/extreme_values_spec.rb +0 -0
  69. data/spec/functional/class_inheritance_spec.rb +52 -0
  70. data/spec/functional/compile_and_require_spec.rb +29 -0
  71. data/spec/lib/protobuf/base_spec.rb +84 -0
  72. data/spec/lib/protobuf/code_generator_spec.rb +60 -0
  73. data/spec/lib/protobuf/enum_generator_spec.rb +73 -0
  74. data/spec/lib/protobuf/enum_spec.rb +265 -0
  75. data/spec/lib/protobuf/extension_generator_spec.rb +42 -0
  76. data/spec/lib/protobuf/field/bool_field_spec.rb +51 -0
  77. data/spec/lib/protobuf/field/field_array_spec.rb +69 -0
  78. data/spec/lib/protobuf/field/float_field_spec.rb +55 -0
  79. data/spec/lib/protobuf/field/int32_field_spec.rb +90 -0
  80. data/spec/lib/protobuf/field/string_field_spec.rb +45 -0
  81. data/spec/lib/protobuf/field_generator_spec.rb +102 -0
  82. data/spec/lib/protobuf/field_spec.rb +191 -0
  83. data/spec/lib/protobuf/file_generator_spec.rb +32 -0
  84. data/spec/lib/protobuf/message_generator_spec.rb +0 -0
  85. data/spec/lib/protobuf/message_spec.rb +526 -0
  86. data/spec/lib/protobuf/optionable_spec.rb +46 -0
  87. data/spec/lib/protobuf_spec.rb +45 -0
  88. data/spec/spec_helper.rb +9 -0
  89. data/spec/support/packed_field.rb +22 -0
  90. data/spec/support/test/all_types.data.bin +0 -0
  91. data/spec/support/test/all_types.data.txt +119 -0
  92. data/spec/support/test/bacon.proto +14 -0
  93. data/spec/support/test/defaults.pb.rb +27 -0
  94. data/spec/support/test/defaults.proto +9 -0
  95. data/spec/support/test/enum.pb.rb +61 -0
  96. data/spec/support/test/enum.proto +34 -0
  97. data/spec/support/test/extended.pb.rb +24 -0
  98. data/spec/support/test/extended.proto +10 -0
  99. data/spec/support/test/extreme_values.data.bin +0 -0
  100. data/spec/support/test/google_unittest.pb.rb +530 -0
  101. data/spec/support/test/google_unittest.proto +713 -0
  102. data/spec/support/test/google_unittest_import.pb.rb +39 -0
  103. data/spec/support/test/google_unittest_import.proto +64 -0
  104. data/spec/support/test/google_unittest_import_public.pb.rb +10 -0
  105. data/spec/support/test/google_unittest_import_public.proto +38 -0
  106. data/spec/support/test/multi_field_extensions.pb.rb +58 -0
  107. data/spec/support/test/multi_field_extensions.proto +33 -0
  108. data/spec/support/test/resource.pb.rb +106 -0
  109. data/spec/support/test/resource.proto +94 -0
  110. metadata +306 -0
@@ -0,0 +1,132 @@
1
+ require 'set'
2
+ require 'protobuf/generators/base'
3
+ require 'protobuf/generators/group_generator'
4
+
5
+ module Protobuf
6
+ module Generators
7
+ class FileGenerator < Base
8
+
9
+ attr_reader :output_file
10
+
11
+ def initialize(*args)
12
+ super
13
+ @output_file = ::Google::Protobuf::Compiler::CodeGeneratorResponse::File.new(:name => file_name)
14
+ @extension_fields = Hash.new { |h, k| h[k] = [] }
15
+ @known_messages = []
16
+ @dangling_messages = {}
17
+ end
18
+
19
+ def file_name
20
+ convert_filename(descriptor.name, false)
21
+ end
22
+
23
+ def compile
24
+ run_once(:compile) do
25
+ map_extensions(descriptor, [descriptor.package])
26
+
27
+ print_file_comment
28
+ print_generic_requires
29
+ print_import_requires
30
+
31
+ print_package do
32
+ group = GroupGenerator.new(current_indent)
33
+ group.add_enums(descriptor.enum_type, :namespace => [descriptor.package])
34
+ group.add_message_declarations(descriptor.message_type)
35
+ group.add_messages(descriptor.message_type, :extension_fields => @extension_fields, :namespace => [descriptor.package])
36
+ group.add_extended_messages(unknown_extensions)
37
+
38
+ group.add_header(:enum, 'Enum Classes')
39
+ group.add_header(:message_declaration, 'Message Classes')
40
+ group.add_header(:message, 'Message Fields')
41
+ group.add_header(:extended_message, 'Extended Message Fields')
42
+ print group.to_s
43
+ end
44
+
45
+ end
46
+ end
47
+
48
+ def unknown_extensions
49
+ @unknown_extensions ||= @extension_fields.reject do |k, _|
50
+ @known_messages.include?(k)
51
+ end
52
+ end
53
+
54
+ def generate_output_file
55
+ compile
56
+ output_file.content = to_s
57
+ output_file
58
+ end
59
+
60
+ # Recursively map out all extensions known in this file.
61
+ # The key is the type_name of the message being extended, and
62
+ # the value is an array of field descriptors.
63
+ #
64
+ def map_extensions(descriptor, namespaces)
65
+ # Record all the message descriptor name's we encounter (should be the whole tree).
66
+ if descriptor.is_a?(::Google::Protobuf::DescriptorProto)
67
+ if fully_qualified_token?(descriptor.name)
68
+ @known_messages << descriptor.name
69
+ else
70
+ fully_qualified_namespace = ".#{namespaces.join('.')}"
71
+ @known_messages << fully_qualified_namespace
72
+ end
73
+ end
74
+
75
+ descriptor.extension.each do |field_descriptor|
76
+ @extension_fields[field_descriptor.extendee] << field_descriptor
77
+ end
78
+
79
+ [:message_type, :nested_type].each do |type|
80
+ next unless descriptor.respond_to_has_and_present?(type)
81
+
82
+ descriptor.public_send(type).each do |type_descriptor|
83
+ map_extensions(type_descriptor, (namespaces + [type_descriptor.name]))
84
+ end
85
+ end
86
+ end
87
+
88
+ def print_file_comment
89
+ puts "# encoding: utf-8"
90
+ puts
91
+ puts "##"
92
+ puts "# This file is auto-generated. DO NOT EDIT!"
93
+ puts "#"
94
+ end
95
+
96
+ def print_generic_requires
97
+ print_require("protobuf/message")
98
+ puts
99
+ end
100
+
101
+ def print_import_requires
102
+ return if descriptor.dependency.empty?
103
+
104
+ header "Imports"
105
+
106
+ descriptor.dependency.each do |dependency|
107
+ print_require(convert_filename(dependency))
108
+ end
109
+
110
+ puts
111
+ end
112
+
113
+ def print_package(&block)
114
+ namespaces = descriptor.package.split('.')
115
+ namespaces.reverse.reduce(block) do |previous, namespace|
116
+ -> { print_module(namespace, &previous) }
117
+ end.call
118
+ end
119
+
120
+ private
121
+
122
+ def convert_filename(filename, for_require = true)
123
+ filename.sub(/\.proto/, (for_require ? '.pb' : '.pb.rb'))
124
+ end
125
+
126
+ def fully_qualified_token?(token)
127
+ token[0] == '.'
128
+ end
129
+
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,105 @@
1
+ require 'protobuf/generators/enum_generator'
2
+ require 'protobuf/generators/extension_generator'
3
+ require 'protobuf/generators/field_generator'
4
+ require 'protobuf/generators/message_generator'
5
+
6
+ module Protobuf
7
+ module Generators
8
+ class GroupGenerator
9
+ include ::Protobuf::Generators::Printable
10
+
11
+ attr_reader :groups, :indent_level
12
+ attr_writer :order
13
+
14
+ def initialize(indent_level = 0)
15
+ @groups = Hash.new { |h, k| h[k] = [] }
16
+ @headers = {}
17
+ @comments = {}
18
+ @handlers = {}
19
+ @indent_level = indent_level
20
+ @order = [:enum, :message_declaration, :message, :extended_message, :service]
21
+ init_printer(indent_level)
22
+ end
23
+
24
+ def add_enums(enum_descriptors, options)
25
+ enum_descriptors.each do |enum_descriptor|
26
+ @groups[:enum] << EnumGenerator.new(enum_descriptor, indent_level, options)
27
+ end
28
+ end
29
+
30
+ def add_comment(type, message)
31
+ @comments[type] = message
32
+ end
33
+
34
+ def add_extended_messages(extended_messages)
35
+ extended_messages.each do |message_type, field_descriptors|
36
+ @groups[:extended_message] << ExtensionGenerator.new(message_type, field_descriptors, indent_level)
37
+ end
38
+ end
39
+
40
+ def add_extension_fields(field_descriptors)
41
+ field_descriptors.each do |field_descriptor|
42
+ @groups[:extension_field] << FieldGenerator.new(field_descriptor, indent_level)
43
+ end
44
+ end
45
+
46
+ def add_extension_ranges(extension_ranges, &item_handler)
47
+ @groups[:extension_range] = extension_ranges
48
+ @handlers[:extension_range] = item_handler
49
+ end
50
+
51
+ def add_header(type, message)
52
+ @headers[type] = message
53
+ end
54
+
55
+ def add_message_declarations(descriptors)
56
+ descriptors.each do |descriptor|
57
+ @groups[:message_declaration] << MessageGenerator.new(descriptor, indent_level, :declaration => true)
58
+ end
59
+ end
60
+
61
+ def add_message_fields(field_descriptors)
62
+ field_descriptors.each do |field_descriptor|
63
+ @groups[:field] << FieldGenerator.new(field_descriptor, indent_level)
64
+ end
65
+ end
66
+
67
+ def add_messages(descriptors, options = {})
68
+ descriptors.each do |descriptor|
69
+ @groups[:message] << MessageGenerator.new(descriptor, indent_level, options)
70
+ end
71
+ end
72
+
73
+ def compile
74
+ @order.each do |type|
75
+ items = @groups[type]
76
+ next if items.empty?
77
+
78
+ item_handler = @handlers[type]
79
+
80
+ item_header = @headers[type]
81
+ header(item_header) if item_header
82
+
83
+ item_comment = @comments[type]
84
+ comment(item_comment) if item_comment
85
+
86
+ items.each do |item|
87
+ if item_handler
88
+ puts item_handler.call(item)
89
+ else
90
+ print item.to_s
91
+ end
92
+ end
93
+
94
+ puts if type == :message_declaration
95
+ end
96
+ end
97
+
98
+ def to_s
99
+ compile
100
+ print_contents
101
+ end
102
+
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,98 @@
1
+ require 'protobuf/generators/base'
2
+ require 'protobuf/generators/group_generator'
3
+
4
+ module Protobuf
5
+ module Generators
6
+ class MessageGenerator < Base
7
+
8
+ def initialize(descriptor, indent_level, options = {})
9
+ super
10
+ @only_declarations = options.fetch(:declaration) { false }
11
+ @extension_fields = options.fetch(:extension_fields) { {} }
12
+ end
13
+
14
+ def compile
15
+ run_once(:compile) do
16
+ if @only_declarations
17
+ compile_declaration
18
+ else
19
+ compile_message
20
+ end
21
+ end
22
+ end
23
+
24
+ def compile_declaration
25
+ run_once(:compile_declaration) do
26
+ if printable?
27
+ print_class(descriptor.name, :message) do
28
+ group = GroupGenerator.new(current_indent)
29
+ group.add_enums(descriptor.enum_type, :namespace => type_namespace)
30
+ group.add_message_declarations(descriptor.nested_type)
31
+ print group.to_s
32
+ end
33
+ else
34
+ print_class(descriptor.name, :message)
35
+ end
36
+ end
37
+ end
38
+
39
+ def compile_message
40
+ run_once(:compile_message) do
41
+ if printable?
42
+ print_class(descriptor.name, nil) do
43
+ group = GroupGenerator.new(current_indent)
44
+ group.add_messages(descriptor.nested_type, :extension_fields => @extension_fields, :namespace => type_namespace)
45
+ group.add_message_fields(descriptor.field)
46
+ self.class.validate_tags(fully_qualified_type_namespace, descriptor.field.map(&:number))
47
+
48
+ group.add_comment(:extension_range, 'Extension Fields')
49
+ group.add_extension_ranges(descriptor.extension_range) do |extension_range|
50
+ "extensions #{extension_range.start}...#{extension_range.end}"
51
+ end
52
+
53
+ group.add_extension_fields(message_extension_fields)
54
+
55
+ group.order = [:message, :field, :extension_range, :extension_field]
56
+ print group.to_s
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def extensions?
65
+ !message_extension_fields.empty?
66
+ end
67
+
68
+ def fields?
69
+ descriptor.field.count > 0
70
+ end
71
+
72
+ def nested_enums?
73
+ descriptor.enum_type.count > 0
74
+ end
75
+
76
+ def nested_messages?
77
+ descriptor.nested_type.count > 0
78
+ end
79
+
80
+ def nested_types?
81
+ nested_enums? || nested_messages?
82
+ end
83
+
84
+ def printable?
85
+ if @only_declarations
86
+ nested_types?
87
+ else
88
+ fields? || nested_messages? || extensions?
89
+ end
90
+ end
91
+
92
+ def message_extension_fields
93
+ @extension_fields.fetch(fully_qualified_type_namespace) { [] }
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,160 @@
1
+ module Protobuf
2
+ module Generators
3
+ module Printable
4
+
5
+ PARENT_CLASS_MESSAGE = "::Protobuf::Message".freeze
6
+ PARENT_CLASS_ENUM = "::Protobuf::Enum".freeze
7
+ PARENT_CLASS_SERVICE = "::Protobuf::Rpc::Service".freeze
8
+
9
+ # Initialize the printer.
10
+ # Must be called by any class/module that includes the Printable module.
11
+ #
12
+ def init_printer(indent_level)
13
+ @io = ::StringIO.new
14
+ self.current_indent = indent_level.to_i
15
+ end
16
+
17
+ protected
18
+
19
+ attr_accessor :current_indent
20
+
21
+ private
22
+
23
+ # Print a one-line comment.
24
+ #
25
+ def comment(message)
26
+ puts "# #{message}"
27
+ end
28
+
29
+ # Print a "header" comment.
30
+ #
31
+ # header("Lorem ipsum dolor")
32
+ # ##
33
+ # # Lorem ipsum dolor
34
+ # #
35
+ def header(message)
36
+ puts
37
+ puts "##"
38
+ puts "# #{message}"
39
+ puts "#"
40
+ end
41
+
42
+ # Increase the indent level. An outdent will only occur if given a block
43
+ # (after the block is finished).
44
+ #
45
+ def indent
46
+ self.current_indent += 1
47
+ yield
48
+ outdent
49
+ end
50
+
51
+ # Take a string and upcase the first character of each namespace.
52
+ # Due to the nature of varying standards about how class/modules are named
53
+ # (e.g. CamelCase, Underscore_Case, SCREAMING_SNAKE_CASE), we only want
54
+ # to capitalize the first character to ensure ruby will treat the value
55
+ # as a constant. Otherwise we do not attempt to change the
56
+ # token's definition.
57
+ #
58
+ # modulize("foo.bar.Baz") -> "::Foo::Bar::Baz"
59
+ # modulize("foo.bar.baz") -> "::Foo::Bar::Baz"
60
+ # modulize("foo.bar.BAZ") -> "::Foo::Bar::BAZ"
61
+ #
62
+ def modulize(name)
63
+ name = name.gsub(/\./, '::')
64
+ name = name.gsub(/(^(?:::)?[a-z]|::[a-z])/) { |match| match.upcase }
65
+ name
66
+ end
67
+
68
+ # Decrease the indent level. Cannot be negative.
69
+ #
70
+ def outdent
71
+ self.current_indent -= 1 unless current_indent.zero?
72
+ end
73
+
74
+ # Return the parent class for a given type.
75
+ # Valid types are :message, :enum, and :service, otherwise an error
76
+ # will be thrown.
77
+ #
78
+ def parent_class(type)
79
+ case type
80
+ when :message then
81
+ PARENT_CLASS_MESSAGE
82
+ when :enum then
83
+ PARENT_CLASS_ENUM
84
+ when :service then
85
+ PARENT_CLASS_SERVICE
86
+ else
87
+ fail "Unknown parent class type #{type}: #{caller[0..5].join("\n")}"
88
+ end
89
+ end
90
+
91
+ # Print a class or module block, indicated by type.
92
+ # If a class, can be given a parent class to inherit from.
93
+ # If a block is given, call the block from within an indent block.
94
+ # Otherwise, end the block on the same line.
95
+ #
96
+ def print_block(name, parent_klass, type, &block)
97
+ name = modulize(name)
98
+ block_def = "#{type} #{name}"
99
+ block_def += " < #{parent_class(parent_klass)}" if parent_klass
100
+
101
+ if block_given?
102
+ puts block_def
103
+ indent { block.call }
104
+ puts "end"
105
+ puts
106
+ else
107
+ block_def += "; end"
108
+ puts block_def
109
+ end
110
+ end
111
+
112
+ # Use print_block to print a class, with optional parent class
113
+ # to inherit from. Accepts a block for use with print_block.
114
+ #
115
+ def print_class(name, parent_klass, &block)
116
+ print_block(name, parent_klass, :class, &block)
117
+ end
118
+
119
+ # Use print_block to print a module.
120
+ # Accepts a block for use with print_block.
121
+ #
122
+ def print_module(name, &block)
123
+ print_block(name, nil, :module, &block)
124
+ end
125
+
126
+ # Print a file require.
127
+ #
128
+ # print_require('foo/bar/baz') -> "require 'foo/bar/baz'"
129
+ #
130
+ def print_require(file)
131
+ puts "require '#{file}'"
132
+ end
133
+
134
+ # Puts the given message prefixed by the indent level.
135
+ # If no message is given print a newline.
136
+ #
137
+ def puts(message = nil)
138
+ if message
139
+ @io.puts((" " * current_indent) + message)
140
+ else
141
+ @io.puts
142
+ end
143
+ end
144
+
145
+ # Print the given message raw, no indent.
146
+ #
147
+ def print(contents)
148
+ @io.print(contents)
149
+ end
150
+
151
+ # Returns the contents of the underlying StringIO object.
152
+ #
153
+ def print_contents
154
+ @io.rewind
155
+ @io.read
156
+ end
157
+
158
+ end
159
+ end
160
+ end