ruby_protobuf 0.3.2 → 0.3.3
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.
- data/History.txt +7 -2
- data/Manifest.txt +74 -0
- data/README.txt +1 -1
- data/Rakefile +5 -5
- data/bin/rprotoc +25 -10
- data/{test/proto → examples}/addressbook.pb.rb +1 -14
- data/examples/addressbook.proto +24 -0
- data/examples/reading_a_message.rb +32 -0
- data/examples/writing_a_message.rb +46 -0
- data/lib/protobuf/compiler/compiler.rb +9 -11
- data/lib/protobuf/compiler/nodes.rb +15 -7
- data/lib/protobuf/compiler/proto.y +56 -36
- data/lib/protobuf/compiler/proto_parser.rb +373 -236
- data/lib/protobuf/compiler/visitors.rb +5 -1
- data/lib/protobuf/descriptor/enum_descriptor.rb +1 -1
- data/lib/protobuf/message/decoder.rb +12 -19
- data/lib/protobuf/message/encoder.rb +5 -2
- data/lib/protobuf/message/enum.rb +1 -1
- data/lib/protobuf/message/field.rb +302 -298
- data/lib/protobuf/message/message.rb +63 -35
- data/lib/ruby_protobuf.rb +1 -1
- data/{bin → script}/mk_parser +0 -0
- data/test/merge.rb +1 -1
- data/test/proto/types.proto +20 -0
- data/test/test_addressbook.rb +1 -0
- data/test/test_compiler.rb +21 -7
- data/test/test_message.rb +19 -0
- data/test/test_optional_field.rb +80 -0
- data/test/test_repeated_types.rb +106 -0
- data/test/test_serialize.rb +34 -0
- data/test/test_standard_message.rb +10 -0
- data/test/test_types.rb +49 -4
- data/test/types.rb +23 -2
- metadata +22 -20
- data/lib/protobuf/compiler/compiler_old.rb +0 -123
- data/test/proto/addressbook.rb +0 -69
- data/test/proto/bool_default.pb.rb +0 -16
- data/test/proto/bool_default.proto +0 -3
- data/test/proto/float_default.proto +0 -2
@@ -29,7 +29,7 @@ module Protobuf
|
|
29
29
|
|
30
30
|
class <<self
|
31
31
|
include Protobuf::Protoable
|
32
|
-
def fields; @fields ||=
|
32
|
+
def fields; @fields ||= {} end
|
33
33
|
|
34
34
|
def extensions(range)
|
35
35
|
@extension_fields = ExtensionFields.new range
|
@@ -53,7 +53,6 @@ module Protobuf
|
|
53
53
|
Field number #{tag} has already been used in "#{self.name}" by field "#{fname}".
|
54
54
|
eos
|
55
55
|
field_hash[tag] = Protobuf::Field.build self, rule, type, fname, tag, opts
|
56
|
-
#(@fields ||= {})[tag] = Protobuf::Field.build self, rule, type, fname, tag, opts
|
57
56
|
end
|
58
57
|
|
59
58
|
def extension_tag?(tag)
|
@@ -65,7 +64,8 @@ module Protobuf
|
|
65
64
|
end
|
66
65
|
|
67
66
|
def get_field_by_name(name)
|
68
|
-
|
67
|
+
name = name.to_sym
|
68
|
+
fields.values.find {|field| field.name == name}
|
69
69
|
end
|
70
70
|
|
71
71
|
def get_field_by_tag(tag)
|
@@ -82,7 +82,8 @@ module Protobuf
|
|
82
82
|
|
83
83
|
#TODO merge to get_field_by_name
|
84
84
|
def get_ext_field_by_name(name)
|
85
|
-
|
85
|
+
name = name.to_sym
|
86
|
+
extension_fields.values.find {|field| field.name == name}
|
86
87
|
end
|
87
88
|
|
88
89
|
#TODO merge to get_field_by_tag
|
@@ -105,12 +106,16 @@ module Protobuf
|
|
105
106
|
end
|
106
107
|
|
107
108
|
def initialize(values={})
|
108
|
-
|
109
|
+
@values = {}
|
110
|
+
|
111
|
+
self.class.fields.each do |tag, field|
|
109
112
|
unless field.ready?
|
110
113
|
field = field.setup
|
111
114
|
self.class.class_eval {@fields[tag] = field}
|
112
115
|
end
|
113
|
-
field.
|
116
|
+
if field.repeated?
|
117
|
+
@values[field.name] = Protobuf::Field::FieldArray.new(field)
|
118
|
+
end
|
114
119
|
end
|
115
120
|
|
116
121
|
# TODO
|
@@ -119,25 +124,29 @@ module Protobuf
|
|
119
124
|
field = field.setup
|
120
125
|
self.class.class_eval {@extension_fields[tag] = field}
|
121
126
|
end
|
122
|
-
field.
|
127
|
+
if field.repeated?
|
128
|
+
@values[field.name] = Protobuf::Field::FieldArray.new(field)
|
129
|
+
end
|
123
130
|
end
|
124
131
|
|
125
132
|
values.each {|tag, val| self[tag] = val}
|
126
133
|
end
|
127
134
|
|
128
135
|
def initialized?
|
129
|
-
fields.
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
136
|
+
fields.all? {|tag, field| field.initialized?(self) } && \
|
137
|
+
extension_fields.all? {|tag, field| field.initialized?(self) }
|
138
|
+
end
|
139
|
+
|
140
|
+
def has_field?(tag_or_name)
|
141
|
+
field = get_field(tag_or_name) || get_ext_field(tag_or_name)
|
142
|
+
raise ArgumentError.new("unknown field: #{tag_or_name.inspect}") unless field
|
143
|
+
@values.has_key?(field.name)
|
135
144
|
end
|
136
145
|
|
137
146
|
def ==(obj)
|
138
147
|
return false unless obj.is_a? self.class
|
139
148
|
each_field do |field, value|
|
140
|
-
return false unless value == obj
|
149
|
+
return false unless value == obj.send(field.name)
|
141
150
|
end
|
142
151
|
true
|
143
152
|
end
|
@@ -152,11 +161,12 @@ module Protobuf
|
|
152
161
|
ret = self.class.new
|
153
162
|
each_field do |field, value|
|
154
163
|
if field.repeated?
|
164
|
+
field_array = ret.send(field.name)
|
155
165
|
value.each do |v|
|
156
|
-
|
166
|
+
field_array << (v.is_a?(Numeric) ? v : v.dup)
|
157
167
|
end
|
158
168
|
else
|
159
|
-
ret
|
169
|
+
ret.send("#{field.name}=", value.is_a?(Numeric) ? value : value.dup)
|
160
170
|
end
|
161
171
|
end
|
162
172
|
ret
|
@@ -168,11 +178,31 @@ module Protobuf
|
|
168
178
|
field_value_to_string = lambda do |field, value|
|
169
179
|
ret +=
|
170
180
|
if field.is_a? Protobuf::Field::MessageField
|
171
|
-
|
181
|
+
if value.nil?
|
182
|
+
if $DEBUG
|
183
|
+
"#{i}#{field.name} {\n#{' ' * (indent + 1)}nil\n#{i}}\n"
|
184
|
+
else
|
185
|
+
"#{i}#{field.name} {}\n"
|
186
|
+
end
|
187
|
+
else
|
188
|
+
"#{i}#{field.name} {\n#{value.inspect(indent + 1)}#{i}}\n"
|
189
|
+
end
|
172
190
|
elsif field.is_a? Protobuf::Field::EnumField
|
173
|
-
|
191
|
+
if field.optional? and not has_field?(field.name)
|
192
|
+
''
|
193
|
+
else
|
194
|
+
"#{i}#{field.name}: #{field.type.name_by_value(value)}\n"
|
195
|
+
end
|
174
196
|
else
|
175
|
-
|
197
|
+
if $DEBUG
|
198
|
+
"#{i}#{field.name}: #{value.inspect}\n"
|
199
|
+
else
|
200
|
+
if field.optional? and not has_field?(field.name)
|
201
|
+
''
|
202
|
+
else
|
203
|
+
"#{i}#{field.name}: #{value.inspect}\n"
|
204
|
+
end
|
205
|
+
end
|
176
206
|
end
|
177
207
|
end
|
178
208
|
each_field do |field, value|
|
@@ -195,7 +225,7 @@ module Protobuf
|
|
195
225
|
if filename.is_a? File
|
196
226
|
parse_from filename
|
197
227
|
else
|
198
|
-
File.open(filename, '
|
228
|
+
File.open(filename, 'rb') do |f|
|
199
229
|
parse_from f
|
200
230
|
end
|
201
231
|
end
|
@@ -208,7 +238,9 @@ module Protobuf
|
|
208
238
|
def serialize_to_string(string='')
|
209
239
|
io = StringIO.new string
|
210
240
|
serialize_to io
|
211
|
-
io.string
|
241
|
+
result = io.string
|
242
|
+
result.force_encoding('ASCII-8BIT') if result.respond_to?(:force_encoding)
|
243
|
+
result
|
212
244
|
end
|
213
245
|
alias to_s serialize_to_string
|
214
246
|
|
@@ -216,7 +248,7 @@ module Protobuf
|
|
216
248
|
if filename.is_a? File
|
217
249
|
serialize_to filename
|
218
250
|
else
|
219
|
-
File.open(filename, '
|
251
|
+
File.open(filename, 'wb') do |f|
|
220
252
|
serialize_to f
|
221
253
|
end
|
222
254
|
end
|
@@ -233,8 +265,8 @@ module Protobuf
|
|
233
265
|
end
|
234
266
|
|
235
267
|
def set_field(tag, bytes)
|
236
|
-
|
237
|
-
|
268
|
+
field = (get_field_by_tag(tag) or get_ext_field_by_tag(tag))
|
269
|
+
field.set self, bytes if field
|
238
270
|
end
|
239
271
|
|
240
272
|
def merge_field(tag, value)
|
@@ -243,22 +275,18 @@ module Protobuf
|
|
243
275
|
end
|
244
276
|
|
245
277
|
def [](tag_or_name)
|
246
|
-
if field = get_field(tag_or_name)
|
247
|
-
send field.name
|
248
|
-
elsif field = get_ext_field(tag_or_name)
|
278
|
+
if field = get_field(tag_or_name) || get_ext_field(tag_or_name)
|
249
279
|
send field.name
|
250
280
|
else
|
251
|
-
raise NoMethodError.new("No such
|
281
|
+
raise NoMethodError.new("No such field: #{tag_or_name.inspect}")
|
252
282
|
end
|
253
283
|
end
|
254
284
|
|
255
285
|
def []=(tag_or_name, value)
|
256
|
-
if field = get_field(tag_or_name)
|
257
|
-
send "#{field.name}=", value
|
258
|
-
elsif field = get_ext_field(tag_or_name) and not field.repeated?
|
286
|
+
if field = get_field(tag_or_name) || get_ext_field(tag_or_name)
|
259
287
|
send "#{field.name}=", value
|
260
288
|
else
|
261
|
-
raise NoMethodError.new("No such
|
289
|
+
raise NoMethodError.new("No such field: #{tag_or_name.inspect}")
|
262
290
|
end
|
263
291
|
end
|
264
292
|
|
@@ -272,9 +300,9 @@ module Protobuf
|
|
272
300
|
def get_ext_field_by_tag(tag); self.class.get_ext_field_by_tag(tag) end
|
273
301
|
def get_ext_field(tag_or_name); self.class.get_ext_field(tag_or_name) end
|
274
302
|
|
275
|
-
def each_field
|
276
|
-
(fields.merge extension_fields).
|
277
|
-
|
303
|
+
def each_field
|
304
|
+
(fields.merge extension_fields).sort_by {|tag, field| tag}.each do |tag, field|
|
305
|
+
yield field, send(field.name)
|
278
306
|
end
|
279
307
|
end
|
280
308
|
end
|
data/lib/ruby_protobuf.rb
CHANGED
data/{bin → script}/mk_parser
RENAMED
File without changes
|
data/test/merge.rb
CHANGED
data/test/proto/types.proto
CHANGED
@@ -14,4 +14,24 @@ message TestTypes {
|
|
14
14
|
required bool type11 = 11;
|
15
15
|
required string type12 = 12;
|
16
16
|
required bytes type13 = 13;
|
17
|
+
required sfixed32 type14 = 14;
|
18
|
+
required sfixed64 type15 = 15;
|
19
|
+
}
|
20
|
+
|
21
|
+
message RepeatedTypes {
|
22
|
+
repeated double type1 = 1;
|
23
|
+
repeated float type2 = 2;
|
24
|
+
repeated int32 type3 = 3;
|
25
|
+
repeated int64 type4 = 4;
|
26
|
+
repeated uint32 type5 = 5;
|
27
|
+
repeated uint64 type6 = 6;
|
28
|
+
repeated sint32 type7 = 7;
|
29
|
+
repeated sint64 type8 = 8;
|
30
|
+
repeated fixed32 type9 = 9;
|
31
|
+
repeated fixed64 type10 = 10;
|
32
|
+
repeated bool type11 = 11;
|
33
|
+
repeated string type12 = 12;
|
34
|
+
repeated bytes type13 = 13;
|
35
|
+
repeated sfixed32 type14 = 14;
|
36
|
+
repeated sfixed64 type15 = 15;
|
17
37
|
}
|
data/test/test_addressbook.rb
CHANGED
@@ -6,6 +6,7 @@ require 'test/addressbook'
|
|
6
6
|
class AddressbookTest < Test::Unit::TestCase
|
7
7
|
def test_enum
|
8
8
|
phone_number = Tutorial::Person::PhoneNumber.new
|
9
|
+
assert_equal Tutorial::Person::PhoneType::HOME, phone_number.type
|
9
10
|
phone_number.type = Tutorial::Person::PhoneType::MOBILE
|
10
11
|
assert_equal 0, phone_number.type
|
11
12
|
phone_number.type = Tutorial::Person::PhoneType::HOME
|
data/test/test_compiler.rb
CHANGED
@@ -8,7 +8,15 @@ class CompilerTest < Test::Unit::TestCase
|
|
8
8
|
assert_compile_proto <<-eos, 'test/proto/float_default.proto'
|
9
9
|
### Generated by rprotoc. DO NOT EDIT!
|
10
10
|
### <proto file: test/proto/float_default.proto>
|
11
|
-
# message M {
|
11
|
+
# message M {
|
12
|
+
# optional float f = 1 [default = 4.2];
|
13
|
+
# optional float g = 2 [default = -4.2];
|
14
|
+
# optional float h = 3 [default = 4352];
|
15
|
+
# optional float i = 4 [default = 23145.2 ];
|
16
|
+
# optional float j = 5 [default = -5 ];
|
17
|
+
# optional float k = 6 [default = +23 ];
|
18
|
+
# optional float l = 7 [default = +23.42 ];
|
19
|
+
# }
|
12
20
|
#
|
13
21
|
|
14
22
|
require 'protobuf/message/message'
|
@@ -19,6 +27,12 @@ require 'protobuf/message/extend'
|
|
19
27
|
class M < ::Protobuf::Message
|
20
28
|
defined_in __FILE__
|
21
29
|
optional :float, :f, 1, :default => 4.2
|
30
|
+
optional :float, :g, 2, :default => -4.2
|
31
|
+
optional :float, :h, 3, :default => 4352
|
32
|
+
optional :float, :i, 4, :default => 23145.2
|
33
|
+
optional :float, :j, 5, :default => -5
|
34
|
+
optional :float, :k, 6, :default => 23
|
35
|
+
optional :float, :l, 7, :default => 23.42
|
22
36
|
end
|
23
37
|
eos
|
24
38
|
end
|
@@ -136,15 +150,15 @@ end
|
|
136
150
|
def test_nested_message
|
137
151
|
Protobuf::Visitor::CreateMessageVisitor.instance_eval {remove_const :Baaz}
|
138
152
|
file_contents = Protobuf::Compiler.new.create_message('test/proto/nested.proto', '.', '.', false)
|
139
|
-
assert_nothing_raised {
|
153
|
+
assert_nothing_raised {Object.class_eval file_contents}
|
140
154
|
assert_raise(TypeError) {Baaz.new.x = 1}
|
141
155
|
assert_nothing_raised {Baaz.new.x = Foo::Bar.new}
|
142
156
|
end
|
143
157
|
|
144
158
|
def test_create_rpc
|
145
|
-
file_contents = Protobuf::Compiler.new.create_rpc('test/proto/rpc.proto', '.', '
|
159
|
+
file_contents = Protobuf::Compiler.new.create_rpc('test/proto/rpc.proto', '.', 'test/proto', false)
|
146
160
|
|
147
|
-
assert_source <<-eos, file_contents['
|
161
|
+
assert_source <<-eos, file_contents['test/proto/address_book_service.rb']
|
148
162
|
require 'protobuf/rpc/server'
|
149
163
|
require 'protobuf/rpc/handler'
|
150
164
|
require 'test/proto/rpc.pb'
|
@@ -177,14 +191,14 @@ class Tutorial::AddressBookService < Protobuf::Rpc::Server
|
|
177
191
|
end
|
178
192
|
eos
|
179
193
|
|
180
|
-
assert_source <<-eos, file_contents['
|
194
|
+
assert_source <<-eos, file_contents['test/proto/start_address_book_service']
|
181
195
|
#!/usr/bin/env ruby
|
182
196
|
require 'address_book_service'
|
183
197
|
|
184
198
|
Tutorial::AddressBookService.new(:port => 9999).start
|
185
199
|
eos
|
186
200
|
|
187
|
-
assert_source <<-eos, file_contents['
|
201
|
+
assert_source <<-eos, file_contents['test/proto/client_search.rb']
|
188
202
|
#!/usr/bin/env ruby
|
189
203
|
require 'protobuf/rpc/client'
|
190
204
|
require 'test/proto/rpc.pb'
|
@@ -204,7 +218,7 @@ Protobuf::Rpc::Client.new('localhost', 9999).call :search, request, response
|
|
204
218
|
puts response
|
205
219
|
eos
|
206
220
|
|
207
|
-
assert_source <<-eos, file_contents['
|
221
|
+
assert_source <<-eos, file_contents['test/proto/client_add.rb']
|
208
222
|
#!/usr/bin/env ruby
|
209
223
|
require 'protobuf/rpc/client'
|
210
224
|
require 'test/proto/rpc.pb'
|
data/test/test_message.rb
CHANGED
@@ -3,6 +3,9 @@ require 'test/addressbook'
|
|
3
3
|
require 'test/merge'
|
4
4
|
require 'test/unit'
|
5
5
|
|
6
|
+
# It should not conflict with Test::InnerMessage1 which is included in merge.proto
|
7
|
+
class InnerMessage1; end
|
8
|
+
|
6
9
|
class MessageTest < Test::Unit::TestCase
|
7
10
|
def test_equality
|
8
11
|
person1 = Tutorial::Person.new :name => 'ando'
|
@@ -33,6 +36,22 @@ class MessageTest < Test::Unit::TestCase
|
|
33
36
|
assert_equal 'Jiro', person.name
|
34
37
|
assert_equal 300, person.id
|
35
38
|
assert_equal 'jiro@ema.il', person.email
|
39
|
+
|
40
|
+
# initialize with array of hash
|
41
|
+
person = Tutorial::Person.new(:phone => [{:number => 'phone1'}, {:number => 'phone2'}])
|
42
|
+
assert_equal 'phone1', person.phone[0].number
|
43
|
+
assert_equal 'phone2', person.phone[1].number
|
44
|
+
|
45
|
+
# initalize with hash in hash
|
46
|
+
message = Test::MergeMessage.new(:require_message => { :name => 'name1', :repeate_message => [{:name => 'name2'}] })
|
47
|
+
assert_equal 'name1', message.require_message.name
|
48
|
+
assert_equal 'name2', message.require_message.repeate_message[0].name
|
49
|
+
|
50
|
+
message.require_message = { :name => 'name21' }
|
51
|
+
message.require_message.repeate_message = [ {:name => 'name22'} ]
|
52
|
+
assert_equal 'name21', message.require_message.name
|
53
|
+
assert_equal 'name22', message.require_message.repeate_message[0].name
|
54
|
+
assert_equal 1, message.require_message.repeate_message.size
|
36
55
|
end
|
37
56
|
|
38
57
|
def test_defined_filenames
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/optional_field'
|
3
|
+
|
4
|
+
class OptionalFieldTest < Test::Unit::TestCase
|
5
|
+
def test_accessor
|
6
|
+
message = Test::Optional_field::Message.new
|
7
|
+
|
8
|
+
# default values
|
9
|
+
assert !message.has_field?(:number)
|
10
|
+
assert_equal 20, message.number
|
11
|
+
|
12
|
+
assert !message.has_field?(:text)
|
13
|
+
assert_equal 'default string', message.text
|
14
|
+
|
15
|
+
assert !message.has_field?(:enum)
|
16
|
+
assert_equal 2, message.enum
|
17
|
+
|
18
|
+
assert !message.has_field?(:signed)
|
19
|
+
assert_equal(-100, message.signed)
|
20
|
+
|
21
|
+
# assign values
|
22
|
+
assert_nothing_raised { message.number = 100 }
|
23
|
+
assert message.has_field?(:number)
|
24
|
+
assert_equal 100, message.number
|
25
|
+
|
26
|
+
assert_nothing_raised { message.text = 'abc' }
|
27
|
+
assert message.has_field?(:text)
|
28
|
+
assert_equal 'abc', message.text
|
29
|
+
|
30
|
+
assert_nothing_raised { message.enum = Test::Optional_field::Message::Enum::A }
|
31
|
+
assert message.has_field?(:enum)
|
32
|
+
assert_equal 1, message.enum
|
33
|
+
|
34
|
+
assert_nothing_raised { message.signed = -20 }
|
35
|
+
assert message.has_field?(:signed)
|
36
|
+
assert_equal(-20, message.signed)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_serialize
|
40
|
+
message1 = Test::Optional_field::Message.new
|
41
|
+
message2 = Test::Optional_field::Message.new
|
42
|
+
|
43
|
+
# all fields are empty
|
44
|
+
serialized_string = message1.to_s
|
45
|
+
assert serialized_string.empty?
|
46
|
+
message2.parse_from_string(serialized_string)
|
47
|
+
assert_equal message1.number, message2.number
|
48
|
+
assert_equal message1.text, message2.text
|
49
|
+
assert_equal message1.enum, message2.enum
|
50
|
+
assert_equal message1.signed, message2.signed
|
51
|
+
assert !message2.has_field?(:number)
|
52
|
+
assert !message2.has_field?(:text)
|
53
|
+
assert !message2.has_field?(:enum)
|
54
|
+
assert !message2.has_field?(:signed)
|
55
|
+
|
56
|
+
# assign the value whith is equal to default value
|
57
|
+
message1 = Test::Optional_field::Message.new
|
58
|
+
message1.number = message1.number
|
59
|
+
message1.text = message1.text
|
60
|
+
message1.enum = message1.enum
|
61
|
+
message1.signed = message1.signed
|
62
|
+
serialized_string = message1.to_s
|
63
|
+
assert !serialized_string.empty?
|
64
|
+
|
65
|
+
# set some fields
|
66
|
+
message1 = Test::Optional_field::Message.new
|
67
|
+
message1.number = 100
|
68
|
+
message1.text = 'new text'
|
69
|
+
serialized_string = message1.to_s
|
70
|
+
message2.parse_from_string(serialized_string)
|
71
|
+
assert_equal message1.number, message2.number
|
72
|
+
assert_equal message1.text, message2.text
|
73
|
+
assert_equal message1.enum, message2.enum
|
74
|
+
assert_equal message1.signed, message2.signed
|
75
|
+
assert message2.has_field?(:number)
|
76
|
+
assert message2.has_field?(:text)
|
77
|
+
assert !message2.has_field?(:enum)
|
78
|
+
assert !message2.has_field?(:signed)
|
79
|
+
end
|
80
|
+
end
|