ruby_protobuf 0.3.3 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.txt +10 -2
  2. data/Manifest.txt +26 -12
  3. data/README.txt +6 -1
  4. data/Rakefile +51 -14
  5. data/TODO +15 -0
  6. data/VERSION +1 -0
  7. data/bin/rprotoc +11 -6
  8. data/lib/protobuf/common/exceptions.rb +11 -0
  9. data/lib/protobuf/common/util.rb +9 -0
  10. data/lib/protobuf/common/wire_type.rb +6 -6
  11. data/lib/protobuf/compiler/compiler.rb +16 -16
  12. data/lib/protobuf/compiler/nodes.rb +67 -65
  13. data/lib/protobuf/compiler/proto.y +31 -38
  14. data/lib/protobuf/compiler/proto_parser.rb +315 -294
  15. data/lib/protobuf/compiler/template/rpc_bin.erb +1 -1
  16. data/lib/protobuf/compiler/template/rpc_client.erb +1 -1
  17. data/lib/protobuf/compiler/template/rpc_service.erb +2 -2
  18. data/lib/protobuf/compiler/visitors.rb +45 -39
  19. data/lib/protobuf/descriptor/descriptor.proto +0 -0
  20. data/lib/protobuf/descriptor/descriptor.rb +11 -10
  21. data/lib/protobuf/descriptor/descriptor_builder.rb +6 -7
  22. data/lib/protobuf/descriptor/descriptor_proto.rb +51 -31
  23. data/lib/protobuf/descriptor/enum_descriptor.rb +5 -5
  24. data/lib/protobuf/descriptor/field_descriptor.rb +8 -9
  25. data/lib/protobuf/descriptor/file_descriptor.rb +0 -1
  26. data/lib/protobuf/message/decoder.rb +33 -35
  27. data/lib/protobuf/message/encoder.rb +23 -19
  28. data/lib/protobuf/message/enum.rb +43 -9
  29. data/lib/protobuf/message/field.rb +281 -193
  30. data/lib/protobuf/message/message.rb +166 -110
  31. data/lib/protobuf/message/protoable.rb +4 -3
  32. data/lib/protobuf/message/service.rb +1 -1
  33. data/lib/protobuf/rpc/client.rb +3 -3
  34. data/lib/protobuf/rpc/handler.rb +1 -1
  35. data/lib/protobuf/rpc/server.rb +8 -8
  36. data/lib/ruby_protobuf.rb +1 -1
  37. data/test/check_unbuild.rb +7 -7
  38. data/test/proto/addressbook.pb.rb +67 -0
  39. data/test/proto/addressbook.proto +2 -0
  40. data/test/proto/addressbook_base.pb.rb +59 -0
  41. data/test/proto/addressbook_base.proto +1 -1
  42. data/test/proto/addressbook_ext.pb.rb +21 -0
  43. data/test/proto/addressbook_ext.proto +2 -2
  44. data/test/{collision.rb → proto/collision.pb.rb} +0 -0
  45. data/test/{ext_collision.rb → proto/ext_collision.pb.rb} +1 -1
  46. data/test/{ext_range.rb → proto/ext_range.pb.rb} +4 -4
  47. data/test/proto/ext_range.proto +2 -2
  48. data/test/proto/float_default.proto +10 -0
  49. data/test/proto/lowercase.pb.rb +31 -0
  50. data/test/proto/lowercase.proto +9 -0
  51. data/test/{merge.rb → proto/merge.pb.rb} +2 -2
  52. data/test/proto/nested.pb.rb +31 -0
  53. data/test/proto/nested.proto +2 -0
  54. data/test/proto/optional_field.pb.rb +36 -0
  55. data/test/proto/optional_field.proto +12 -0
  56. data/test/proto/packed.pb.rb +23 -0
  57. data/test/proto/packed.proto +6 -0
  58. data/test/{types.rb → proto/types.pb.rb} +43 -1
  59. data/test/test_addressbook.rb +30 -17
  60. data/test/test_compiler.rb +79 -78
  61. data/test/test_descriptor.rb +12 -12
  62. data/test/test_enum_value.rb +41 -0
  63. data/test/test_extension.rb +10 -14
  64. data/test/test_lowercase.rb +11 -0
  65. data/test/test_message.rb +44 -41
  66. data/test/test_optional_field.rb +61 -38
  67. data/test/test_packed_field.rb +40 -0
  68. data/test/test_parse.rb +8 -8
  69. data/test/test_repeated_types.rb +29 -3
  70. data/test/test_serialize.rb +12 -12
  71. data/test/test_standard_message.rb +30 -30
  72. data/test/test_types.rb +95 -95
  73. metadata +69 -39
  74. data/test/addressbook.rb +0 -98
  75. data/test/addressbook_base.rb +0 -62
  76. data/test/addressbook_ext.rb +0 -12
  77. data/test/nested.rb +0 -25
  78. data/test/test_ruby_protobuf.rb +0 -1
