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,9 @@
1
+ module Protobuf
2
+ class Error < StandardError; end
3
+ class InvalidWireType < Error; end
4
+ class NotInitializedError < Error; end
5
+ class TagCollisionError < Error; end
6
+ class SerializationError < StandardError; end
7
+ class FieldNotDefinedError < StandardError; end
8
+ class DuplicateFieldNameError < StandardError; end
9
+ end
@@ -0,0 +1,74 @@
1
+ require 'protobuf/field/base_field'
2
+ require 'protobuf/field/bytes_field'
3
+ require 'protobuf/field/float_field'
4
+ require 'protobuf/field/message_field'
5
+ require 'protobuf/field/varint_field'
6
+ require 'protobuf/field/string_field'
7
+ require 'protobuf/field/double_field'
8
+ require 'protobuf/field/enum_field'
9
+ require 'protobuf/field/integer_field'
10
+ require 'protobuf/field/signed_integer_field'
11
+ require 'protobuf/field/uint32_field'
12
+ require 'protobuf/field/uint64_field'
13
+ require 'protobuf/field/int32_field'
14
+ require 'protobuf/field/int64_field'
15
+ require 'protobuf/field/sint32_field'
16
+ require 'protobuf/field/sint64_field'
17
+ require 'protobuf/field/bool_field'
18
+ require 'protobuf/field/sfixed32_field'
19
+ require 'protobuf/field/sfixed64_field'
20
+ require 'protobuf/field/fixed32_field'
21
+ require 'protobuf/field/fixed64_field'
22
+
23
+ module Protobuf
24
+ module Field
25
+
26
+ PRIMITIVE_FIELD_MAP = {
27
+ :double => ::Protobuf::Field::DoubleField,
28
+ :float => ::Protobuf::Field::FloatField,
29
+ :int32 => ::Protobuf::Field::Int32Field,
30
+ :int64 => ::Protobuf::Field::Int64Field,
31
+ :uint32 => ::Protobuf::Field::Uint32Field,
32
+ :uint64 => ::Protobuf::Field::Uint64Field,
33
+ :sint32 => ::Protobuf::Field::Sint32Field,
34
+ :sint64 => ::Protobuf::Field::Sint64Field,
35
+ :fixed32 => ::Protobuf::Field::Fixed32Field,
36
+ :fixed64 => ::Protobuf::Field::Fixed64Field,
37
+ :sfixed32 => ::Protobuf::Field::Sfixed32Field,
38
+ :sfixed64 => ::Protobuf::Field::Sfixed64Field,
39
+ :string => ::Protobuf::Field::StringField,
40
+ :bytes => ::Protobuf::Field::BytesField,
41
+ :bool => ::Protobuf::Field::BoolField,
42
+ }.freeze
43
+
44
+ def self.build(message_class, rule, type, name, tag, options = {})
45
+ field_class(type).new(message_class, rule, field_type(type), name, tag, options)
46
+ end
47
+
48
+ # Returns the field class for primitives,
49
+ # EnumField for types that inherit from Protobuf::Enum,
50
+ # and MessageField for types that inherit from Protobuf::Message.
51
+ #
52
+ def self.field_class(type)
53
+ if PRIMITIVE_FIELD_MAP.key?(type)
54
+ PRIMITIVE_FIELD_MAP[type]
55
+ elsif type < ::Protobuf::Enum
56
+ EnumField
57
+ elsif type < ::Protobuf::Message
58
+ MessageField
59
+ elsif type < ::Protobuf::Field::BaseField
60
+ type
61
+ else
62
+ fail ArgumentError, "Invalid field type #{type}"
63
+ end
64
+ end
65
+
66
+ # Returns the mapped type for primitives,
67
+ # otherwise the given type is returned.
68
+ #
69
+ def self.field_type(type)
70
+ PRIMITIVE_FIELD_MAP.fetch(type) { type }
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,267 @@
1
+ require 'protobuf/field/field_array'
2
+ require 'protobuf/logging'
3
+ require 'protobuf/wire_type'
4
+
5
+ module Protobuf
6
+ module Field
7
+ class BaseField
8
+ include ::Protobuf::Logging
9
+
10
+ ##
11
+ # Constants
12
+ #
13
+
14
+ PACKED_TYPES = [
15
+ ::Protobuf::WireType::VARINT,
16
+ ::Protobuf::WireType::FIXED32,
17
+ ::Protobuf::WireType::FIXED64,
18
+ ].freeze
19
+
20
+ ##
21
+ # Attributes
22
+ #
23
+
24
+ attr_reader :message_class, :name, :options, :rule, :tag, :type_class
25
+
26
+ ##
27
+ # Class Methods
28
+ #
29
+
30
+ def self.default
31
+ nil
32
+ end
33
+
34
+ ##
35
+ # Constructor
36
+ #
37
+
38
+ def initialize(message_class, rule, type_class, name, tag, options)
39
+ @message_class = message_class
40
+ @name = name
41
+ @rule = rule
42
+ @tag = tag
43
+ @type_class = type_class
44
+ @options = options
45
+
46
+ validate_packed_field if packed?
47
+ define_accessor
48
+ end
49
+
50
+ ##
51
+ # Public Instance Methods
52
+ #
53
+
54
+ def acceptable?(_value)
55
+ true
56
+ end
57
+
58
+ def coerce!(value)
59
+ value
60
+ end
61
+
62
+ def decode(_bytes)
63
+ fail NotImplementedError, "#{self.class.name}##{__method__}"
64
+ end
65
+
66
+ def default
67
+ options[:default]
68
+ end
69
+
70
+ def default_value
71
+ @default_value ||= case
72
+ when repeated? then ::Protobuf::Field::FieldArray.new(self).freeze
73
+ when required? then nil
74
+ when optional? then typed_default_value
75
+ end
76
+ end
77
+
78
+ def deprecated?
79
+ options.key?(:deprecated)
80
+ end
81
+
82
+ def encode(_value)
83
+ fail NotImplementedError, "#{self.class.name}##{__method__}"
84
+ end
85
+
86
+ def extension?
87
+ options.key?(:extension)
88
+ end
89
+
90
+ def enum?
91
+ false
92
+ end
93
+
94
+ def getter
95
+ name
96
+ end
97
+
98
+ def message?
99
+ false
100
+ end
101
+
102
+ def optional?
103
+ rule == :optional
104
+ end
105
+
106
+ def packed?
107
+ repeated? && options.key?(:packed)
108
+ end
109
+
110
+ def repeated?
111
+ rule == :repeated
112
+ end
113
+
114
+ def repeated_message?
115
+ repeated? && message?
116
+ end
117
+
118
+ def required?
119
+ rule == :required
120
+ end
121
+
122
+ # FIXME: need to cleanup (rename) this warthog of a method.
123
+ def set(message_instance, bytes)
124
+ if packed?
125
+ array = message_instance.__send__(getter)
126
+ method = \
127
+ case wire_type
128
+ when ::Protobuf::WireType::FIXED32 then :read_fixed32
129
+ when ::Protobuf::WireType::FIXED64 then :read_fixed64
130
+ when ::Protobuf::WireType::VARINT then :read_varint
131
+ end
132
+ stream = StringIO.new(bytes)
133
+
134
+ until stream.eof?
135
+ array << decode(::Protobuf::Decoder.__send__(method, stream))
136
+ end
137
+ else
138
+ value = decode(bytes)
139
+ if repeated?
140
+ message_instance.__send__(getter) << value
141
+ else
142
+ message_instance.__send__(setter, value)
143
+ end
144
+ end
145
+ end
146
+
147
+ def setter
148
+ @setter ||= "#{name}="
149
+ end
150
+
151
+ # FIXME: add packed, deprecated, extension options to to_s output
152
+ def to_s
153
+ "#{rule} #{type_class} #{name} = #{tag} #{default ? "[default=#{default.inspect}]" : ''}"
154
+ end
155
+
156
+ ::Protobuf.deprecator.define_deprecated_methods(self, :type => :type_class)
157
+
158
+ def wire_type
159
+ ::Protobuf::WireType::VARINT
160
+ end
161
+
162
+ private
163
+
164
+ ##
165
+ # Private Instance Methods
166
+ #
167
+
168
+ def define_accessor
169
+ if repeated?
170
+ define_array_getter
171
+ define_array_setter
172
+ else
173
+ define_getter
174
+ define_setter
175
+ end
176
+ end
177
+
178
+ def define_array_getter
179
+ field = self
180
+ method_name = field.getter
181
+
182
+ message_class.class_eval do
183
+ define_method(method_name) do
184
+ @values[field.name] ||= ::Protobuf::Field::FieldArray.new(field)
185
+ end
186
+ end
187
+
188
+ ::Protobuf.field_deprecator.deprecate_method(message_class, method_name) if field.deprecated?
189
+ end
190
+
191
+ def define_array_setter
192
+ field = self
193
+ method_name = field.setter
194
+
195
+ message_class.class_eval do
196
+ define_method(method_name) do |val|
197
+ if val.is_a?(Array)
198
+ val = val.dup
199
+ val.compact!
200
+ else
201
+ fail TypeError, <<-TYPE_ERROR
202
+ Expected repeated value of type '#{field.type_class}'
203
+ Got '#{val.class}' for repeated protobuf field #{field.name}
204
+ TYPE_ERROR
205
+ end
206
+
207
+ if val.nil? || (val.respond_to?(:empty?) && val.empty?)
208
+ @values.delete(field.name)
209
+ else
210
+ @values[field.name] ||= ::Protobuf::Field::FieldArray.new(field)
211
+ @values[field.name].replace(val)
212
+ end
213
+ end
214
+ end
215
+
216
+ ::Protobuf.field_deprecator.deprecate_method(message_class, method_name) if field.deprecated?
217
+ end
218
+
219
+ def define_getter
220
+ field = self
221
+ method_name = field.getter
222
+
223
+ message_class.class_eval do
224
+ define_method(method_name) do
225
+ @values.fetch(field.name, field.default_value)
226
+ end
227
+ end
228
+
229
+ ::Protobuf.field_deprecator.deprecate_method(message_class, method_name) if field.deprecated?
230
+ end
231
+
232
+ def define_setter
233
+ field = self
234
+ method_name = field.setter
235
+
236
+ message_class.class_eval do
237
+ define_method(method_name) do |val|
238
+ if val.nil? || (val.respond_to?(:empty?) && val.empty?)
239
+ @values.delete(field.name)
240
+ elsif field.acceptable?(val)
241
+ @values[field.name] = field.coerce!(val)
242
+ else
243
+ fail TypeError, "Unacceptable value #{val} for field #{field.name} of type #{field.type_class}"
244
+ end
245
+ end
246
+ end
247
+
248
+ ::Protobuf.field_deprecator.deprecate_method(message_class, method_name) if field.deprecated?
249
+ end
250
+
251
+ def typed_default_value
252
+ if default.nil?
253
+ self.class.default
254
+ else
255
+ default
256
+ end
257
+ end
258
+
259
+ def validate_packed_field
260
+ if packed? && ! ::Protobuf::Field::BaseField::PACKED_TYPES.include?(wire_type)
261
+ fail "Can't use packed encoding for '#{type_class}' type"
262
+ end
263
+ end
264
+
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,59 @@
1
+ require 'protobuf/field/varint_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class BoolField < VarintField
6
+
7
+ ##
8
+ # Class Methods
9
+ #
10
+
11
+ def self.default
12
+ false
13
+ end
14
+
15
+ ##
16
+ # Public Instance Methods
17
+ # #
18
+
19
+ def acceptable?(val)
20
+ [true, false].include?(val) || %w(true false).include?(val)
21
+ end
22
+
23
+ def coerce!(val)
24
+ if val == 'true'
25
+ true
26
+ elsif val == 'false'
27
+ false
28
+ else
29
+ val
30
+ end
31
+ end
32
+
33
+ def decode(value)
34
+ value == 1
35
+ end
36
+
37
+ def encode(value)
38
+ [value ? 1 : 0].pack('C')
39
+ end
40
+
41
+ private
42
+
43
+ ##
44
+ # Private Instance Methods
45
+ #
46
+
47
+ def define_getter
48
+ super
49
+
50
+ field = self
51
+
52
+ message_class.class_eval do
53
+ alias_method "#{field.getter}?", field.getter
54
+ end
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,82 @@
1
+ require 'protobuf/wire_type'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class BytesField < BaseField
6
+
7
+ ##
8
+ # Constants
9
+ #
10
+
11
+ BYTES_ENCODING = Encoding::BINARY
12
+
13
+ ##
14
+ # Class Methods
15
+ #
16
+
17
+ def self.default
18
+ ''
19
+ end
20
+
21
+ ##
22
+ # Public Instance Methods
23
+ #
24
+
25
+ def acceptable?(val)
26
+ val.nil? || val.is_a?(String) || val.is_a?(Symbol) || val.is_a?(::Protobuf::Message)
27
+ end
28
+
29
+ def decode(bytes)
30
+ bytes_to_decode = bytes.dup
31
+ bytes_to_decode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
32
+ bytes_to_decode
33
+ end
34
+
35
+ def encode(value)
36
+ value_to_encode = value.dup
37
+ value_to_encode = value.encode if value.is_a?(::Protobuf::Message)
38
+ value_to_encode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
39
+
40
+ string_size = ::Protobuf::Field::VarintField.encode(value_to_encode.size)
41
+ string_size << value_to_encode
42
+ end
43
+
44
+ def wire_type
45
+ ::Protobuf::WireType::LENGTH_DELIMITED
46
+ end
47
+
48
+ private
49
+
50
+ ##
51
+ # Private Instance Methods
52
+ #
53
+
54
+ def define_setter
55
+ field = self
56
+ method_name = field.setter
57
+
58
+ message_class.class_eval do
59
+ define_method(method_name) do |val|
60
+ begin
61
+ val = "#{val}" if val.is_a?(Symbol)
62
+
63
+ if val.nil?
64
+ @values.delete(field.name)
65
+ elsif field.acceptable?(val)
66
+ @values[field.name] = val.dup
67
+ else
68
+ fail TypeError, "Unacceptable value #{val} for field #{field.name} of type #{field.type_class}"
69
+ end
70
+ rescue NoMethodError => ex
71
+ logger.error { ex.message }
72
+ logger.error { ex.backtrace.join("\n") }
73
+ raise TypeError, "Got NoMethodError attempting to set #{val} for field #{field.name} of type #{field.type_class}: #{ex.message}"
74
+ end
75
+ end
76
+ end
77
+
78
+ ::Protobuf.field_deprecator.deprecate_method(message_class, method_name) if field.deprecated?
79
+ end
80
+ end
81
+ end
82
+ end