macks-ruby_protobuf 0.3.2.1

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 (76) hide show
  1. data/History.txt +14 -0
  2. data/Manifest.txt +74 -0
  3. data/README.txt +58 -0
  4. data/Rakefile +18 -0
  5. data/bin/mk_parser +2 -0
  6. data/bin/rprotoc +36 -0
  7. data/examples/addressbook.pb.rb +56 -0
  8. data/examples/addressbook.proto +24 -0
  9. data/examples/reading_a_message.rb +32 -0
  10. data/examples/writing_a_message.rb +46 -0
  11. data/lib/protobuf/common/wire_type.rb +10 -0
  12. data/lib/protobuf/compiler/compiler.rb +54 -0
  13. data/lib/protobuf/compiler/nodes.rb +319 -0
  14. data/lib/protobuf/compiler/proto.y +203 -0
  15. data/lib/protobuf/compiler/proto2.ebnf +79 -0
  16. data/lib/protobuf/compiler/proto_parser.rb +1394 -0
  17. data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
  18. data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
  19. data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
  20. data/lib/protobuf/compiler/visitors.rb +288 -0
  21. data/lib/protobuf/descriptor/descriptor.proto +286 -0
  22. data/lib/protobuf/descriptor/descriptor.rb +54 -0
  23. data/lib/protobuf/descriptor/descriptor_builder.rb +144 -0
  24. data/lib/protobuf/descriptor/descriptor_proto.rb +119 -0
  25. data/lib/protobuf/descriptor/enum_descriptor.rb +33 -0
  26. data/lib/protobuf/descriptor/field_descriptor.rb +50 -0
  27. data/lib/protobuf/descriptor/file_descriptor.rb +38 -0
  28. data/lib/protobuf/message/decoder.rb +93 -0
  29. data/lib/protobuf/message/encoder.rb +37 -0
  30. data/lib/protobuf/message/enum.rb +28 -0
  31. data/lib/protobuf/message/extend.rb +8 -0
  32. data/lib/protobuf/message/field.rb +654 -0
  33. data/lib/protobuf/message/message.rb +308 -0
  34. data/lib/protobuf/message/protoable.rb +37 -0
  35. data/lib/protobuf/message/service.rb +9 -0
  36. data/lib/protobuf/rpc/client.rb +19 -0
  37. data/lib/protobuf/rpc/handler.rb +17 -0
  38. data/lib/protobuf/rpc/server.rb +39 -0
  39. data/lib/ruby_protobuf.rb +3 -0
  40. data/test/addressbook.rb +98 -0
  41. data/test/addressbook_base.rb +62 -0
  42. data/test/addressbook_ext.rb +12 -0
  43. data/test/check_unbuild.rb +30 -0
  44. data/test/collision.rb +18 -0
  45. data/test/data/data.bin +3 -0
  46. data/test/data/data_source.py +14 -0
  47. data/test/data/types.bin +0 -0
  48. data/test/data/types_source.py +22 -0
  49. data/test/data/unk.png +0 -0
  50. data/test/ext_collision.rb +25 -0
  51. data/test/ext_range.rb +23 -0
  52. data/test/merge.rb +40 -0
  53. data/test/nested.rb +25 -0
  54. data/test/proto/addressbook.proto +31 -0
  55. data/test/proto/addressbook_base.proto +26 -0
  56. data/test/proto/addressbook_ext.proto +6 -0
  57. data/test/proto/collision.proto +5 -0
  58. data/test/proto/ext_collision.proto +8 -0
  59. data/test/proto/ext_range.proto +7 -0
  60. data/test/proto/merge.proto +15 -0
  61. data/test/proto/nested.proto +7 -0
  62. data/test/proto/rpc.proto +6 -0
  63. data/test/proto/types.proto +17 -0
  64. data/test/test_addressbook.rb +43 -0
  65. data/test/test_compiler.rb +313 -0
  66. data/test/test_descriptor.rb +122 -0
  67. data/test/test_extension.rb +40 -0
  68. data/test/test_message.rb +106 -0
  69. data/test/test_optional_field.rb +68 -0
  70. data/test/test_parse.rb +15 -0
  71. data/test/test_ruby_protobuf.rb +1 -0
  72. data/test/test_serialize.rb +42 -0
  73. data/test/test_standard_message.rb +96 -0
  74. data/test/test_types.rb +181 -0
  75. data/test/types.rb +22 -0
  76. metadata +150 -0