@@ -1,91 +1,178 @@
1
+ require 'protobuf/common/util'
1
2
  require 'protobuf/common/wire_type'
2
3
  require 'protobuf/descriptor/field_descriptor'
3
4
 
4
5
  module Protobuf
5
6
  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"
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")
12
23
  else
13
- Protobuf::Field::FieldProxy
24
+ FieldProxy
14
25
  end
15
- field_class.new message_class, rule, type, name, tag, opts
26
+ field_class.new(message_class, rule, type, name, tag, options)
16
27
  end
17
28
 
18
- class InvalidRuleError < StandardError; end
19
-
20
29
  class BaseField
21
- class <<self
22
- def descriptor
23
- @descriptor ||= Protobuf::Descriptor::FieldDescriptor.new
24
- end
25
30
 
26
- def default; nil end
31
+ def self.descriptor
32
+ @descriptor ||= Descriptor::FieldDescriptor.new
33
+ end
34
+
35
+ def self.default
36
+ nil
27
37
  end
28
38
 
29
- attr_accessor :message_class, :rule, :type, :name, :tag, :default
39
+ attr_reader :message_class, :rule, :type, :name, :tag, :default
40
+ attr_reader :default_value
30
41
 
31
42
  def descriptor
32
- @descriptor ||= Protobuf::Descriptor::FieldDescriptor.new self
43
+ @descriptor ||= Descriptor::FieldDescriptor.new(self)
33
44
  end
34
45
 
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'
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
+
39
70
  define_accessor
40
71
  end
41
72
 
42
- def ready?; true end
73
+ def ready?
74
+ true
75
+ end
43
76
 
44
- def initialized?(message)
45
- case rule
77
+ def initialized?(message_instance)
78
+ value = message_instance.__send__(@name)
79
+ case @rule
46
80
  when :required
47
- return false if message[name].nil?
48
- return false if is_a?(Protobuf::Field::MessageField) and not message[name].initialized?
81
+ ! value.nil? && (! kind_of?(MessageField) || value.initialized?)
49
82
  when :repeated
50
- return message[name].all? {|msg|
51
- (not is_a?(Protobuf::Field::MessageField)) or msg.initialized?
52
- }
83
+ value.all? {|msg| ! kind_of?(MessageField) || msg.initialized? }
53
84
  when :optional
54
- return false if message[name] and is_a?(Protobuf::Field::MessageField) and not message[name].initialized?
85
+ value.nil? || ! kind_of?(MessageField) || value.initialized?
55
86
  end
56
- true
57
87
  end
58
88
 
59
- def clear(message)
60
- if repeated?
61
- message[name].clear
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
62
103
  else
63
- message.instance_variable_get(:@values).delete(name)
104
+ value = decode(bytes)
105
+ if repeated?
106
+ message_instance.__send__(@name) << value
107
+ else
108
+ message_instance.__send__("#{@name}=", value)
109
+ end
64
110
  end
65
111
  end
66
112
 
67
- def default_value
68
- case rule
69
- when :repeated
70
- FieldArray.new self
71
- when :required
72
- nil
73
- when :optional
74
- typed_default_value default
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)
75
127
  else
