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,494 @@
1
+ require 'stringio'
2
+ require 'protocol_buffers/runtime/field'
3
+ require 'protocol_buffers/runtime/encoder'
4
+ require 'protocol_buffers/runtime/decoder'
5
+
6
+ module ProtocolBuffers
7
+
8
+ # = Generated Code
9
+ #
10
+ # This text describes exactly what Ruby code the protocol buffer compiler
11
+ # generates for any given protocol definition. You should read the language
12
+ # guide before reading this document:
13
+ #
14
+ # http://code.google.com/apis/protocolbuffers/docs/proto.html
15
+ #
16
+ # == Packages
17
+ #
18
+ # If a package name is given in the <tt>.proto</tt> file, all top-level
19
+ # messages and enums in the file will be defined underneath a module with the
20
+ # same name as the package. The first letter of the package is capitalized if
21
+ # necessary. This applies to message and enum names as well, since Ruby
22
+ # classes and modules must be capitalized.
23
+ #
24
+ # For example, the following <tt>.proto</tt> file:
25
+ #
26
+ # package wootcakes;
27
+ # message uberWoot { }
28
+ #
29
+ # Will define a module +Wootcakes+ and a class <tt>Wootcakes::UberWoot</tt>
30
+ #
31
+ # == Messages
32
+ #
33
+ # Given a simple message definition:
34
+ #
35
+ # message Foo {}
36
+ #
37
+ # The compiler will generate a class called +Foo+, which subclasses
38
+ # ProtocolBuffers::Message.
39
+ #
40
+ # These generated classes are not designed for subclassing.
41
+ #
42
+ # Ruby message classes have no particular public methods or accessors other
43
+ # than those defined by ProtocolBuffers::Message and those generated for
44
+ # nested fields, messages, and enum types (see below).
45
+ #
46
+ # A message can be declared inside another message. For example:
47
+ # <tt>message Foo { message Bar { } }</tt>
48
+ #
49
+ # In this case, the +Bar+ class is declared inside the +Foo+ class, so you can
50
+ # access it as <tt>Foo::Bar</tt> (or if in package +Baz+,
51
+ # <tt>Baz::Foo::Bar</tt>)
52
+ #
53
+ # == Fields
54
+ #
55
+ # For each field in the message type, the corresponding class has a member
56
+ # with the same name as the field. How you can manipulate the member depends
57
+ # on its type.
58
+ #
59
+ # === Singular Fields
60
+ #
61
+ # If you have a singular (optional or repeated) field +foo+ of any non-message
62
+ # type, you can manipulate the field +foo+ as if it were a regular object
63
+ # attribute. For example, if +foo+'s type is <tt>int32</tt>, you can say:
64
+ #
65
+ # message.foo = 123
66
+ # puts message.foo
67
+ #
68
+ # Note that setting +foo+ to a value of the wrong type will raise a
69
+ # TypeError. Setting +foo+ to a value of the right type, but one that doesn't
70
+ # fit (such as assigning an out-of-bounds enum value) will raise an
71
+ # ArgumentError.
72
+ #
73
+ # If +foo+ is read when it is not set, its value is the default value for that
74
+ # field. To check if +foo+ is set, call <tt>has_foo?</tt> To clear +foo+, call
75
+ # <tt>message.foo = nil</tt>. For example:
76
+ #
77
+ # assert(!message.has_foo?)
78
+ # message.foo = 123
79
+ # assert(message.has_foo?)
80
+ # message.foo = nil
81
+ # assert(!message.has_foo?)
82
+ #
83
+ # === Singular String Fields
84
+ #
85
+ # String fields are treated like other singular fields, but note that the
86
+ # default value for string fields is frozen, so it is effectively an immutable
87
+ # string. Attempting to modify this default string will raise a TypeError,
88
+ # so assign a new string to the field instead.
89
+ #
90
+ # === Singular Message Fields
91
+ #
92
+ # Message types are a bit special, since they are mutable. Accessing an unset
93
+ # message field will return a default instance of the message type. Say you
94
+ # have the following <tt>.proto</tt> definition:
95
+ #
96
+ # message Foo {
97
+ # optional Bar bar = 1;
98
+ # }
99
+ # message Bar {
100
+ # optional int32 i = 1;
101
+ # }
102
+ #
103
+ # To set the message field, you can do either of the following:
104
+ #
105
+ # foo = Foo.new
106
+ # assert(!foo.has_bar?)
107
+ # foo.bar = Bar.new
108
+ # assert(foo.has_bar?)
109
+ #
110
+ # Or, to set bar, you can simply assign a value directly to a field within
111
+ # bar, and - presto! - foo has a bar field:
112
+ #
113
+ # foo = Foo.new
114
+ # assert(!foo.has_bar?)
115
+ # foo.bar.i = 1
116
+ # assert(foo.has_bar?)
117
+ #
118
+ # Note that simply reading a field inside bar does not set the field:
119
+ #
120
+ # foo = Foo.new
121
+ # assert(!foo.has_bar?)
122
+ # puts foo.bar.i
123
+ # assert(!foo.has_bar?)
124
+ #
125
+ # === Repeated Fields
126
+ #
127
+ # Repeated fields are represented as an object that acts like an Array.
128
+ # For example, given this message definition:
129
+ #
130
+ # message Foo {
131
+ # repeated int32 nums = 1;
132
+ # }
133
+ #
134
+ # You can do the following:
135
+ #
136
+ # foo = Foo.new
137
+ # foo.nums << 15
138
+ # foo.nums.push(32)
139
+ # assert(foo.nums.length == 2)
140
+ # assert(foo.nums[0] == 15)
141
+ # assert(foo.nums[1] == 32)
142
+ # foo.nums.each { |i| puts i }
143
+ # foo.nums[1] = 56
144
+ # assert(foo.nums[1] == 56)
145
+ #
146
+ # To clear a repeated field, call the <tt>clear</tt> method, or assign nil to
147
+ # it like a singular field.
148
+ #
149
+ # foo = Foo.new
150
+ # foo.nums << 15
151
+ # foo.nums.push(32)
152
+ # assert(foo.nums.length == 2)
153
+ # foo.nums.clear
154
+ # assert(foo.nums.length == 0)
155
+ # foo.nums = nil # equivalent to foo.nums.clear
156
+ # assert(foo.nums.length == 0)
157
+ #
158
+ # You can assign to a repeated field using an array, or any other object that
159
+ # responds to +each+. This will replace the current contents of the repeated
160
+ # field.
161
+ #
162
+ # foo = Foo.new
163
+ # foo.nums << 15
164
+ # foo.nums = [1, 3, 5]
165
+ # assert(foo.nums.length == 3)
166
+ # assert(foo.nums.to_a == [1,3,5])
167
+ #
168
+ # Repeated fields are always set, so <tt>foo.has_nums?</tt> will always be
169
+ # true. Repeated fields don't take up any space in a serialized message if
170
+ # they are empty.
171
+ #
172
+ # === Repeated Message Fields
173
+ #
174
+ # Repeated message fields work like other repeated fields. For example, given
175
+ # this message definition:
176
+ #
177
+ # message Foo {
178
+ # repeated Bar bars = 1;
179
+ # }
180
+ # message Bar {
181
+ # optional int32 i = 1;
182
+ # }
183
+ #
184
+ # You can do the following:
185
+ #
186
+ # foo = Foo.new
187
+ # foo.bars << Bar.new(:i => 15)
188
+ # foo.bars << Bar.new(:i => 32)
189
+ # assert(foo.bars.length == 2)
190
+ # assert(foo.bars[0].i == 15)
191
+ # assert(foo.bars[1].i == 32)
192
+ # foo.bars.each { |bar| puts bar.i }
193
+ # foo.bars[1].i = 56
194
+ # assert(foo.bars[1].i == 56)
195
+ #
196
+ # == Enumerations
197
+ #
198
+ # Enumerations are defined as a module with an integer constant for each
199
+ # valid value. For example, given:
200
+ #
201
+ # enum Foo {
202
+ # VALUE_A = 1;
203
+ # VALUE_B = 5;
204
+ # VALUE_C = 1234;
205
+ # }
206
+ #
207
+ # The following Ruby code will be generated:
208
+ #
209
+ # module Foo
210
+ # VALUE_A = 1
211
+ # VALUE_B = 5
212
+ # VALUE_C 1234
213
+ # end
214
+ #
215
+ # An exception will be thrown if an enum field is assigned a value not in the
216
+ # enum. Right now, this includes throwing an exception while parsing. This may
217
+ # change in the future to match the C++ behavior of treating it as an unknown
218
+ # tag number.
219
+ #
220
+ # == Extensions
221
+ #
222
+ # Protocol Buffer extensions are not currently supported in this library.
223
+ #
224
+ # == Services
225
+ #
226
+ # Protocol Buffer service (RPC) definitions are ignored.
227
+
228
+ class Message
229
+ # Create a new Message of this class.
230
+ #
231
+ # message = MyMessageClass.new(attributes)
232
+ # # is equivalent to
233
+ # message = MyMessageClass.new
234
+ # message.attributes = attributes
235
+ def initialize(attributes = {})
236
+ @set_fields = []
237
+
238
+ fields.each do |tag, field|
239
+ if field.repeated?
240
+ self.instance_variable_set("@#{field.name}", RepeatedField.new(field))
241
+ @set_fields[tag] = true # repeated fields are always "set"
242
+ else
243
+ value = field.default_value
244
+ self.__send__("#{field.name}=", value)
245
+ @set_fields[tag] = false
246
+ if field.class == Field::MessageField
247
+ value.notify_on_change(self, tag)
248
+ end
249
+ end
250
+ end
251
+
252
+ self.attributes = attributes
253
+ end
254
+
255
+ # Serialize this Message to the given IO stream using the Protocol Buffer
256
+ # wire format.
257
+ #
258
+ # Equivalent to, but more efficient than
259
+ #
260
+ # io << message
261
+ #
262
+ # Returns +io+
263
+ def serialize(io)
264
+ Encoder.encode(io, self)
265
+ io
266
+ end
267
+
268
+ # Serialize this Message to a String and return it.
269
+ def serialize_to_string
270
+ sio = StringIO.new
271
+ serialize(sio)
272
+ return sio.string
273
+ end
274
+ alias_method :to_s, :serialize_to_string
275
+
276
+ # Parse a Message of this class from the given IO/String. Since Protocol
277
+ # Buffers are not length delimited, this will read until the end of the
278
+ # stream.
279
+ #
280
+ # This does not call clear! beforehand, so this is logically equivalent to
281
+ #
282
+ # new_message = self.class.new
283
+ # new_message.parse(io)
284
+ # merge_from(new_message)
285
+ def parse(io_or_string)
286
+ io = io_or_string
287
+ if io.is_a?(String)
288
+ io = StringIO.new(io)
289
+ end
290
+ Decoder.decode(io, self)
291
+ return self
292
+ end
293
+
294
+ # Shortcut, simply calls self.new.parse(io)
295
+ def self.parse(io)
296
+ self.new.parse(io)
297
+ end
298
+
299
+ # Merge the attribute values from +obj+ into this Message, which must be of
300
+ # the same class.
301
+ #
302
+ # Singular fields will be overwritten, except for embedded messages which
303
+ # will be merged. Repeated fields will be concatenated.
304
+ def merge_from(obj)
305
+ raise(ArgumentError, "Incompatible merge types: #{self.class} and #{obj.class}") unless obj.is_a?(self.class)
306
+ for tag, field in self.class.fields
307
+ next unless obj.value_for_tag?(tag)
308
+ value = obj.value_for_tag(tag)
309
+ merge_field(tag, value, field)
310
+ end
311
+ end
312
+
313
+ # Parse the string into a new Message of this class, and merge it into the
314
+ # current message like +merge_from+.
315
+ def merge_from_string(string)
316
+ merge_from(self.class.new.parse(string))
317
+ end
318
+
319
+ # Assign values to attributes in bulk.
320
+ #
321
+ # message.attributes = { :field1 => value1, :field2 => value2 } -> message
322
+ def attributes=(hash = {})
323
+ hash.each do |name, value|
324
+ self.send("#{name}=", value)
325
+ end
326
+ self
327
+ end
328
+
329
+ # Comparison by class and field values.
330
+ def ==(obj)
331
+ return false unless obj.is_a?(self.class)
332
+ fields.each do |tag, field|
333
+ return false unless self.__send__(field.name) == obj.__send__(field.name)
334
+ end
335
+ return true
336
+ end
337
+
338
+ # Reset all fields to the default value.
339
+ def clear!
340
+ fields.each { |tag, field| self.__send__("#{field.name}=", nil) }
341
+ end
342
+
343
+ # This is a shallow copy.
344
+ def dup
345
+ ret = self.class.new
346
+ fields.each do |tag, field|
347
+ val = self.__send__(field.name)
348
+ ret.__send__("#{field.name}=", val)
349
+ end
350
+ return ret
351
+ end
352
+
353
+ # Returns a hash of { tag => ProtocolBuffers::Field }
354
+ def self.fields
355
+ @fields || @fields = {}
356
+ end
357
+
358
+ # Returns a hash of { tag => ProtocolBuffers::Field }
359
+ def fields
360
+ self.class.fields
361
+ end
362
+
363
+ # Find the field for the given attribute name. Returns a
364
+ # ProtocolBuffers::field
365
+ def self.field_for_name(name)
366
+ name = name.to_sym
367
+ field = fields.find { |tag,field| field.name == name }
368
+ field && field.last
369
+ end
370
+
371
+ # Equivalent to fields[tag]
372
+ def self.field_for_tag(tag)
373
+ fields[tag]
374
+ end
375
+
376
+ # Reflection: get the attribute value for the given tag id.
377
+ #
378
+ # message.value_for_tag(message.class.field_for_name(:f1).tag)
379
+ # # is equivalent to
380
+ # message.f1
381
+ def value_for_tag(tag)
382
+ self.__send__(fields[tag].name)
383
+ end
384
+
385
+ def set_value_for_tag(tag, value)
386
+ self.__send__("#{fields[tag].name}=", value)
387
+ end
388
+
389
+ # Reflection: does this Message have the field set?
390
+ #
391
+ # message.value_for_tag?(message.class.field_for_name(:f1).tag)
392
+ # # is equivalent to
393
+ # message.has_f1?
394
+ def value_for_tag?(tag)
395
+ @set_fields[tag] || false
396
+ end
397
+
398
+ def inspect
399
+ ret = StringIO.new
400
+ ret << "#<#{self.class.name}"
401
+ fields.each do |tag, field|
402
+ ret << " #{field.name}=#{field.inspect_value(self.__send__(field.name))}"
403
+ end
404
+ ret << ">"
405
+ return ret.string
406
+ end
407
+
408
+ def merge_field(tag, value, field = fields[tag]) # :nodoc:
409
+ if field.repeated?
410
+ if value.is_a?(Array)
411
+ self.__send__("#{field.name}=", self.__send__(field.name) + value)
412
+ else
413
+ self.__send__(field.name) << value
414
+ end
415
+ else
416
+ self.__send__("#{field.name}=", value)
417
+ @set_fields[tag] = true
418
+ end
419
+ end
420
+
421
+ def self.define_field(otype, type, name, tag, opts = {}) # :NODOC:
422
+ raise("gen_methods! already called, cannot add more fields") if @methods_generated
423
+ type = type.is_a?(Module) ? type : type.to_sym
424
+ name = name.to_sym
425
+ tag = tag.to_i
426
+ raise("Field already exists for tag: #{tag}") if fields[tag]
427
+ field = Field.create(self, otype, type, name, tag, opts)
428
+ fields[tag] = field
429
+ field.add_methods_to(self)
430
+ end
431
+
432
+ def self.required(type, name, tag, opts = {}) # :NODOC:
433
+ define_field(:required, type, name, tag, opts)
434
+ @has_required_field = true
435
+ end
436
+
437
+ def self.optional(type, name, tag, opts = {}) # :NODOC:
438
+ define_field(:optional, type, name, tag, opts)
439
+ end
440
+
441
+ def self.repeated(type, name, tag, opts = {}) # :NODOC:
442
+ define_field(:repeated, type, name, tag, opts)
443
+ end
444
+
445
+ def notify_on_change(parent, tag)
446
+ @parent_for_notify = parent
447
+ @tag_for_notify = tag
448
+ end
449
+
450
+ def default_changed(tag)
451
+ @set_fields[tag] = true
452
+ if @parent_for_notify
453
+ @parent_for_notify.default_changed(@tag_for_notify)
454
+ @parent_for_notify = @tag_for_notify = nil
455
+ end
456
+ end
457
+
458
+ def valid?
459
+ self.class.valid?(self)
460
+ end
461
+
462
+ def self.valid?(message)
463
+ return true unless @has_required_field
464
+
465
+ fields.each do |tag, field|
466
+ if field.otype == :required
467
+ return false unless message.value_for_tag?(tag)
468
+ end
469
+ end
470
+ end
471
+
472
+ def remember_unknown_field(tag_int, value)
473
+ @unknown_fields || @unknown_fields = []
474
+ @unknown_fields << [tag_int, value]
475
+ end
476
+
477
+ # yields |tag_int, value| pairs
478
+ def each_unknown_field # :nodoc:
479
+ return unless @unknown_fields
480
+ @unknown_fields.each { |tag_int, value| yield tag_int, value }
481
+ end
482
+
483
+ # Generate the initialize method using reflection, to improve speed. This is
484
+ # called by the generated .pb.rb code, it's not necessary to call this
485
+ # method directly.
486
+ def self.gen_methods! # :NODOC:
487
+ @methods_generated = true
488
+ # these generated methods have gone away for now -- the infrastructure has
489
+ # been left in place, since they'll probably make their way back in at
490
+ # some point.
491
+ end
492
+
493
+ end
494
+ end