ruby-protocol-buffers 0.8.4

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 (41) hide show
  1. data/.document +3 -0
  2. data/.gitignore +11 -0
  3. data/LICENSE +22 -0
  4. data/README +82 -0
  5. data/Rakefile +56 -0
  6. data/VERSION +1 -0
  7. data/bin/ruby-protoc +55 -0
  8. data/debian/changelog +105 -0
  9. data/debian/compatability +1 -0
  10. data/debian/control +12 -0
  11. data/debian/libprotobuf-ruby1.8.install +7 -0
  12. data/debian/protocol_buffers.rb +3 -0
  13. data/debian/rules +13 -0
  14. data/examples/json_protobuf.rb +90 -0
  15. data/ext/extconf.disabled.rb +3 -0
  16. data/ext/varint.c +65 -0
  17. data/lib/protocol_buffers.rb +5 -0
  18. data/lib/protocol_buffers/compiler.rb +48 -0
  19. data/lib/protocol_buffers/compiler/descriptor.pb.rb +236 -0
  20. data/lib/protocol_buffers/compiler/descriptor.proto +393 -0
  21. data/lib/protocol_buffers/compiler/file_descriptor_to_d.rb +195 -0
  22. data/lib/protocol_buffers/compiler/file_descriptor_to_ruby.rb +173 -0
  23. data/lib/protocol_buffers/limited_io.rb +33 -0
  24. data/lib/protocol_buffers/runtime/decoder.rb +65 -0
  25. data/lib/protocol_buffers/runtime/encoder.rb +53 -0
  26. data/lib/protocol_buffers/runtime/enum.rb +4 -0
  27. data/lib/protocol_buffers/runtime/extend.rb +1 -0
  28. data/lib/protocol_buffers/runtime/field.rb +550 -0
  29. data/lib/protocol_buffers/runtime/message.rb +494 -0
  30. data/lib/protocol_buffers/runtime/service.rb +1 -0
  31. data/lib/protocol_buffers/runtime/varint.rb +62 -0
  32. data/spec/compiler_spec.rb +19 -0
  33. data/spec/fields_spec.rb +49 -0
  34. data/spec/proto_files/depends.proto +5 -0
  35. data/spec/proto_files/featureful.proto +54 -0
  36. data/spec/proto_files/no_package.proto +10 -0
  37. data/spec/proto_files/simple.proto +5 -0
  38. data/spec/runtime_spec.rb +430 -0
  39. data/spec/spec.opts +1 -0
  40. data/spec/spec_helper.rb +8 -0
  41. metadata +128 -0