76
- raise InvalidRuleError
128
+ merge_value(message_instance, value)
77
129
  end
78
130
  end
79
131
 
80
- def typed_default_value(default=nil)
81
- default or self.class.default
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}]" : ''}"
82
169
  end
83
170
 
84
171
  private
85
172
 
86
173
  def define_accessor
87
174
  define_getter
88
- if rule == :repeated
175
+ if repeated?
89
176
  define_array_setter
90
177
  else
91
178
  define_setter
@@ -111,7 +198,7 @@ module Protobuf
111
198
  define_method("#{field.name}=") do |val|
112
199
  if val.nil?
113
200
  @values.delete(field.name)
114
- elsif field.acceptable? val
201
+ elsif field.acceptable?(val)
115
202
  @values[field.name] = val
116
203
  end
117
204
  end
@@ -127,117 +214,77 @@ module Protobuf
127
214
  end
128
215
  end
129
216
 
130
- public
131
-
132
- # encoder/decoder related methods
133
-
134
- def set(message_instance, bytes)
135
- value = decode(bytes)
136
- if repeated?
137
- message_instance.send(name) << value
138
- else
139
- message_instance.send("#{name}=", value)
140
- end
141
- end
142
-
143
- def get(value)
144
- encode(value)
145
- end
146
-
147
- def decode(bytes)
148
- raise NotImplementedError.new("#{self.class.name}\#decode")
217
+ def merge_array(message_instance, value)
218
+ message_instance.__send__(@name).concat(value)
149
219
  end
150
- private :decode
151
220
 
152
- def encode(value)
153
- raise NotImplementedError.new("#{self.class.name}\#encode")
221
+ def merge_value(message_instance, value)
222
+ message_instance.__send__("#{@name}=", value)
154
223
  end
155
- private :encode
156
224
 
157
- def merge(message_instance, value)
158
- if repeated?
159
- merge_array message_instance, value
225
+ def typed_default_value
226
+ if @default.nil?
227
+ self.class.default
160
228
  else
161
- merge_value message_instance, value
229
+ @default
162
230
  end
163
231
  end
164
232
 
165
- def merge_array(message_instance, value)
166
- message_instance[tag].concat value
167
- end
233
+ end # BaseField
168
234
 
169
- def merge_value(message_instance, value)
170
- message_instance[tag] = value
171
- end
172
-
173
- # utility methods
174
-
175
- def repeated?; rule == :repeated end
176
- def required?; rule == :required end
177
- def optional?; rule == :optional end
178
-
179
- def max; self.class.max end
180
- def min; self.class.min end
181
-
182
- def acceptable?(val)
183
- true
184
- end
185
235
 
186
- def error_message
187
- @error_message
188
- end
236
+ class FieldProxy
189
237
 
190
- def to_s
191
- "#{rule} #{type} #{name} = #{tag} #{default ? "[default=#{default}]" : ''}"
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
192
241
  end
193
- end
194
242
 
195
- class FieldProxy
196
- def initialize(message_class, rule, type, name, tag, opts={})
197
- @message_class, @rule, @type, @name, @tag, @opts =
198
- message_class, rule, type, name, tag, opts
243
+ def ready?
244
+ false
199
245
  end
200
246
 
201
- def ready?; false end
202
-
203
247
  def setup
204
- type = typename_to_class @message_class, @type
205
- field_class =
206
- if type.superclass == Protobuf::Enum
207
- Protobuf::Field::EnumField
208
- elsif type.superclass == Protobuf::Message
209
- Protobuf::Field::MessageField
248
+ type = typename_to_class(@message_class, @type)
249
+ field_class = \
250
+ if type < Enum
251
+ EnumField
252
+ elsif type < Message
253
+ MessageField
210
254
  else
211
- raise TypeError.new(type.inspect)
255
+ raise TypeError, type.inspect
212
256
  end
213
- field_class.new @message_class, @rule, type, @name, @tag, @opts
257
+ field_class.new(@message_class, @rule, type, @name, @tag, @options)
214
258
  end
215
259
 
260
+ private
261
+
216
262
  def typename_to_class(message_class, type)
217
- suffix = type.to_s.split('::')
218
- modules = message_class.to_s.split('::')
219
- args = (Object.method(:const_defined?).arity == 1) ? [] : [nil, false]
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]
220
266
  while
