protobuf 1.0.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 (113) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +28 -0
  4. data/README.md +216 -0
  5. data/Rakefile +1 -0
  6. data/bin/rpc_server +117 -0
  7. data/bin/rprotoc +46 -0
  8. data/examples/addressbook.pb.rb +55 -0
  9. data/examples/addressbook.proto +24 -0
  10. data/examples/reading_a_message.rb +32 -0
  11. data/examples/writing_a_message.rb +46 -0
  12. data/lib/protobuf.rb +6 -0
  13. data/lib/protobuf/common/exceptions.rb +11 -0
  14. data/lib/protobuf/common/logger.rb +64 -0
  15. data/lib/protobuf/common/util.rb +59 -0
  16. data/lib/protobuf/common/wire_type.rb +10 -0
  17. data/lib/protobuf/compiler/compiler.rb +52 -0
  18. data/lib/protobuf/compiler/nodes.rb +323 -0
  19. data/lib/protobuf/compiler/proto.y +216 -0
  20. data/lib/protobuf/compiler/proto2.ebnf +79 -0
  21. data/lib/protobuf/compiler/proto_parser.rb +1425 -0
  22. data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
  23. data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
  24. data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
  25. data/lib/protobuf/compiler/template/rpc_service_implementation.erb +42 -0
  26. data/lib/protobuf/compiler/visitors.rb +302 -0
  27. data/lib/protobuf/descriptor/descriptor.proto +286 -0
  28. data/lib/protobuf/descriptor/descriptor.rb +55 -0
  29. data/lib/protobuf/descriptor/descriptor_builder.rb +143 -0
  30. data/lib/protobuf/descriptor/descriptor_proto.rb +138 -0
  31. data/lib/protobuf/descriptor/enum_descriptor.rb +33 -0
  32. data/lib/protobuf/descriptor/field_descriptor.rb +49 -0
  33. data/lib/protobuf/descriptor/file_descriptor.rb +37 -0
  34. data/lib/protobuf/message/decoder.rb +83 -0
  35. data/lib/protobuf/message/encoder.rb +46 -0
  36. data/lib/protobuf/message/enum.rb +62 -0
  37. data/lib/protobuf/message/extend.rb +8 -0
  38. data/lib/protobuf/message/field.rb +701 -0
  39. data/lib/protobuf/message/message.rb +402 -0
  40. data/lib/protobuf/message/protoable.rb +38 -0
  41. data/lib/protobuf/rpc/buffer.rb +74 -0
  42. data/lib/protobuf/rpc/client.rb +268 -0
  43. data/lib/protobuf/rpc/client_connection.rb +225 -0
  44. data/lib/protobuf/rpc/error.rb +34 -0
  45. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  46. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  47. data/lib/protobuf/rpc/rpc.pb.rb +107 -0
  48. data/lib/protobuf/rpc/server.rb +183 -0
  49. data/lib/protobuf/rpc/service.rb +244 -0
  50. data/lib/protobuf/rpc/stat.rb +70 -0
  51. data/lib/protobuf/version.rb +3 -0
  52. data/proto/rpc.proto +73 -0
  53. data/protobuf.gemspec +25 -0
  54. data/script/mk_parser +2 -0
  55. data/spec/functional/embedded_service_spec.rb +7 -0
  56. data/spec/proto/test.pb.rb +31 -0
  57. data/spec/proto/test.proto +31 -0
  58. data/spec/proto/test_service.rb +30 -0
  59. data/spec/proto/test_service_impl.rb +17 -0
  60. data/spec/spec_helper.rb +26 -0
  61. data/spec/unit/client_spec.rb +128 -0
  62. data/spec/unit/common/logger_spec.rb +121 -0
  63. data/spec/unit/enum_spec.rb +13 -0
  64. data/spec/unit/message_spec.rb +67 -0
  65. data/spec/unit/server_spec.rb +27 -0
  66. data/spec/unit/service_spec.rb +75 -0
  67. data/test/check_unbuild.rb +30 -0
  68. data/test/data/data.bin +3 -0
  69. data/test/data/data_source.py +14 -0
  70. data/test/data/types.bin +0 -0
  71. data/test/data/types_source.py +22 -0
  72. data/test/data/unk.png +0 -0
  73. data/test/proto/addressbook.pb.rb +66 -0
  74. data/test/proto/addressbook.proto +33 -0
  75. data/test/proto/addressbook_base.pb.rb +58 -0
  76. data/test/proto/addressbook_base.proto +26 -0
  77. data/test/proto/addressbook_ext.pb.rb +20 -0
  78. data/test/proto/addressbook_ext.proto +6 -0
  79. data/test/proto/collision.pb.rb +17 -0
  80. data/test/proto/collision.proto +5 -0
  81. data/test/proto/ext_collision.pb.rb +24 -0
  82. data/test/proto/ext_collision.proto +8 -0
  83. data/test/proto/ext_range.pb.rb +22 -0
  84. data/test/proto/ext_range.proto +7 -0
  85. data/test/proto/float_default.proto +10 -0
  86. data/test/proto/lowercase.pb.rb +30 -0
  87. data/test/proto/lowercase.proto +9 -0
  88. data/test/proto/merge.pb.rb +39 -0
  89. data/test/proto/merge.proto +15 -0
  90. data/test/proto/nested.pb.rb +30 -0
  91. data/test/proto/nested.proto +9 -0
  92. data/test/proto/optional_field.pb.rb +35 -0
  93. data/test/proto/optional_field.proto +12 -0
  94. data/test/proto/packed.pb.rb +22 -0
  95. data/test/proto/packed.proto +6 -0
  96. data/test/proto/rpc.proto +6 -0
  97. data/test/proto/types.pb.rb +84 -0
  98. data/test/proto/types.proto +37 -0
  99. data/test/test_addressbook.rb +56 -0
  100. data/test/test_compiler.rb +325 -0
  101. data/test/test_descriptor.rb +122 -0
  102. data/test/test_enum_value.rb +41 -0
  103. data/test/test_extension.rb +36 -0
  104. data/test/test_lowercase.rb +11 -0
  105. data/test/test_message.rb +128 -0
  106. data/test/test_optional_field.rb +103 -0
  107. data/test/test_packed_field.rb +40 -0
  108. data/test/test_parse.rb +15 -0
  109. data/test/test_repeated_types.rb +132 -0
  110. data/test/test_serialize.rb +61 -0
  111. data/test/test_standard_message.rb +96 -0
  112. data/test/test_types.rb +226 -0
  113. metadata +261 -0
