protobuf-core 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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