221
- mod = modules.empty? ? Object : eval(modules.join('::'))
222
- mod = suffix.inject(mod) {|m, s|
223
- args[0] = s
224
- m and m.const_defined?(*args) and m.const_get(s)
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)
225
270
  }
226
271
  break if mod
227
- raise NameError.new("type not found: #{type}", type) if modules.empty?
228
- modules.pop
272
+ raise NameError.new("type not found: #{type}", type) if outer.empty?
273
+ outer.pop
229
274
  end
230
275
  mod
231
276
  end
277
+
232
278
  end
233
279
 
234
280
  class FieldArray < Array
281
+
235
282
  def initialize(field)
236
283
  @field = field
237
284
  end
238
285
 
239
286
  def []=(nth, val)
240
- super(normalize(val))
287
+ super(nth, normalize(val))
241
288
  end
242
289
 
243
290
  def <<(val)
@@ -272,39 +319,49 @@ module Protobuf
272
319
  val
273
320
  end
274
321
  end
322
+
275
323
  end
276
324
 
325
+ # Field class for +bytes+ type.
277
326
  class BytesField < BaseField
278
- class <<self
279
- def default; '' end
327
+ def self.default
328
+ ''
280
329
  end
281
330
 
282
331
  def wire_type
283
- Protobuf::WireType::LENGTH_DELIMITED
332
+ WireType::LENGTH_DELIMITED
284
333
  end
285
334
 
286
335
  def acceptable?(val)
287
- raise TypeError unless val.instance_of? String
336
+ raise TypeError unless val.instance_of?(String)
288
337
  true
289
338
  end
290
339
 
291
340
  def decode(bytes)
292
- bytes.pack('C*')
341
+ bytes.force_encoding(Encoding::ASCII_8BIT) if bytes.respond_to?(:force_encoding)
342
+ bytes
293
343
  end
294
344
 
295
345
  def encode(value)
296
- value = value.dup
297
- value.force_encoding('ASCII-8BIT') if value.respond_to?(:force_encoding)
298
- string_size = VarintField.encode(value.size)
299
- string_size << value
346
+ if value.respond_to?(:force_encoding)
347
+ # Ruby 1.9
348
+ old_encoding = value.encoding
349
+ result = VarintField.encode(value.bytesize)
350
+ result << value.force_encoding(Encoding::ASCII_8BIT)
351
+ value.force_encoding(old_encoding)
352
+ result
353
+ else
354
+ # Ruby 1.8
355
+ result = VarintField.encode(value.size)
356
+ result << value
357
+ end
300
358
  end
301
359
  end
302
360
 
303
361
  class StringField < BytesField
304
362
  def decode(bytes)
305
- message = bytes.pack('C*')
306
- message.force_encoding('UTF-8') if message.respond_to?(:force_encoding)
307
- message
363
+ bytes.force_encoding(Encoding::UTF_8) if bytes.respond_to?(:force_encoding)
364
+ bytes
308
365
  end
309
366
  end
310
367
 
@@ -317,7 +374,9 @@ module Protobuf
317
374
  UINT64_MAX = 2**64 - 1
318
375
 
319
376
  class <<self
320
- def default; 0 end
377
+ def default
378
+ 0
379
+ end
321
380
 
322
381
  def decode(bytes)
323
382
  value = 0
@@ -328,7 +387,7 @@ module Protobuf
328
387
  end
329
388
 
330
389
  def encode(value)
331
- raise RangeError.new(value) if value < 0
390
+ raise RangeError, "#{value} is negative" if value < 0
332
391
  return [value].pack('C') if value < 128
333
392
  bytes = []
334
393
  until value == 0
@@ -341,11 +400,11 @@ module Protobuf
341
400
  end
342
401
 
343
402
  def wire_type
344
- Protobuf::WireType::VARINT
403
+ WireType::VARINT
345
404
  end