@@ -0,0 +1,654 @@
1
+ require 'protobuf/common/wire_type'
2
+ require 'protobuf/descriptor/field_descriptor'
3
+
4
+ module Protobuf
5
+ module Field
6
+ def self.build(message_class, rule, type, name, tag, opts={})
7
+ field_class =
8
+ if [:double, :float, :int32, :int64, :uint32, :uint64,
9
+ :sint32, :sint64, :fixed32, :fixed64, :sfixed32, :sfixed64,
10
+ :bool, :string, :bytes].include? type
11
+ eval "Protobuf::Field::#{type.to_s.capitalize}Field"
12
+ else
13
+ Protobuf::Field::FieldProxy
14
+ end
15
+ field_class.new message_class, rule, type, name, tag, opts
16
+ end
17
+
18
+ class InvalidRuleError < StandardError; end
19
+
20
+ class BaseField
21
+ class <<self
22
+ def descriptor
23
+ @descriptor ||= Protobuf::Descriptor::FieldDescriptor.new
24
+ end
25
+
26
+ def default; nil end
27
+ end
28
+
29
+ attr_accessor :message_class, :rule, :type, :name, :tag, :default
30
+
31
+ def descriptor
32
+ @descriptor ||= Protobuf::Descriptor::FieldDescriptor.new self
33
+ end
34
+
35
+ def initialize(message_class, rule, type, name, tag, opts={})
36
+ @message_class, @rule, @type, @name, @tag, @default, @extension =
37
+ message_class, rule, type, name, tag, opts[:default], opts[:extension]
38
+ @error_message = 'Type invalid'
39
+ end
40
+
41
+ def ready?; true end
42
+
43
+ def initialized?(message)
44
+ case rule
45
+ when :required
46
+ return false if message[name].nil?
47
+ return false if is_a?(Protobuf::Field::MessageField) and not message[name].initialized?
48
+ when :repeated
49
+ return message[name].inject(true) do |result, msg|
50
+ result and msg.initialized?
51
+ end
52
+ when :optional
53
+ return false if message[name] and is_a?(Protobuf::Field::MessageField) and not message[name].initialized?
54
+ end
55
+ true
56
+ end
57
+
58
+ def clear(message)
59
+ if repeated?
60
+ message[name].clear
61
+ else
62
+ message.instance_variable_get(:@values).delete(name)
63
+ end
64
+ end
65
+
66
+ def default_value
67
+ case rule
68
+ when :repeated
69
+ FieldArray.new self
70
+ when :required
71
+ nil
72
+ when :optional
73
+ typed_default_value default
74
+ else
75
+ raise InvalidRuleError
76
+ end
77
+ end
78
+
79
+ def typed_default_value(default=nil)
80
+ default or self.class.default
81
+ end
82
+
83
+ def define_accessor(message_instance)
84
+ message_instance.instance_variable_get(:@values)[name] = default_value if rule == :repeated
85
+ define_getter message_instance
86
+ define_setter message_instance unless rule == :repeated
87
+ end
88
+
89
+ def define_getter(message_instance)
90
+ field = self
91
+ metaclass = (class << message_instance; self; end)
92
+ metaclass.class_eval do
93
+ define_method(field.name) do
94
+ @values[field.name] or field.default_value
95
+ end
96
+ end
97
+ end
98
+
99
+ def define_setter(message_instance)
100
+ field = self
101
+ metaclass = (class << message_instance; self; end)
102
+ metaclass.class_eval do
103
+ define_method("#{field.name}=") do |val|
104
+ if val.nil?
105
+ @values.delete(field.name)
106
+ elsif field.acceptable? val
107
+ @values[field.name] = val
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ def set(message_instance, bytes)
114
+ if repeated?
115
+ set_array message_instance, bytes
116
+ else
117
+ set_bytes message_instance, bytes
118
+ end
119
+ end
120
+
121
+ def set_array(message_instance, bytes)
122
+ raise NotImplementedError
123
+ end
124
+
125
+ def set_bytes(message_instance, bytes)
126
+ raise NotImplementedError
127
+ end
128
+
129
+ def get(value)
130
+ get_bytes value
131
+ end
132
+
133
+ def get_bytes(value)
134
+ raise NotImplementedError
135
+ end
136
+
137
+ def merge(message_instance, value)
138
+ if repeated?
139
+ merge_array message_instance, value
140
+ else
141
+ merge_value message_instance, value
142
+ end
143
+ end
144
+
145
+ def merge_array(message_instance, value)
146
+ message_instance[tag].concat value
147
+ end
148
+
149
+ def merge_value(message_instance, value)
150
+ message_instance[tag] = value
151
+ end
152
+
153
+ def repeated?; rule == :repeated end
154
+ def required?; rule == :required end
155
+ def optional?; rule == :optional end
156
+
157
+ def max; self.class.max end
158
+ def min; self.class.min end
159
+
160
+ def acceptable?(val)
161
+ true
162
+ end
163
+
164
+ def error_message
165
+ @error_message
166
+ end
167
+
168
+ def to_s
169
+ "#{rule} #{type} #{name} = #{tag} #{default ? "[default=#{default}]" : ''}"
170
+ end
171
+ end
172
+
173
+ class FieldProxy
174
+ def initialize(message_class, rule, type, name, tag, opts={})
175
+ @message_class, @rule, @type, @name, @tag, @opts =
176
+ message_class, rule, type, name, tag, opts
177
+ end
178
+
179
+ def ready?; false end
180
+
181
+ def setup
182
+ type = typename_to_class @message_class, @type
183
+ field_class =
184
+ if type.superclass == Protobuf::Enum
185
+ Protobuf::Field::EnumField
186
+ elsif type.superclass == Protobuf::Message
187
+ Protobuf::Field::MessageField
188
+ else
189
+ raise $!
190
+ end
191
+ field_class.new @message_class, @rule, type, @name, @tag, @opts
192
+ end
193
+
194
+ def typename_to_class(message_class, type)
195
+ modules = message_class.to_s.split('::')
196
+ while
197
+ begin
198
+ type = eval((modules | [type.to_s]).join('::'))
199
+ break
200
+ rescue NameError
201
+ modules.empty? ? raise($!) : modules.pop
202
+ end
203
+ end
204
+ type
205
+ end
206
+ =begin
207
+ def typename_to_class(message_class, type)
208
+ suffix = type.to_s.split('::')
209
+ modules = message_class.to_s.split('::')
210
+ while
211
+ mod = modules.empty? ? Object : eval(modules.join('::'))
212
+ suffix.each do |s|
213
+ if mod.const_defined?(s)
214
+ mod = mod.const_get(s)
215
+ else
216
+ mod = nil
217
+ break
218
+ end
219
+ end
220
+ break if mod
221
+ raise NameError.new("type not found: #{type}", type) if modules.empty?
222
+ modules.pop
223
+ end
224
+ mod
225
+ end
226
+ =end
227
+ end
228
+
229
+ class FieldArray < Array
230
+ def initialize(field)
231
+ @field = field
232
+ end
233
+
234
+ def []=(nth, val)
235
+ if @field.acceptable? val
236
+ super
237
+ end
238
+ end
239
+
240
+ def <<(val)
241
+ if @field.acceptable? val
242
+ super
243
+ end
244
+ end
245
+
246
+ def push(val)
247
+ if @field.acceptable? val
248
+ super
249
+ end
250
+ end
251
+
252
+ def unshift(val)
253
+ if @field.acceptable? val
254
+ super
255
+ end
256
+ end
257
+
258
+ def to_s
259
+ "[#{@field.name}]"
260
+ end
261
+ end
262
+
263
+ class StringField < BaseField
264
+ class <<self
265
+ def default; '' end
266
+ end
267
+
268
+ def wire_type
269
+ Protobuf::WireType::LENGTH_DELIMITED
270
+ end
271
+
272
+ def acceptable?(val)
273
+ raise TypeError unless val.instance_of? String
274
+ true
275
+ end
276
+
277
+ def set_bytes(message_instance, bytes)
278
+ message = bytes.pack('C*')
279
+ message.force_encoding('UTF-8') if message.respond_to?(:force_encoding)
280
+ message_instance.send("#{name}=", message)
281
+ end
282
+
283
+ def set_array(message_instance, bytes)
284
+ message = bytes.pack('C*')
285
+ message.force_encoding('UTF-8') if message.respond_to?(:force_encoding)
286
+ arr = message_instance.send name
287
+ arr << message
288
+ end
289
+
290
+ def get_bytes(value)
291
+ bytes = value.unpack('C*')
292
+ string_size = VarintField.get_bytes bytes.size
293
+ string_size + bytes.pack('C*')
294
+ end
295
+ end
296
+
297
+ class BytesField < BaseField
298
+ class <<self
299
+ def default; '' end
300
+ end
301
+
302
+ def wire_type
303
+ Protobuf::WireType::LENGTH_DELIMITED
304
+ end
305
+
306
+ def acceptable?(val)
307
+ raise TypeError unless val.instance_of? String
308
+ true
309
+ end
310
+
311
+ def set_bytes(message_instance, bytes)
312
+ message_instance.send("#{name}=", bytes.pack('C*'))
313
+ end
314
+
315
+ def set_array(message_instance, bytes)
316
+ message = bytes.pack('C*')
317
+ arr = message_instance.send name
318
+ arr << message
319
+ end
320
+
321
+ def get_bytes(value)
322
+ string_size = VarintField.get_bytes value.unpack('C*').size
323
+ string_size + value
324
+ end
325
+ end
326
+
327
+ class VarintField < BaseField
328
+ class <<self
329
+ def default; 0 end
330
+ end
331
+
332
+ def wire_type
333
+ Protobuf::WireType::VARINT
334
+ end
335
+
336
+ def set_bytes(message_instance, bytes)
337
+ # TODO should refactor using pack('w*')
338
+ value = 0
339
+ bytes.each_with_index do |byte, index|
340
+ value |= byte << (7 * index)
341
+ end
342
+ message_instance.send("#{name}=", value)
343
+ end
344
+
345
+ def self.get_bytes(value)
346
+ # TODO should refactor using unpack('w*')
347
+ #return [value].pack('w*').unpack('C*')
348
+ return [0].pack('C') if value == 0
349
+ bytes = []
350
+ until value == 0
351
+ byte = 0
352
+ 7.times do |i|
353
+ byte |= (value & 1) << i
354
+ value >>= 1
355
+ end
356
+ byte |= 0b10000000
357
+ bytes << byte
358
+ end
359
+ #bytes[0] &= 0b01111111
360
+ #bytes
361
+ bytes[bytes.size - 1] &= 0b01111111
362
+ bytes.pack('C*')
363
+ end
364
+
365
+ def get_bytes(value)
366
+ self.class.get_bytes value
367
+ end
368
+
369
+ def acceptable?(val)
370
+ raise TypeError.new(val.class.name) unless val.is_a? Integer
371
+ raise RangeError.new(val) if val < min or max < val
372
+ true
373
+ end
374
+ end
375
+
376
+ class Int32Field < VarintField
377
+ def self.max; 1.0/0.0 end
378
+ def self.min; -1.0/0.0 end
379
+ end
380
+
381
+ class Int64Field < VarintField
382
+ def self.max; 1.0/0.0 end
383
+ def self.min; -1.0/0.0 end
384
+ end
385
+
386
+ class Uint32Field < VarintField
387
+ def self.max; 1.0/0.0 end
388
+ def self.min; 0 end
389
+ end
390
+
391
+ class Uint64Field < VarintField
392
+ def self.max; 1.0/0.0 end
393
+ def self.min; 0 end
394
+ end
395
+
396
+ class Sint32Field < VarintField
397
+ def self.max; 1.0/0.0 end
398
+ def self.min; -1.0/0.0 end
399
+
400
+ def set_bytes(message_instance, bytes)
401
+ # TODO use only bit-operations
402
+ byte = bytes.first
403
+ value =
404
+ if byte % 2 == 0
405
+ byte / 2
406
+ else
407
+ -(byte + 1) / 2
408
+ end
409
+ message_instance.send("#{name}=", value)
410
+ end
411
+
412
+ def get_bytes(value)
413
+ #(value << 1) ^ (value >> 31)
414
+ [(value << 1) ^ (value >> 31)].pack('C*')
415
+ end
416
+ end
417
+
418
+ class Sint64Field < VarintField
419
+ def self.max; 1.0/0.0 end
420
+ def self.min; -1.0/0.0 end
421
+
422
+ def set_bytes(message_instance, bytes)
423
+ # TODO use only bit-operations
424
+ byte = bytes.first
425
+ value =
426
+ if byte % 2 == 0
427
+ byte / 2
428
+ else
429
+ -(byte + 1) / 2
430
+ end
431
+ message_instance.send("#{name}=", value)
432
+ end
433
+
434
+ def get_bytes(value)
435
+ #(value << 1) ^ (value >> 63)
436
+ [(value << 1) ^ (value >> 63)].pack('C*')
437
+ end
438
+ end
439
+
440
+ class DoubleField < VarintField
441
+ def wire_type
442
+ Protobuf::WireType::FIXED64
443
+ end
444
+
445
+ #TODO
446
+ def self.max
447
+ '0x7fefffffffffffff'.unpack('d').first
448
+ end
449
+
450
+ #TODO
451
+ def self.min
452
+ -(2**(64/2) - 1)
453
+ end
454
+
455
+ def set_bytes(message_instance, bytes)
456
+ message_instance.send("#{name}=", bytes.unpack('E').first)
457
+ end
458
+
459
+ def get_bytes(value)
460
+ [value].pack('E')
461
+ end
462
+
463
+ def acceptable?(val)
464
+ raise TypeError.new(val.class.name) unless val.is_a? Numeric
465
+ raise RangeError.new(val) if val < min or max < val
466
+ true
467
+ end
468
+ end
469
+
470
+ class FloatField < VarintField
471
+ def wire_type
472
+ Protobuf::WireType::FIXED32
473
+ end
474
+
475
+ #TODO
476
+ def self.max
477
+ '0x7fefffffffffffff'.unpack('e').first
478
+ end
479
+
480
+ #TODO
481
+ def self.min
482
+ -(2**(32/2) - 1)
483
+ end
484
+
485
+ def set_bytes(message_instance, bytes)
486
+ message_instance.send("#{name}=", bytes.unpack('e').first)
487
+ end
488
+
489
+ def get_bytes(value)
490
+ [value].pack('e')
491
+ end
492
+
493
+ def acceptable?(val)
494
+ raise TypeError unless val.is_a? Numeric
495
+ raise RangeError if val < min or max < val
496
+ true
497
+ end
498
+ end
499
+
500
+ class Fixed32Field < VarintField
501
+ def wire_type
502
+ Protobuf::WireType::FIXED32
503
+ end
504
+
505
+ def self.max
506
+ 2**32
507
+ end
508
+
509
+ def self.min
510
+ 0
511
+ end
512
+
513
+ def set_bytes(message_instance, bytes)
514
+ message_instance.send("#{name}=", bytes.unpack('L').first)
515
+ end
516
+
517
+ def get_bytes(value)
518
+ [value].pack('L')
519
+ end
520
+ end
521
+
522
+ class Fixed64Field < VarintField
523
+ def wire_type
524
+ Protobuf::WireType::FIXED64
525
+ end
526
+
527
+ def self.max
528
+ 2**64
529
+ end
530
+
531
+ def self.min
532
+ 0
533
+ end
534
+
535
+ def set_bytes(message_instance, bytes)
536
+ message_instance.send("#{name}=", bytes.unpack('l').first)
537
+ end
538
+
539
+ def get_bytes(value)
540
+ [value].pack('Q')
541
+ end
542
+ end
543
+
544
+ class Sfinxed32Field < VarintField
545
+ def wire_type
546
+ Protobuf::WireType::FIXED32
547
+ end
548
+
549
+ def self.max
550
+ 2**(32/2)
551
+ end
552
+
553
+ def self.min
554
+ -(2**(32/2) - 1)
555
+ end
556
+ end
557
+
558
+ class Sfixed64Field < VarintField
559
+ def wire_type
560
+ Protobuf::WireType::FIXED64
561
+ end
562
+
563
+ def self.max
564
+ 2**(64/2)
565
+ end
566
+
567
+ def self.min
568
+ -(2**(64/2) - 1)
569
+ end
570
+ end
571
+
572
+ class BoolField < VarintField
573
+ class <<self
574
+ def default; false end
575
+ end
576
+
577
+ def acceptable?(val)
578
+ raise TypeError unless [TrueClass, FalseClass].include? val.class
579
+ true
580
+ end
581
+
582
+ def set_bytes(message_instance, bytes)
583
+ message_instance.send("#{name}=", bytes.first == 1)
584
+ end
585
+
586
+ def get_bytes(value)
587
+ [value ? 1 : 0].pack('C')
588
+ end
589
+ end
590
+
591
+ class MessageField < BaseField
592
+ class <<self
593
+ def default; nil end
594
+ end
595
+
596
+ def wire_type
597
+ Protobuf::WireType::LENGTH_DELIMITED
598
+ end
599
+
600
+ def typed_default_value(default=nil)
601
+ if default.is_a? Symbol
602
+ type.module_eval default.to_s
603
+ else
604
+ default
605
+ end
606
+ end
607
+
608
+ def acceptable?(val)
609
+ raise TypeError unless val.instance_of? type
610
+ true
611
+ end
612
+
613
+ def set_bytes(message_instance, bytes)
614
+ message = type.new
615
+ message.parse_from_string bytes.pack('C*') # TODO
616
+ message_instance.send("#{name}=", message)
617
+ end
618
+
619
+ def set_array(message_instance, bytes)
620
+ message = type.new
621
+ message.parse_from_string bytes.pack('C*')
622
+ arr = message_instance.send name
623
+ arr << message
624
+ end
625
+
626
+ def get_bytes(value)
627
+ stringio = StringIO.new ''
628
+ value.serialize_to stringio
629
+ bytes = stringio.string.unpack 'C*'
630
+ string_size = VarintField.get_bytes bytes.size
631
+ string_size + bytes.pack('C*')
632
+ end
633
+
634
+ def merge_value(message_instance, value)
635
+ message_instance[tag].merge_from value
636
+ end
637
+ end
638
+
639
+ class EnumField < VarintField
640
+ def default
641
+ if @default.is_a?(Symbol)
642
+ type.const_get @default
643
+ else
644
+ @default
645
+ end
646
+ end
647
+
648
+ def acceptable?(val)
649
+ raise TypeError unless type.valid_tag? val
650
+ true
651
+ end
652
+ end
653
+ end
654
+ end