@@ -0,0 +1,53 @@
1
+ module ProtocolBuffers
2
+
3
+ class EncodeError < StandardError; end
4
+
5
+ module Encoder # :nodoc: all
6
+ def self.encode(io, message)
7
+ unless message.valid?
8
+ raise(EncodeError, "invalid message")
9
+ end
10
+
11
+ message.fields.each do |tag, field|
12
+ next unless message.value_for_tag?(tag)
13
+
14
+ value = message.value_for_tag(tag)
15
+ wire_type = field.wire_type
16
+ tag = (field.tag << 3) | wire_type
17
+
18
+ if field.repeated?
19
+ value.each { |i| serialize_field(io, tag, wire_type,
20
+ field.serialize(i)) }
21
+ else
22
+ serialize_field(io, tag, wire_type, field.serialize(value))
23
+ end
24
+ end
25
+
26
+ message.each_unknown_field do |tag_int, value|
27
+ wire_type = tag_int & 0b111
28
+ serialize_field(io, tag_int, wire_type, value)
29
+ end
30
+ end
31
+
32
+ def self.serialize_field(io, tag, wire_type, serialized)
33
+ # write the tag
34
+ Varint.encode(io, tag)
35
+
36
+ # see comment in decoder.rb about magic numbers
37
+ case wire_type
38
+ when 0 # VARINT
39
+ Varint.encode(io, serialized)
40
+ when 1, 5 # FIXED64, FIXED32
41
+ io.write(serialized)
42
+ when 2 # LENGTH_DELIMITED
43
+ Varint.encode(io, serialized.length)
44
+ io.write(serialized)
45
+ when 3, 4 # deprecated START_GROUP/END_GROUP types
46
+ raise(EncodeError, "groups are deprecated and unsupported")
47
+ else
48
+ raise(EncodeError, "unknown wire type: #{wire_type}")
49
+ end
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,4 @@
1
+ module ProtocolBuffers
2
+ module Enum # :nodoc:
3
+ end
4
+ end
@@ -0,0 +1 @@
1
+ # TODO
@@ -0,0 +1,550 @@
1
+ require 'protocol_buffers'
2
+ require 'protocol_buffers/runtime/enum'
3
+ require 'protocol_buffers/runtime/varint'
4
+ require 'protocol_buffers/limited_io'
5
+
6
+ module ProtocolBuffers
7
+
8
+ module WireTypes # :nodoc:
9
+ VARINT = 0
10
+ FIXED64 = 1
11
+ LENGTH_DELIMITED = 2
12
+ START_GROUP = 3 # deprecated, not supported in ruby
13
+ END_GROUP = 4 # ditto
14
+ FIXED32 = 5
15
+ end
16
+
17
+ # Acts like an Array, but type-checks each element
18
+ class RepeatedField < Array # :nodoc:
19
+ def initialize(field)
20
+ super()
21
+ @field = field
22
+ end
23
+
24
+ # ovverride all mutating methods.
25
+ # I'm sure this will break down on each new major Ruby release, as new
26
+ # mutating methods are added to Array. Ah, well. caveat emptor.
27
+
28
+ def <<(obj)
29
+ check(obj)
30
+ super
31
+ end
32
+
33
+ def []=(*args)
34
+ obj = args.last
35
+ case obj
36
+ when nil
37
+ check(obj) if args.length == 2 && !args.first.is_a?(Range)
38
+ when Array
39
+ check_each(obj)
40
+ else
41
+ check(obj)
42
+ end
43
+ super
44
+ end
45
+
46
+ def collect!(&b)
47
+ replace(collect(&b))
48
+ end
49
+ alias_method :map!, :collect!
50
+
51
+ def concat(rhs)
52
+ check_each(rhs)
53
+ super
54
+ end
55
+
56
+ def fill(*args, &b)
57
+ if block_given?
58
+ super(*args) { |v| check(b.call(v)) }
59
+ else
60
+ check(args.first)
61
+ super
62
+ end
63
+ end
64
+
65
+ def insert(index, *objs)
66
+ check_each(objs)
67
+ super
68
+ end
69
+
70
+ def push(*objs)
71
+ check_each(objs)
72
+ super
73
+ end
74
+
75
+ def replace(array)
76
+ check_each(array)
77
+ super
78
+ end
79
+
80
+ def unshift(*objs)
81
+ check_each(objs)
82
+ super
83
+ end
84
+
85
+ private
86
+
87
+ def check(value)
88
+ @field.check_valid(value)
89
+ end
90
+
91
+ def check_each(iter)
92
+ iter.each { |value| @field.check_valid(value) }
93
+ end
94
+ end
95
+
96
+ class Field # :nodoc: all
97
+ attr_reader :otype, :name, :tag
98
+
99
+ def repeated?; otype == :repeated end
100
+
101
+ def self.create(sender, otype, type, name, tag, opts = {})
102
+ if type.is_a?(Symbol)
103
+ klass = Field.const_get("#{type.to_s.capitalize}Field") rescue nil
104
+ raise("Type not found: #{type}") if klass.nil?
105
+ field = klass.new(otype, name, tag, opts)
106
+ elsif type.ancestors.include?(ProtocolBuffers::Enum)
107
+ field = Field::EnumField.new(type, otype, name, tag, opts)
108
+ elsif type.ancestors.include?(ProtocolBuffers::Message)
109
+ field = Field::MessageField.new(type, otype, name, tag, opts)
110
+ else
111
+ raise("Type not found: #{type}")
112
+ end
113
+ return field
114
+ end
115
+
116
+ def initialize(otype, name, tag, opts = {})
117
+ @otype = otype
118
+ @name = name
119
+ @tag = tag
120
+ @opts = opts.dup
121
+ end
122
+
123
+ def add_methods_to(klass)
124
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
125
+ attr_reader :#{name}
126
+ EOF
127
+ if repeated?
128
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
129
+ def #{name}=(value)
130
+ if value.nil?
131
+ @#{name}.clear
132
+ else
133
+ @#{name}.clear
134
+ value.each { |i| @#{name}.push i }
135
+ end
136
+ end
137
+
138
+ def has_#{name}?; true; end
139
+ EOF
140
+ else
141
+ klass.class_eval <<-EOF, __FILE__, __LINE__+1
142
+ def #{name}=(value)
143
+ field = fields[#{tag}]
144
+ if value.nil?
145
+ @set_fields.delete_at(#{tag})
146
+ @#{name} = field.default_value
147
+ else
148
+ field.check_valid(value)
149
+ @set_fields[#{tag}] = true
150
+ @#{name} = value
151
+ if @parent_for_notify
152
+ @parent_for_notify.default_changed(@tag_for_notify)
153
+ @parent_for_notify = @tag_for_notify = nil
154
+ end
155
+ end
156
+ end
157
+
158
+ def has_#{name}?
159
+ value_for_tag?(#{tag})
160
+ end
161
+ EOF
162
+ end
163
+ end
164
+
165
+ def check_value(value)
166
+ # pass
167
+ end
168
+
169
+ def valid_type?(value)
170
+ true
171
+ end
172
+
173
+ def inspect_value(value)
174
+ value.inspect
175
+ end
176
+
177
+ def check_valid(value)
178
+ raise(TypeError, "can't assign #{value.class.name} to #{self.class.name}") unless valid_type?(value)
179
+ check_value(value)
180
+ end
181
+
182
+ # the type of value to return depends on the wire_type of the field:
183
+ # VARINT => Integer
184
+ # FIXED64 => 8-byte string
185
+ # LENGTH_DELIMITED => string
186
+ # FIXED32 => 4-byte string
187
+ def serialize(value)
188
+ value
189
+ end
190
+
191
+ # the type of value passed in depends on the wire_type of the field:
192
+ # VARINT => Integer (Fixnum or Bignum)
193
+ # FIXED64 => 8-byte string
194
+ # LENGTH_DELIMITED => IO class, make sure to consume all data available
195
+ # FIXED32 => 4-byte string
196
+ def deserialize(value)
197
+ value
198
+ end
199
+
200
+ module WireFormats
201
+ module LENGTH_DELIMITED
202
+ def wire_type
203
+ WireTypes::LENGTH_DELIMITED
204
+ end
205
+
206
+ def deserialize(value)
207
+ value.read
208
+ end
209
+ end
210
+
211
+ module VARINT
212
+ def wire_type
213
+ WireTypes::VARINT
214
+ end
215
+ end
216
+
217
+ module FIXED32
218
+ def wire_type
219
+ WireTypes::FIXED32
220
+ end
221
+
222
+ def serialize(value)
223
+ [value].pack(pack_code)
224
+ end
225
+
226
+ def deserialize(value)
227
+ value.unpack(pack_code).first
228
+ end
229
+ end
230
+
231
+ module FIXED64
232
+ def wire_type
233
+ WireTypes::FIXED64
234
+ end
235
+
236
+ def serialize(value)
237
+ [value].pack(pack_code)
238
+ end
239
+
240
+ def deserialize(value)
241
+ value.unpack(pack_code).first
242
+ end
243
+ end
244
+ end
245
+
246
+ class BytesField < Field
247
+ include WireFormats::LENGTH_DELIMITED
248
+
249
+ def valid_type?(value)
250
+ value.is_a?(String)
251
+ end
252
+
253
+ def default_value
254
+ @default_value || @default_value = (@opts[:default] || "").freeze
255
+ end
256
+ end
257
+
258
+ class StringField < BytesField
259
+ # TODO: UTF-8 validation
260
+ # Make sure to handle this weird case: strings are mutable, so a UTF-8
261
+ # valid string could be assigned to a repeated field and then modified in
262
+ # place later on to not be valid UTF-8 anymore.
263
+ #
264
+ # Maybe we just punt on this except in Ruby 1.9 where we can rely on the
265
+ # language ensuring the string is always UTF-8?
266
+ end
267
+
268
+ class NumericField < Field
269
+ def min
270
+ 0
271
+ end
272
+
273
+ def max
274
+ 1.0 / 0.0
275
+ end
276
+
277
+ def check_value(value)
278
+ raise(ArgumentError, "value is out of range for type #{self.class.name}: #{value}") unless value >= min && value <= max
279
+ end
280
+
281
+ def default_value
282
+ @opts[:default] || 0
283
+ end
284
+
285
+ private
286
+ # base class, not used directly
287
+ def initialize(*a); super; end
288
+ end
289
+
290
+ class VarintField < NumericField
291
+ include WireFormats::VARINT
292
+
293
+ def valid_type?(value)
294
+ value.is_a?(Integer)
295
+ end
296
+
297
+ private
298
+ # base class, not used directly
299
+ def initialize(*a); super; end
300
+ end
301
+
302
+ class SignedVarintField < VarintField
303
+ def deserialize(value)
304
+ if value > max
305
+ value - (1<<bits)
306
+ else
307
+ value
308
+ end
309
+ end
310
+ end
311
+
312
+ class Uint32Field < VarintField
313
+ def max
314
+ 0xFFFFFFFF
315
+ end
316
+ end
317
+
318
+ class Uint64Field < VarintField
319
+ def max
320
+ 0xFFFFFFFF_FFFFFFFF
321
+ end
322
+ end
323
+
324
+ class Fixed32Field < NumericField
325
+ include WireFormats::FIXED32
326
+
327
+ def pack_code
328
+ 'L'
329
+ end
330
+
331
+ def max
332
+ 0xFFFFFFFF
333
+ end
334
+
335
+ def valid_type?(value)
336
+ value.is_a?(Integer)
337
+ end
338
+ end
339
+
340
+ class Fixed64Field < NumericField
341
+ include WireFormats::FIXED64
342
+
343
+ def pack_code
344
+ 'Q'
345
+ end
346
+
347
+ def max
348
+ 0xFFFFFFFF_FFFFFFFF
349
+ end
350
+
351
+ def valid_type?(value)
352
+ value.is_a?(Integer)
353
+ end
354
+ end
355
+
356
+ class Int32Field < SignedVarintField
357
+ def min
358
+ -(1 << 31)
359
+ end
360
+
361
+ def max
362
+ (1 << 31) - 1
363
+ end
364
+
365
+ def bits
366
+ 32
367
+ end
368
+ end
369
+
370
+ class Sint32Field < Int32Field
371
+ def serialize(value)
372
+ Varint.encodeZigZag32(value)
373
+ end
374
+
375
+ def deserialize(value)
376
+ Varint.decodeZigZag32(value)
377
+ end
378
+ end
379
+
380
+ class Sfixed32Field < NumericField
381
+ include WireFormats::FIXED32
382
+
383
+ def pack_code
384
+ 'l'
385
+ end
386
+
387
+ def min
388
+ -(1 << 31)
389
+ end
390
+
391
+ def max
392
+ (1 << 31) - 1
393
+ end
394
+
395
+ def valid_type?(value)
396
+ value.is_a?(Integer)
397
+ end
398
+ end
399
+
400
+ class Int64Field < SignedVarintField
401
+ def min
402
+ -(1 << 63)
403
+ end
404
+
405
+ def max
406
+ (1 << 63) - 1
407
+ end
408
+
409
+ def bits
410
+ 64
411
+ end
412
+ end
413
+
414
+ class Sint64Field < Int64Field
415
+ def serialize(value)
416
+ Varint.encodeZigZag64(value)
417
+ end
418
+
419
+ def deserialize(value)
420
+ Varint.decodeZigZag64(value)
421
+ end
422
+ end
423
+
424
+ class Sfixed64Field < NumericField
425
+ include WireFormats::FIXED64
426
+
427
+ def pack_code
428
+ 'q'
429
+ end
430
+
431
+ def min
432
+ -(1 << 63)
433
+ end
434
+
435
+ def max
436
+ (1 << 63) - 1
437
+ end
438
+
439
+ def valid_type?(value)
440
+ value.is_a?(Integer)
441
+ end
442
+ end
443
+
444
+ class FloatField < Field
445
+ include WireFormats::FIXED32
446
+
447
+ def pack_code
448
+ 'e'
449
+ end
450
+
451
+ def valid_type?(value)
452
+ value.is_a?(Numeric)
453
+ end
454
+
455
+ def default_value
456
+ @opts[:default] || 0.0
457
+ end
458
+ end
459
+
460
+ class DoubleField < Field
461
+ include WireFormats::FIXED64
462
+
463
+ def pack_code
464
+ 'E'
465
+ end
466
+
467
+ def valid_type?(value)
468
+ value.is_a?(Numeric)
469
+ end
470
+
471
+ def default_value
472
+ @opts[:default] || 0.0
473
+ end
474
+ end
475
+
476
+ class BoolField < VarintField
477
+ def serialize(value)
478
+ value ? 1 : 0
479
+ end
480
+
481
+ def valid_type?(value)
482
+ value == true || value == false
483
+ end
484
+
485
+ def check_value(value); end
486
+
487
+ def deserialize(value)
488
+ value != 0
489
+ end
490
+
491
+ def default_value
492
+ @opts[:default] || false
493
+ end
494
+ end
495
+
496
+ class EnumField < Int32Field
497
+ attr_reader :valid_values, :value_to_name
498
+
499
+ def initialize(proxy_enum, otype, name, tag, opts = {})
500
+ super(otype, name, tag, opts)
501
+ @proxy_enum = proxy_enum
502
+ @valid_values = @proxy_enum.constants.map { |c| @proxy_enum.const_get(c) }.sort
503
+ @value_to_name = @proxy_enum.constants.inject({}) { |h, c|
504
+ h[@proxy_enum.const_get(c)] = c.to_s; h
505
+ }
506
+ end
507
+
508
+ def check_value(value)
509
+ raise(ArgumentError, "value is out of range for #{self.class.name}: #{value}") unless @valid_values.include?(value)
510
+ end
511
+
512
+ def default_value
513
+ @opts[:default] || @valid_values.first
514
+ end
515
+
516
+ def inspect_value(value)
517
+ "#{@value_to_name[value]}(#{value})"
518
+ end
519
+ end
520
+
521
+ class MessageField < Field
522
+ include WireFormats::LENGTH_DELIMITED
523
+
524
+ def initialize(proxy_class, otype, name, tag, opts = {})
525
+ super(otype, name, tag, opts)
526
+ @proxy_class = proxy_class
527
+ end
528
+
529
+ def default_value
530
+ @proxy_class.new
531
+ end
532
+
533
+ def valid_type?(value)
534
+ value.is_a?(@proxy_class)
535
+ end
536
+
537
+ # TODO: serialize could be more efficient if it used the underlying stream
538
+ # directly rather than string copying, but that would require knowing the
539
+ # length beforehand.
540
+ def serialize(value)
541
+ value.to_s
542
+ end
543
+
544
+ def deserialize(io)
545
+ @proxy_class.parse(io)
546
+ end
547
+ end
548
+
549
+ end
550
+ end