346
405
 
347
- def decode(bytes)
348
- self.class.decode(bytes)
406
+ def decode(value)
407
+ value
349
408
  end
350
409
 
351
410
  def encode(value)
@@ -353,8 +412,8 @@ module Protobuf
353
412
  end
354
413
 
355
414
  def acceptable?(val)
356
- raise TypeError.new(val.class.name) unless val.is_a? Integer
357
- raise RangeError.new(val) if val < min or max < val
415
+ raise TypeError, val.class.name unless val.is_a?(Integer)
416
+ raise RangeError if val < min || max < val
358
417
  true
359
418
  end
360
419
  end
@@ -366,8 +425,7 @@ module Protobuf
366
425
  VarintField.encode(value & 0xffff_ffff_ffff_ffff)
367
426
  end
368
427
 
369
- def decode(bytes)
370
- value = VarintField.decode(bytes)
428
+ def decode(value)
371
429
  value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero?
372
430
  value
373
431
  end
@@ -395,8 +453,7 @@ module Protobuf
395
453
 
396
454
  # Base class for sint32 and sint64
397
455
  class SignedIntegerField < VarintField
398
- def decode(bytes)
399
- value = VarintField.decode(bytes)
456
+ def decode(value)
400
457
  if (value & 1).zero?
401
458
  value >> 1 # positive value
402
459
  else
@@ -429,7 +486,7 @@ module Protobuf
429
486
  def self.min; -1.0/0; end
430
487
 
431
488
  def wire_type
432
- Protobuf::WireType::FIXED32
489
+ WireType::FIXED32
433
490
  end
434
491
 
435
492
  def decode(bytes)
@@ -441,15 +498,15 @@ module Protobuf
441
498
  end
442
499
 
443
500
  def acceptable?(val)
444
- raise TypeError.new(val.class.name) unless val.is_a? Numeric
445
- raise RangeError.new(val) if val < min or max < val
501
+ raise TypeError, val.class.name unless val.is_a?(Numeric)
502
+ raise RangeError if val < min || max < val
446
503
  true
447
504
  end
448
505
  end
449
506
 
450
507
  class DoubleField < FloatField
451
508
  def wire_type
452
- Protobuf::WireType::FIXED64
509
+ WireType::FIXED64
453
510
  end
454
511
 
455
512
  def decode(bytes)
@@ -463,7 +520,7 @@ module Protobuf
463
520
 
464
521
  class Fixed32Field < Uint32Field
465
522
  def wire_type
466
- Protobuf::WireType::FIXED32
523
+ WireType::FIXED32
467
524
  end
468
525
 
469
526
  def decode(bytes)
@@ -477,7 +534,7 @@ module Protobuf
477
534
 
478
535
  class Fixed64Field < Uint64Field
479
536
  def wire_type
480
- Protobuf::WireType::FIXED64
537
+ WireType::FIXED64
481
538
  end
482
539
 
483
540
  def decode(bytes)
@@ -494,7 +551,7 @@ module Protobuf
494
551
 
495
552
  class Sfixed32Field < Int32Field
496
553
  def wire_type
497
- Protobuf::WireType::FIXED32
554
+ WireType::FIXED32
498
555
  end
499
556
 
500
557
  def decode(bytes)
@@ -510,7 +567,7 @@ module Protobuf
510
567
 
511
568
  class Sfixed64Field < Int64Field
512
569
  def wire_type
513
- Protobuf::WireType::FIXED64
570
+ WireType::FIXED64
514
571
  end
515
572
 
516
573
  def decode(bytes)
@@ -528,17 +585,17 @@ module Protobuf
528
585
  end
529
586
 
530
587
  class BoolField < VarintField
531
- class <<self
532
- def default; false end
588
+ def self.default
589
+ false
533
590
  end
534
591
 
535
592
  def acceptable?(val)
536
- raise TypeError unless [TrueClass, FalseClass].include? val.class
593
+ raise TypeError unless [true, false].include?(val)
537
594
  true
538
595
  end
539
596
 
