protobuf 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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