@@ -0,0 +1,83 @@
1
+ require 'protobuf/common/wire_type'
2
+ require 'protobuf/common/exceptions'
3
+
4
+ module Protobuf
5
+
6
+ module Decoder
7
+
8
+ module_function
9
+
10
+ # Read bytes from +stream+ and pass to +message+ object.
11
+ def decode(stream, message)
12
+ until stream.eof?
13
+ tag, wire_type = read_key(stream)
14
+ bytes =
15
+ case wire_type
16
+ when WireType::VARINT
17
+ read_varint(stream)
18
+ when WireType::FIXED64
19
+ read_fixed64(stream)
20
+ when WireType::LENGTH_DELIMITED
21
+ read_length_delimited(stream)
22
+ when WireType::START_GROUP
23
+ read_start_group(stream)
24
+ when WireType::END_GROUP
25
+ read_end_group(stream)
26
+ when WireType::FIXED32
27
+ read_fixed32(stream)
28
+ else
29
+ raise InvalidWireType, wire_type
30
+ end
31
+ message.set_field(tag, bytes)
32
+ end
33
+ message
34
+ end
35
+
36
+ # Read key pair (tag and wire-type) from +stream+.
37
+ def read_key(stream)
38
+ bits = read_varint(stream)
39
+ wire_type = bits & 0x07
40
+ tag = bits >> 3
41
+ [tag, wire_type]
42
+ end
43
+
44
+ # Read varint integer value from +stream+.
45
+ def read_varint(stream)
46
+ read_method = stream.respond_to?(:readbyte) ? :readbyte : :readchar
47
+ value = index = 0
48
+ begin
49
+ byte = stream.__send__(read_method)
50
+ value |= (byte & 0x7f) << (7 * index)
51
+ index += 1
52
+ end while (byte & 0x80).nonzero?
53
+ value
54
+ end
55
+
56
+ # Read 32-bit string value from +stream+.
57
+ def read_fixed32(stream)
58
+ stream.read(4)
59
+ end
60
+
61
+ # Read 64-bit string value from +stream+.
62
+ def read_fixed64(stream)
63
+ stream.read(8)
64
+ end
65
+
66
+ # Read length-delimited string value from +stream+.
67
+ def read_length_delimited(stream)
68
+ value_length = read_varint(stream)
69
+ stream.read(value_length)
70
+ end
71
+
72
+ # Not implemented.
73
+ def read_start_group(stream)
74
+ raise NotImplementedError, 'Group is deprecated.'
75
+ end
76
+
77
+ # Not implemented.
78
+ def read_end_group(stream)
79
+ raise NotImplementedError, 'Group is deprecated.'
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,46 @@
1
+ require 'protobuf/common/wire_type'
2
+ require 'protobuf/common/exceptions'
3
+
4
+ module Protobuf
5
+
6
+ module Encoder
7
+
8
+ module_function
9
+
10
+ # Encode +message+ and write to +stream+.
11
+ def encode(stream, message)
12
+ # FIXME make this not as ghetto
13
+ raise NotInitializedError, "Message %s is not initialized (one or more fields is improperly set): %s" % [message.class.name, JSON.parse(message.to_json)] unless message.initialized?
14
+
15
+ message.each_field do |field, value|
16
+ next unless message.has_field?(field.name)
17
+
18
+ if field.repeated?
19
+ if field.packed?
20
+ key = (field.tag << 3) | WireType::LENGTH_DELIMITED
21
+ packed_value = value.map {|val| field.encode(val) }.join
22
+ stream.write(Field::VarintField.encode(key))
23
+ stream.write(Field::VarintField.encode(packed_value.size))
24
+ stream.write(packed_value)
25
+ else
26
+ value.each do |val|
27
+ write_pair(stream, field, val)
28
+ end
29
+ end
30
+ else
31
+ write_pair(stream, field, value)
32
+ end
33
+ end
34
+ end
35
+
36
+ # Encode key and value, and write to +stream+.
37
+ def write_pair(stream, field, value)
38
+ key = (field.tag << 3) | field.wire_type
39
+ key_bytes = Field::VarintField.encode(key)
40
+ stream.write(key_bytes)
41
+ bytes = field.encode(value)
42
+ stream.write(bytes)
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,62 @@
1
+ require 'delegate'
2
+ require 'protobuf/descriptor/enum_descriptor'
3
+ require 'protobuf/message/protoable'
4
+
5
+ module Protobuf
6
+ class Enum
7
+ class <<self
8
+ include Protoable
9
+
10
+ attr_reader :values
11
+
12
+ def name_by_value(value)
13
+ if not defined?(@values)
14
+ constants.find {|c| const_get(c) == value} # for compatibility
15
+ else
16
+ @values_index ||= @values.inject({}) {|hash, (n, v)| hash[v.value] = n; hash }
17
+ @values_index[value]
18
+ end
19
+ end
20
+
21
+ alias get_name_by_tag name_by_value
22
+
23
+ def valid_tag?(tag)
24
+ !! name_by_value(tag)
25
+ end
26
+
27
+ def descriptor
28
+ @descriptor ||= Descriptor::EnumDescriptor.new(self)
29
+ end
30
+
31
+ private
32
+
33
+ def define(name, value)
34
+ enum_value = EnumValue.new(self, name, value)
35
+ const_set(name, enum_value)
36
+ @values ||= {}
37
+ @values[name] = enum_value
38
+ end
39
+ end
40
+ end
41
+
42
+ class EnumValue < SimpleDelegator
43
+
44
+ attr_reader :parent_class, :name, :value
45
+
46
+ def initialize(parent_class, name, value)
47
+ @parent_class = parent_class
48
+ @name = name
49
+ @value = value
50
+ super(@value)
51
+ end
52
+
53
+ def to_s
54
+ @name.to_s
55
+ end
56
+
57
+ def inspect
58
+ "\#<#{self.class} #{@parent_class}::#{@name}=#{@value}>"
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,8 @@
1
+ require 'protobuf/message/message'
2
+
3
+ module Protobuf
4
+ class Extend < Message
5
+ MIN = -1.0/0
6
+ MAX = 1.0/0
7
+ end
8
+ end
@@ -0,0 +1,701 @@
1
+ require 'protobuf/common/util'
2
+ require 'protobuf/common/wire_type'
3
+ require 'protobuf/descriptor/field_descriptor'
4
+
5
+ module Protobuf
6
+ module Field
7
+
8
+ PREDEFINED_TYPES = [
9
+ :double, :float,
10
+ :int32, :int64,
11
+ :uint32, :uint64,
12
+ :sint32, :sint64,
13
+ :fixed32, :fixed64,
14
+ :sfixed32, :sfixed64,
15
+ :string, :bytes,
16
+ :bool,
17
+ ].freeze
18
+
19
+ def self.build(message_class, rule, type, name, tag, options={})
20
+ field_class = \
21
+ if PREDEFINED_TYPES.include?(type)
22
+ const_get("#{type.to_s.capitalize}Field")
23
+ else
24
+ FieldProxy
25
+ end
26
+ field_class.new(message_class, rule, type, name, tag, options)
27
+ end
28
+
29
+ class BaseField
30
+
31
+ def self.descriptor
32
+ @descriptor ||= Descriptor::FieldDescriptor.new
33
+ end
34
+
35
+ def self.default
36
+ nil
37
+ end
38
+
39
+ attr_reader :message_class, :rule, :type, :name, :tag, :default
40
+ attr_reader :default_value
41
+
42
+ def descriptor
43
+ @descriptor ||= Descriptor::FieldDescriptor.new(self)
44
+ end
45
+
46
+ def initialize(message_class, rule, type, name, tag, options)
47
+ @message_class, @rule, @type, @name, @tag = \
48
+ message_class, rule, type, name, tag
49
+
50
+ @default = options.delete(:default)
51
+ @extension = options.delete(:extension)
52
+ @packed = repeated? && options.delete(:packed)
53
+ unless options.empty?
54
+ warn "WARNING: Invalid options: #{options.inspect} (in #{@message_class.name.split('::').last}.#{@name})"
55
+ end
56
+ if packed? && ! [WireType::VARINT, WireType::FIXED32, WireType::FIXED64].include?(wire_type)
57
+ raise "Can't use packed encoding for `#{@type}' type"
58
+ end
59
+
60
+ @default_value = \
61
+ case @rule
62
+ when :repeated
63
+ FieldArray.new(self).freeze
64
+ when :required
65
+ nil
66
+ when :optional
67
+ typed_default_value
68
+ end
69
+
70
+ define_accessor
71
+ end
72
+
73
+ def ready?
74
+ true
75
+ end
76
+
77
+ def initialized?(message_instance)
78
+ value = message_instance.__send__(@name)
79
+ case @rule
80
+ when :required
81
+ ! value.nil? && (! kind_of?(MessageField) || value.initialized?)
82
+ when :repeated
83
+ value.all? {|msg| ! kind_of?(MessageField) || msg.initialized? }
84
+ when :optional
85
+ value.nil? || ! kind_of?(MessageField) || value.initialized?
86
+ end
87
+ end
88
+
89
+ # Decode +bytes+ and pass to +message_instance+.
90
+ def set(message_instance, bytes)
91
+ if packed?
92
+ array = message_instance.__send__(@name)
93
+ method = \
94
+ case wire_type
95
+ when WireType::FIXED32 then :read_fixed32
96
+ when WireType::FIXED64 then :read_fixed64
97
+ when WireType::VARINT then :read_varint
98
+ end
99
+ stream = StringIO.new(bytes)
100
+ until stream.eof?
101
+ array << decode(Decoder.__send__(method, stream))
102
+ end
103
+ else
104
+ value = decode(bytes)
105
+ if repeated?
106
+ message_instance.__send__(@name) << value
107
+ else
108
+ message_instance.__send__("#{@name}=", value)
109
+ end
110
+ end
111
+ end
112
+
113
+ # Decode +bytes+ and return a field value.
114
+ def decode(bytes)
115
+ raise NotImplementedError, "#{self.class.name}\#decode"
116
+ end
117
+
118
+ # Encode +value+ and return a byte string.
119
+ def encode(value)
120
+ raise NotImplementedError, "#{self.class.name}\#encode"
121
+ end
122
+
123
+ # Merge +value+ with +message_instance+.
124
+ def merge(message_instance, value)
125
+ if repeated?
126
+ merge_array(message_instance, value)
127
+ else
128
+ merge_value(message_instance, value)
129
+ end
130
+ end
131
+
132
+ # Is this a repeated field?
133
+ def repeated?
134
+ @rule == :repeated
135
+ end
136
+
137
+ # Is this a required field?
138
+ def required?
139
+ @rule == :required
140
+ end
141
+
142
+ # Is this a optional field?
143
+ def optional?
144
+ @rule == :optional
145
+ end
146
+
147
+ # Is this a packed repeated field?
148
+ def packed?
149
+ !!@packed
150
+ end
151
+
152
+ # Upper limit for this field.
153
+ def max
154
+ self.class.max
155
+ end
156
+
157
+ # Lower limit for this field.
158
+ def min
159
+ self.class.min
160
+ end
161
+
162
+ # Is a +value+ acceptable for this field?
163
+ def acceptable?(value)
164
+ true
165
+ end
166
+
167
+ def to_s
168
+ "#{@rule} #{@type} #{@name} = #{@tag} #{@default ? "[default=#{@default.inspect}]" : ''}"
169
+ end
170
+
171
+ private
172
+
173
+ def define_accessor
174
+ define_getter
175
+ if repeated?
176
+ define_array_setter
177
+ else
178
+ define_setter
179
+ end
180
+ end
181
+
182
+ def define_getter
183
+ field = self
184
+ @message_class.class_eval do
185
+ define_method(field.name) do
186
+ if @values.has_key?(field.name)
187
+ @values[field.name]
188
+ else
189
+ field.default_value
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ def define_setter
196
+ field = self
197
+ @message_class.class_eval do
198
+ define_method("#{field.name}=") do |val|
199
+ if val.nil?
200
+ @values.delete(field.name)
201
+ elsif field.acceptable?(val)
202
+ @values[field.name] = val
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def define_array_setter
209
+ field = self
210
+ @message_class.class_eval do
211
+ define_method("#{field.name}=") do |val|
212
+ @values[field.name].replace(val)
213
+ end
214
+ end
215
+ end
216
+
217
+ def merge_array(message_instance, value)
218
+ message_instance.__send__(@name).concat(value)
219
+ end
220
+
221
+ def merge_value(message_instance, value)
222
+ message_instance.__send__("#{@name}=", value)
223
+ end
224
+
225
+ def typed_default_value
226
+ if @default.nil?
227
+ self.class.default
228
+ else
229
+ @default
230
+ end
231
+ end
232
+
233
+ end # BaseField
234
+
235
+
236
+ class FieldProxy
237
+
238
+ def initialize(message_class, rule, type, name, tag, options)
239
+ @message_class, @rule, @type, @name, @tag, @options =
240
+ message_class, rule, type, name, tag, options
241
+ end
242
+
243
+ def ready?
244
+ false
245
+ end
246
+
247
+ def setup
248
+ type = typename_to_class(@message_class, @type)
249
+ field_class = \
250
+ if type < Enum
251
+ EnumField
252
+ elsif type < Message
253
+ MessageField
254
+ else
255
+ raise TypeError, type.inspect
256
+ end
257
+ field_class.new(@message_class, @rule, type, @name, @tag, @options)
258
+ end
259
+
260
+ private
261
+
262
+ def typename_to_class(message_class, type)
263
+ names = type.to_s.split('::').map {|s| Util.camelize(s) }
264
+ outer = message_class.to_s.split('::')
265
+ args = (Object.method(:const_defined?).arity == 1) ? [] : [false]
266
+ while
267
+ mod = outer.empty? ? Object : eval(outer.join('::'))
268
+ mod = names.inject(mod) {|m, s|
269
+ m && m.const_defined?(s, *args) && m.const_get(s)
270
+ }
271
+ break if mod
272
+ raise NameError.new("type not found: #{type}", type) if outer.empty?
273
+ outer.pop
274
+ end
275
+ mod
276
+ end
277
+
278
+ end
279
+
280
+ class FieldArray < Array
281
+
282
+ def initialize(field)
283
+ @field = field
284
+ end
285
+
286
+ def []=(nth, val)
287
+ super(nth, normalize(val))
288
+ end
289
+
290
+ def <<(val)
291
+ super(normalize(val))
292
+ end
293
+
294
+ def push(val)
295
+ super(normalize(val))
296
+ end
297
+
298
+ def unshift(val)
299
+ super(normalize(val))
300
+ end
301
+
302
+ def replace(val)
303
+ raise TypeError unless val.is_a?(Array)
304
+ val = val.map {|v| normalize(v)}
305
+ super(val)
306
+ end
307
+
308
+ def to_s
309
+ "[#{@field.name}]"
310
+ end
311
+
312
+ private
313
+
314
+ def normalize(val)
315
+ raise TypeError unless @field.acceptable?(val)
316
+ if @field.is_a?(MessageField) && val.is_a?(Hash)
317
+ @field.type.new(val)
318
+ else
319
+ val
320
+ end
321
+ end
322
+
323
+ end
324
+
325
+ # Field class for +bytes+ type.
326
+ class BytesField < BaseField
327
+ def self.default
328
+ ''
329
+ end
330
+
331
+ def wire_type
332
+ WireType::LENGTH_DELIMITED
333
+ end
334
+
335
+ def acceptable?(val)
336
+ raise TypeError unless val.instance_of?(String)
337
+ true
338
+ end
339
+
340
+ def decode(bytes)
341
+ bytes.force_encoding('ASCII-8BIT') if bytes.respond_to?(:force_encoding)
342
+ bytes
343
+ end
344
+
345
+ def encode(value)
346
+ value = value.dup
347
+ value.force_encoding('ASCII-8BIT') if value.respond_to?(:force_encoding)
348
+ string_size = VarintField.encode(value.size)
349
+ string_size << value
350
+ end
351
+ end
352
+
353
+ class StringField < BytesField
354
+ def decode(bytes)
355
+ bytes.force_encoding('UTF-8') if bytes.respond_to?(:force_encoding)
356
+ bytes
357
+ end
358
+ end
359
+
360
+ class VarintField < BaseField
361
+ INT32_MAX = 2**31 - 1
362
+ INT32_MIN = -2**31
363
+ INT64_MAX = 2**63 - 1
364
+ INT64_MIN = -2**63
365
+ UINT32_MAX = 2**32 - 1
366
+ UINT64_MAX = 2**64 - 1
367
+
368
+ class <<self
369
+ def default
370
+ 0
371
+ end
372
+
373
+ def decode(bytes)
374
+ value = 0
375
+ bytes.each_with_index do |byte, index|
376
+ value |= byte << (7 * index)
377
+ end
378
+ value
379
+ end
380
+
381
+ def encode(value)
382
+ raise RangeError, "#{value} is negative" if value < 0
383
+ return [value].pack('C') if value < 128
384
+ bytes = []
385
+ until value == 0
386
+ bytes << (0x80 | (value & 0x7f))
387
+ value >>= 7
388
+ end
389
+ bytes[-1] &= 0x7f
390
+ bytes.pack('C*')
391
+ end
392
+ end
393
+
394
+ def wire_type
395
+ WireType::VARINT
396
+ end
397
+
398
+ def decode(value)
399
+ value
400
+ end
401
+
402
+ def encode(value)
403
+ self.class.encode(value)
404
+ end
405
+
406
+ def acceptable?(val)
407
+ raise TypeError, val.class.name unless val.is_a?(Integer)
408
+ raise RangeError if val < min || max < val
409
+ true
410
+ end
411
+ end
412
+
413
+ # Base class for int32 and int64
414
+ class IntegerField < VarintField
415
+ def encode(value)
416
+ # original Google's library uses 64bits integer for negative value
417
+ VarintField.encode(value & 0xffff_ffff_ffff_ffff)
418
+ end
419
+
420
+ def decode(value)
421
+ value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero?
422
+ value
423
+ end
424
+ end
425
+
426
+ class Int32Field < IntegerField
427
+ def self.max; INT32_MAX; end
428
+ def self.min; INT32_MIN; end
429
+ end
430
+
431
+ class Int64Field < IntegerField
432
+ def self.max; INT64_MAX; end
433
+ def self.min; INT64_MIN; end
434
+ end
435
+
436
+ class Uint32Field < VarintField
437
+ def self.max; UINT32_MAX; end
438
+ def self.min; 0; end
439
+ end
440
+
441
+ class Uint64Field < VarintField
442
+ def self.max; UINT64_MAX; end
443
+ def self.min; 0; end
444
+ end
445
+
446
+ # Base class for sint32 and sint64
447
+ class SignedIntegerField < VarintField
448
+ def decode(value)
449
+ if (value & 1).zero?
450
+ value >> 1 # positive value
451
+ else
452
+ ~value >> 1 # negative value
453
+ end
454
+ end
455
+
456
+ def encode(value)
457
+ if value >= 0
458
+ VarintField.encode(value << 1)
459
+ else
460
+ VarintField.encode(~(value << 1))
461
+ end
462
+ end
463
+ end
464
+
465
+ class Sint32Field < SignedIntegerField
466
+ def self.max; INT32_MAX; end
467
+ def self.min; INT32_MIN; end
468
+ end
469
+
470
+ class Sint64Field < SignedIntegerField
471
+ def self.max; INT64_MAX; end
472
+ def self.min; INT64_MIN; end
473
+ end
474
+
475
+ class FloatField < BaseField
476
+ def self.default; 0.0; end
477
+ def self.max; 1.0/0; end
478
+ def self.min; -1.0/0; end
479
+
480
+ def wire_type
481
+ WireType::FIXED32
482
+ end
483
+
484
+ def decode(bytes)
485
+ bytes.unpack('e').first
486
+ end
487
+
488
+ def encode(value)
489
+ [value].pack('e')
490
+ end
491
+
492
+ def acceptable?(val)
493
+ raise TypeError, val.class.name unless val.is_a?(Numeric)
494
+ raise RangeError if val < min || max < val
495
+ true
496
+ end
497
+ end
498
+
499
+ class DoubleField < FloatField
500
+ def wire_type
501
+ WireType::FIXED64
502
+ end
503
+
504
+ def decode(bytes)
505
+ bytes.unpack('E').first
506
+ end
507
+
508
+ def encode(value)
509
+ [value].pack('E')
510
+ end
511
+ end
512
+
513
+ class Fixed32Field < Uint32Field
514
+ def wire_type
515
+ WireType::FIXED32
516
+ end
517
+
518
+ def decode(bytes)
519
+ bytes.unpack('V').first
520
+ end
521
+
522
+ def encode(value)
523
+ [value].pack('V')
524
+ end
525
+ end
526
+
527
+ class Fixed64Field < Uint64Field
528
+ def wire_type
529
+ WireType::FIXED64
530
+ end
531
+
532
+ def decode(bytes)
533
+ # we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
534
+ values = bytes.unpack('VV')
535
+ values[0] + (values[1] << 32)
536
+ end
537
+
538
+ def encode(value)
539
+ # we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
540
+ [value & 0xffff_ffff, value >> 32].pack('VV')
541
+ end
542
+ end
543
+
544
+ class Sfixed32Field < Int32Field
545
+ def wire_type
546
+ WireType::FIXED32
547
+ end
548
+
549
+ def decode(bytes)
550
+ value = bytes.unpack('V').first
551
+ value -= 0x1_0000_0000 if (value & 0x8000_0000).nonzero?
552
+ value
553
+ end
554
+
555
+ def encode(value)
556
+ [value].pack('V')
557
+ end
558
+ end
559
+
560
+ class Sfixed64Field < Int64Field
561
+ def wire_type
562
+ WireType::FIXED64
563
+ end
564
+
565
+ def decode(bytes)
566
+ # we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
567
+ values = bytes.unpack('VV')
568
+ value = values[0] + (values[1] << 32)
569
+ value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero?
570
+ value
571
+ end
572
+
573
+ def encode(value)
574
+ # we don't use 'Q' for pack/unpack. 'Q' is machine-dependent.
575
+ [value & 0xffff_ffff, value >> 32].pack('VV')
576
+ end
577
+ end
578
+
579
+ class BoolField < VarintField
580
+ def self.default
581
+ false
582
+ end
583
+
584
+ def acceptable?(val)
585
+ raise TypeError unless [true, false].include?(val)
586
+ true
587
+ end
588
+
589
+ def decode(value)
590
+ value == 1
591
+ end
592
+
593
+ def encode(value)
594
+ [value ? 1 : 0].pack('C')
595
+ end
596
+ end
597
+
598
+
599
+ class MessageField < BaseField
600
+ def wire_type
601
+ WireType::LENGTH_DELIMITED
602
+ end
603
+
604
+ def acceptable?(val)
605
+ raise TypeError unless val.instance_of?(type) || val.instance_of?(Hash)
606
+ true
607
+ end
608
+
609
+ def decode(bytes)
610
+ message = type.new
611
+ message.parse_from_string(bytes)
612
+ message
613
+ end
614
+
615
+ def encode(value)
616
+ bytes = value.serialize_to_string
617
+ result = VarintField.encode(bytes.size)
618
+ result << bytes
619
+ end
620
+
621
+ private
622
+
623
+ def define_setter
624
+ field = self
625
+ @message_class.class_eval do
626
+ define_method("#{field.name}=") do |val|
627
+ case val
628
+ when nil
629
+ @values.delete(field.name)
630
+ when Hash
631
+ @values[field.name] = field.type.new(val)
632
+ when field.type
633
+ @values[field.name] = val
634
+ else
635
+ raise TypeError, "Expected value of type '#{field.type}', but got '#{val.class}'"
636
+ end
637
+ end
638
+ end
639
+ end
640
+
641
+ def merge_value(message_instance, value)
642
+ message_instance.__send__(@name).merge_from(value)
643
+ end
644
+ end
645
+
646
+
647
+ class EnumField < VarintField
648
+ def acceptable?(val)
649
+ case val
650
+ when Symbol
651
+ raise TypeError unless @type.const_defined?(val)
652
+ when EnumValue
653
+ raise TypeError if val.parent_class != @type
654
+ else
655
+ raise TypeError unless @type.valid_tag?(val)
656
+ end
657
+ true
658
+ end
659
+
660
+ def encode(value)
661
+ super(value.to_i)
662
+ end
663
+
664
+ private
665
+
666
+ def typed_default_value
667
+ if @default.is_a?(Symbol)
668
+ @type.const_get(@default)
669
+ else
670
+ self.class.default
671
+ end
672
+ end
673
+
674
+ def define_setter
675
+ field = self
676
+ @message_class.class_eval do
677
+ define_method("#{field.name}=") do |val|
678
+ if val.nil?
679
+ @values.delete(field.name)
680
+ else
681
+ val = \
682
+ case val
683
+ when Symbol
684
+ field.type.const_get(val) rescue nil
685
+ when Integer
686
+ field.type.const_get(field.type.name_by_value(val)) rescue nil
687
+ when EnumValue
688
+ raise TypeError, "Invalid value: #{val.inspect}" if val.parent_class != field.type
689
+ val
690
+ end
691
+ raise TypeError, "Invalid value: #{val.inspect}" unless val
692
+
693
+ @values[field.name] = val
694
+ end
695
+ end
696
+ end
697
+ end
698
+
699
+ end
700
+ end
701
+ end