540
- def decode(bytes)
541
- bytes.first == 1
597
+ def decode(value)
598
+ value == 1
542
599
  end
543
600
 
544
601
  def encode(value)
@@ -546,11 +603,31 @@ module Protobuf
546
603
  end
547
604
  end
548
605
 
606
+
549
607
  class MessageField < BaseField
550
- class <<self
551
- def default; nil end
608
+ def wire_type
609
+ WireType::LENGTH_DELIMITED
610
+ end
611
+
612
+ def acceptable?(val)
613
+ raise TypeError unless val.instance_of?(type) || val.instance_of?(Hash)
614
+ true
615
+ end
616
+
617
+ def decode(bytes)
618
+ message = type.new
619
+ message.parse_from_string(bytes)
620
+ message
621
+ end
622
+
623
+ def encode(value)
624
+ bytes = value.serialize_to_string
625
+ result = VarintField.encode(bytes.size)
626
+ result << bytes
552
627
  end
553
628
 
629
+ private
630
+
554
631
  def define_setter
555
632
  field = self
556
633
  @message_class.class_eval do
@@ -563,59 +640,70 @@ module Protobuf
563
640
  when field.type
564
641
  @values[field.name] = val
565
642
  else
566
- raise TypeError
643
+ raise TypeError, "Expected value of type '#{field.type}', but got '#{val.class}'"
567
644
  end
568
645
  end
569
646
  end
570
647
  end
571
648
 
572
- def wire_type
573
- Protobuf::WireType::LENGTH_DELIMITED
649
+ def merge_value(message_instance, value)
650
+ message_instance.__send__(@name).merge_from(value)
574
651
  end
652
+ end
575
653
 
576
- def typed_default_value(default=nil)
577
- if default.is_a? Symbol
578
- type.module_eval default.to_s
579
- else
580
- default
581
- end
582
- end
583
654
 
655
+ class EnumField < VarintField
584
656
  def acceptable?(val)
585
- raise TypeError unless val.instance_of?(type) or val.instance_of?(Hash)
657
+ case val
658
+ when Symbol
659
+ raise TypeError unless @type.const_defined?(val)
660
+ when EnumValue
661
+ raise TypeError if val.parent_class != @type
662
+ else
663
+ raise TypeError unless @type.valid_tag?(val)
664
+ end
586
665
  true
587
666
  end
588
667
 
589
- def decode(bytes)
590
- message = type.new
591
- message.parse_from_string bytes.pack('C*') # TODO
592
- message
593
- end
594
-
595
668
  def encode(value)
596
- bytes = value.serialize_to_string
597
- string_size = VarintField.encode bytes.size
598
- string_size << bytes
669
+ super(value.to_i)
599
670
  end
600
671
 
601
- def merge_value(message_instance, value)
602
- message_instance[tag].merge_from value
603
- end
604
- end
672
+ private
605
673
 
606
- class EnumField < VarintField
607
- def default
674
+ def typed_default_value
608
675
  if @default.is_a?(Symbol)
609
- type.const_get @default
676
+ @type.const_get(@default)
610
677
  else
611
- @default
678
+ self.class.default
612
679
  end
613
680
  end
614
681
 
615
- def acceptable?(val)
616
- raise TypeError unless type.valid_tag? val
617
- true
682
+ def define_setter
683
+ field = self
684
+ @message_class.class_eval do
685
+ define_method("#{field.name}=") do |val|
686
+ if val.nil?
687
+ @values.delete(field.name)
688
+ else
689
+ val = \
690
+ case val
691
+ when Symbol
692
+ field.type.const_get(val) rescue nil
693
+ when Integer
694
+ field.type.const_get(field.type.name_by_value(val)) rescue nil
695
+ when EnumValue
696
+ raise TypeError, "Invalid value: #{val.inspect}" if val.parent_class != field.type
697
+ val
698
+ end
699
+ raise TypeError, "Invalid value: #{val.inspect}" unless val
700
+
701
+ @values[field.name] = val
702
+ end
703
+ end
704
+ end
618
705
  end
706
+
619
707
  end
620
708
  end
621
709
  end