ruby_protobuf 0.3.0 → 0.3.2
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 +3 -1
- data/bin/mk_parser +2 -0
- data/bin/rprotoc +1 -1
- data/lib/protobuf/compiler/compiler.rb +12 -12
- data/lib/protobuf/compiler/nodes.rb +140 -35
- data/lib/protobuf/compiler/proto.y +7 -4
- data/lib/protobuf/compiler/proto_parser.rb +170 -167
- data/lib/protobuf/compiler/template/rpc_bin.erb +1 -1
- data/lib/protobuf/compiler/template/rpc_client.erb +1 -1
- data/lib/protobuf/compiler/visitors.rb +168 -16
- data/lib/protobuf/message/enum.rb +3 -0
- data/lib/protobuf/message/field.rb +52 -37
- data/lib/protobuf/message/message.rb +37 -14
- data/lib/protobuf/message/protoable.rb +37 -0
- data/lib/ruby_protobuf.rb +1 -1
- data/test/addressbook.rb +36 -0
- data/test/check_unbuild.rb +1 -1
- data/test/collision.rb +18 -0
- data/test/data/types.bin +0 -0
- data/test/data/unk.png +0 -0
- data/test/ext_collision.rb +25 -0
- data/test/ext_range.rb +23 -0
- data/test/merge.rb +40 -0
- data/test/nested.rb +25 -0
- data/test/proto/addressbook.pb.rb +69 -0
- data/test/{addressbook.proto → proto/addressbook.proto} +1 -0
- data/test/proto/addressbook.rb +69 -0
- data/test/{addressbook_base.proto → proto/addressbook_base.proto} +0 -0
- data/test/{addressbook_ext.proto → proto/addressbook_ext.proto} +0 -0
- data/test/proto/bool_default.pb.rb +16 -0
- data/test/proto/bool_default.proto +3 -0
- data/test/proto/collision.proto +5 -0
- data/test/proto/ext_collision.proto +8 -0
- data/test/proto/ext_range.proto +7 -0
- data/test/proto/float_default.proto +2 -0
- data/test/proto/merge.proto +15 -0
- data/test/proto/nested.proto +7 -0
- data/test/{rpc.proto → proto/rpc.proto} +0 -0
- data/test/{types.proto → proto/types.proto} +0 -0
- data/test/test_compiler.rb +191 -12
- data/test/test_message.rb +86 -0
- data/test/test_standard_message.rb +8 -5
- data/test/test_types.rb +9 -8
- metadata +26 -13
- data/Manifest.txt +0 -62
- data/examples/addressbook.proto +0 -24
- data/examples/addressbook.rb +0 -30
- data/examples/reading_a_message.rb +0 -32
- data/examples/writing_a_message.rb +0 -46
@@ -1,14 +1,54 @@
|
|
1
1
|
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'protobuf/descriptor/descriptor_proto'
|
2
4
|
|
3
5
|
module Protobuf
|
4
6
|
module Visitor
|
5
|
-
class
|
6
|
-
|
7
|
+
class Base
|
8
|
+
attr_reader :silent
|
7
9
|
|
8
|
-
def
|
10
|
+
def create_file_with_backup(filename, contents, executable=false)
|
11
|
+
if File.exist? filename
|
12
|
+
if File.read(filename) == contents
|
13
|
+
# do nothing
|
14
|
+
return
|
15
|
+
else
|
16
|
+
backup_filename = "#{filename}.#{Time.now.to_i}"
|
17
|
+
log_writing "#{backup_filename}", "backingup..."
|
18
|
+
FileUtils.copy filename, backup_filename
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
File.open(filename, 'w') do |file|
|
23
|
+
log_writing filename
|
24
|
+
FileUtils.mkpath File.dirname(filename)
|
25
|
+
file.write contents
|
26
|
+
end
|
27
|
+
FileUtils.chmod 0755, filename if executable
|
28
|
+
end
|
29
|
+
|
30
|
+
def log_writing(filename, message="writing...")
|
31
|
+
puts "#{filename} #{message}" unless silent
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class CreateMessageVisitor < Base
|
36
|
+
attr_accessor :indent, :context, :attach_proto, :proto_file
|
37
|
+
|
38
|
+
def initialize(proto_file=nil, proto_dir='.', out_dir='.')
|
9
39
|
@proto_dir, @out_dir = proto_dir, out_dir
|
10
40
|
@indent = 0
|
11
41
|
@context = []
|
42
|
+
@attach_proto = true
|
43
|
+
@proto_file = proto_file
|
44
|
+
end
|
45
|
+
|
46
|
+
def attach_proto?
|
47
|
+
@attach_proto
|
48
|
+
end
|
49
|
+
|
50
|
+
def commented_proto_contents
|
51
|
+
File.read(proto_file).gsub(/^/, '# ') if proto_file
|
12
52
|
end
|
13
53
|
|
14
54
|
def write(str)
|
@@ -47,20 +87,31 @@ module Protobuf
|
|
47
87
|
end
|
48
88
|
|
49
89
|
def visit(node)
|
50
|
-
node.
|
90
|
+
node.accept_message_visitor self
|
51
91
|
self
|
52
92
|
end
|
53
93
|
|
54
94
|
def required_message_from_proto(proto_file)
|
55
|
-
rb_path = proto_file.sub(/\.proto$/, '.rb')
|
95
|
+
rb_path = proto_file.sub(/\.proto$/, '.pb.rb')
|
56
96
|
unless File.exist?("#{@out_dir}/#{rb_path}")
|
57
97
|
Compiler.compile proto_file, @proto_dir, @out_dir
|
58
98
|
end
|
59
|
-
rb_path.sub
|
99
|
+
rb_path.sub(/\.rb$/, '')
|
100
|
+
end
|
101
|
+
|
102
|
+
def create_files(filename, out_dir, file_create)
|
103
|
+
eval to_s # check the message
|
104
|
+
if file_create
|
105
|
+
log_writing filename
|
106
|
+
FileUtils.mkpath File.dirname(filename)
|
107
|
+
File.open(filename, 'w') {|file| file.write to_s}
|
108
|
+
else
|
109
|
+
to_s
|
110
|
+
end
|
60
111
|
end
|
61
112
|
end
|
62
113
|
|
63
|
-
class CreateRpcVisitor
|
114
|
+
class CreateRpcVisitor < Base
|
64
115
|
attr_accessor :package, :services, :current_service, :file_contents
|
65
116
|
|
66
117
|
def initialize
|
@@ -70,7 +121,7 @@ module Protobuf
|
|
70
121
|
end
|
71
122
|
|
72
123
|
def visit(node)
|
73
|
-
node.
|
124
|
+
node.accept_rpc_visitor self
|
74
125
|
self
|
75
126
|
end
|
76
127
|
|
@@ -78,8 +129,7 @@ module Protobuf
|
|
78
129
|
(@services[@current_service] ||= []) << [name, request.first, response.first]
|
79
130
|
end
|
80
131
|
|
81
|
-
|
82
|
-
def create_files(message_file, out_dir, create_file=false)
|
132
|
+
def create_files(message_file, out_dir, create_file=true)
|
83
133
|
@create_file = create_file
|
84
134
|
default_port = 9999
|
85
135
|
@services.each do |service_name, rpcs|
|
@@ -91,7 +141,8 @@ module Protobuf
|
|
91
141
|
create_service message_file, out_dir, underscored_name, message_module,
|
92
142
|
service_name, default_port, rpcs, required_file
|
93
143
|
rpcs.each do |name, request, response|
|
94
|
-
create_client out_dir, underscored_name, default_port, name, request, response,
|
144
|
+
create_client out_dir, underscored_name, default_port, name, request, response,
|
145
|
+
message_module, required_file
|
95
146
|
end
|
96
147
|
end
|
97
148
|
@file_contents
|
@@ -100,21 +151,23 @@ module Protobuf
|
|
100
151
|
def create_bin(out_dir, underscored_name, module_name, service_name, default_port)
|
101
152
|
bin_filename = "#{out_dir}/start_#{underscored_name}"
|
102
153
|
bin_contents = template_erb('rpc_bin').result binding
|
103
|
-
|
154
|
+
create_file_with_backup bin_filename, bin_contents, true if @create_file
|
104
155
|
@file_contents[bin_filename] = bin_contents
|
105
156
|
end
|
106
157
|
|
107
|
-
def create_service(message_file, out_dir, underscored_name, module_name, service_name,
|
158
|
+
def create_service(message_file, out_dir, underscored_name, module_name, service_name,
|
159
|
+
default_port, rpcs, required_file)
|
108
160
|
service_filename = "#{out_dir}/#{underscored_name}.rb"
|
109
161
|
service_contents = template_erb('rpc_service').result binding
|
110
|
-
|
162
|
+
create_file_with_backup service_filename, service_contents if @create_file
|
111
163
|
@file_contents[service_filename] = service_contents
|
112
164
|
end
|
113
165
|
|
114
|
-
def create_client(out_dir, underscored_name, default_port, name, request, response,
|
166
|
+
def create_client(out_dir, underscored_name, default_port, name, request, response,
|
167
|
+
message_module, required_file)
|
115
168
|
client_filename = "#{out_dir}/client_#{underscore name}.rb"
|
116
169
|
client_contents = template_erb('rpc_client').result binding
|
117
|
-
|
170
|
+
create_file_with_backup client_filename, client_contents, true if @create_file
|
118
171
|
@file_contents[client_filename] = client_contents
|
119
172
|
end
|
120
173
|
|
@@ -128,5 +181,104 @@ module Protobuf
|
|
128
181
|
ERB.new File.read("#{File.dirname(__FILE__)}/template/#{template}.erb"), nil, '-'
|
129
182
|
end
|
130
183
|
end
|
184
|
+
|
185
|
+
class CreateDescriptorVisitor < Base
|
186
|
+
attr_reader :file_descriptor
|
187
|
+
attr_accessor :filename
|
188
|
+
|
189
|
+
def initialize(filename=nil)
|
190
|
+
@context = []
|
191
|
+
@filename = filename
|
192
|
+
end
|
193
|
+
|
194
|
+
def visit(node)
|
195
|
+
node.accept_descriptor_visitor self
|
196
|
+
self
|
197
|
+
end
|
198
|
+
|
199
|
+
def in_context(descriptor, &block)
|
200
|
+
@context.push descriptor
|
201
|
+
block.call
|
202
|
+
@context.pop
|
203
|
+
end
|
204
|
+
|
205
|
+
def current_descriptor
|
206
|
+
@context.last
|
207
|
+
end
|
208
|
+
|
209
|
+
def file_descriptor=(descriptor)
|
210
|
+
@file_descriptor = descriptor
|
211
|
+
@file_descriptor.name = @filename
|
212
|
+
end
|
213
|
+
|
214
|
+
def add_option(name, value)
|
215
|
+
options =
|
216
|
+
case current_descriptor
|
217
|
+
when Google::Protobuf::FileDescriptorProto
|
218
|
+
Google::Protobuf::FileOptions.new
|
219
|
+
when Google::Protobuf::DescriptorProto
|
220
|
+
Google::Protobuf::MessageOptions.new
|
221
|
+
when Google::Protobuf::FieldDescriptorProto
|
222
|
+
Google::Protobuf::FieldOptions.new
|
223
|
+
when Google::Protobuf::EnumDescriptorProto
|
224
|
+
Google::Protobuf::EnumOptions.new
|
225
|
+
when Google::Protobuf::EnumValueDescriptorProto
|
226
|
+
Google::Protobuf::EnumValueOptions.new
|
227
|
+
when Google::Protobuf::ServiceDescriptorProto
|
228
|
+
Google::Protobuf::ServiceOptions.new
|
229
|
+
when Google::Protobuf::MethodDescriptorProto
|
230
|
+
Google::Protobuf::MethodOptions.new
|
231
|
+
else
|
232
|
+
raise ArgumentError.new('Invalid context')
|
233
|
+
end
|
234
|
+
#TODO how should options be handled?
|
235
|
+
#current_descriptor.options << option
|
236
|
+
end
|
237
|
+
|
238
|
+
def descriptor=(descriptor)
|
239
|
+
case current_descriptor
|
240
|
+
when Google::Protobuf::FileDescriptorProto
|
241
|
+
current_descriptor.message_type << descriptor
|
242
|
+
when Google::Protobuf::DescriptorProto
|
243
|
+
current_descriptor.nested_type << descriptor
|
244
|
+
else
|
245
|
+
raise ArgumentError.new('Invalid context')
|
246
|
+
end
|
247
|
+
end
|
248
|
+
alias message_descriptor= descriptor=
|
249
|
+
|
250
|
+
def enum_descriptor=(descriptor)
|
251
|
+
current_descriptor.enum_type << descriptor
|
252
|
+
end
|
253
|
+
|
254
|
+
def enum_value_descriptor=(descriptor)
|
255
|
+
current_descriptor.value << descriptor
|
256
|
+
end
|
257
|
+
|
258
|
+
def service_descriptor=(descriptor)
|
259
|
+
current_descriptor.service << descriptor
|
260
|
+
end
|
261
|
+
|
262
|
+
def method_descriptor=(descriptor)
|
263
|
+
current_descriptor.method << descriptor
|
264
|
+
end
|
265
|
+
|
266
|
+
def field_descriptor=(descriptor)
|
267
|
+
case current_descriptor
|
268
|
+
when Google::Protobuf::FileDescriptorProto
|
269
|
+
current_descriptor.extension << descriptor
|
270
|
+
when Google::Protobuf::DescriptorProto
|
271
|
+
current_descriptor.field << descriptor
|
272
|
+
#TODO: how should i distiguish between field and extension
|
273
|
+
#current_descriptor.extension << descriptor
|
274
|
+
else
|
275
|
+
raise ArgumentError.new('Invalid context')
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def extension_range_descriptor=(descriptor)
|
280
|
+
current_descriptor.extension_range << descriptor
|
281
|
+
end
|
282
|
+
end
|
131
283
|
end
|
132
284
|
end
|
@@ -128,20 +128,20 @@ module Protobuf
|
|
128
128
|
raise NotImplementedError
|
129
129
|
end
|
130
130
|
|
131
|
-
def merge(message_instance,
|
131
|
+
def merge(message_instance, value)
|
132
132
|
if repeated?
|
133
|
-
merge_array
|
133
|
+
merge_array message_instance, value
|
134
134
|
else
|
135
|
-
merge_value
|
135
|
+
merge_value message_instance, value
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
def merge_array(message_instance,
|
140
|
-
|
139
|
+
def merge_array(message_instance, value)
|
140
|
+
message_instance[tag].concat value
|
141
141
|
end
|
142
142
|
|
143
|
-
def merge_value(message_instance,
|
144
|
-
|
143
|
+
def merge_value(message_instance, value)
|
144
|
+
message_instance[tag] = value
|
145
145
|
end
|
146
146
|
|
147
147
|
def repeated?; rule == :repeated end
|
@@ -247,13 +247,13 @@ module Protobuf
|
|
247
247
|
true
|
248
248
|
end
|
249
249
|
|
250
|
-
def set_bytes(
|
251
|
-
|
250
|
+
def set_bytes(message_instance, bytes)
|
251
|
+
message_instance.send("#{name}=", bytes.pack('U*'))
|
252
252
|
end
|
253
253
|
|
254
|
-
def set_array(
|
254
|
+
def set_array(message_instance, bytes)
|
255
255
|
message = bytes.pack('U*')
|
256
|
-
arr =
|
256
|
+
arr = message_instance.send name
|
257
257
|
arr << message
|
258
258
|
end
|
259
259
|
|
@@ -267,20 +267,31 @@ module Protobuf
|
|
267
267
|
|
268
268
|
class BytesField < BaseField
|
269
269
|
def wire_type
|
270
|
-
Protobuf::WireType::
|
270
|
+
Protobuf::WireType::LENGTH_DELIMITED
|
271
271
|
end
|
272
272
|
|
273
273
|
def typed_default_value(default=nil)
|
274
|
-
default or
|
274
|
+
default or ''
|
275
275
|
end
|
276
276
|
|
277
|
-
def
|
278
|
-
|
277
|
+
def acceptable?(val)
|
278
|
+
raise TypeError unless val.instance_of? String
|
279
|
+
true
|
280
|
+
end
|
281
|
+
|
282
|
+
def set_bytes(message_instance, bytes)
|
283
|
+
message_instance.send("#{name}=", bytes.pack('C*'))
|
284
|
+
end
|
285
|
+
|
286
|
+
def set_array(message_instance, bytes)
|
287
|
+
message = bytes.pack('C*')
|
288
|
+
arr = message_instance.send name
|
289
|
+
arr << message
|
279
290
|
end
|
280
291
|
|
281
292
|
def get_bytes(value)
|
282
|
-
string_size = VarintField.get_bytes value.size
|
283
|
-
string_size + value
|
293
|
+
string_size = VarintField.get_bytes value.unpack('C*').size
|
294
|
+
string_size + value
|
284
295
|
end
|
285
296
|
end
|
286
297
|
|
@@ -293,13 +304,13 @@ module Protobuf
|
|
293
304
|
default or 0
|
294
305
|
end
|
295
306
|
|
296
|
-
def set_bytes(
|
307
|
+
def set_bytes(message_instance, bytes)
|
297
308
|
# TODO should refactor using pack('w*')
|
298
309
|
value = 0
|
299
310
|
bytes.each_with_index do |byte, index|
|
300
311
|
value |= byte << (7 * index)
|
301
312
|
end
|
302
|
-
|
313
|
+
message_instance.send("#{name}=", value)
|
303
314
|
end
|
304
315
|
|
305
316
|
def self.get_bytes(value)
|
@@ -357,7 +368,7 @@ module Protobuf
|
|
357
368
|
def self.max; 1.0/0.0 end
|
358
369
|
def self.min; -1.0/0.0 end
|
359
370
|
|
360
|
-
def set_bytes(
|
371
|
+
def set_bytes(message_instance, bytes)
|
361
372
|
# TODO use only bit-operations
|
362
373
|
byte = bytes.first
|
363
374
|
value =
|
@@ -366,7 +377,7 @@ module Protobuf
|
|
366
377
|
else
|
367
378
|
-(byte + 1) / 2
|
368
379
|
end
|
369
|
-
|
380
|
+
message_instance.send("#{name}=", value)
|
370
381
|
end
|
371
382
|
|
372
383
|
def get_bytes(value)
|
@@ -379,7 +390,7 @@ module Protobuf
|
|
379
390
|
def self.max; 1.0/0.0 end
|
380
391
|
def self.min; -1.0/0.0 end
|
381
392
|
|
382
|
-
def set_bytes(
|
393
|
+
def set_bytes(message_instance, bytes)
|
383
394
|
# TODO use only bit-operations
|
384
395
|
byte = bytes.first
|
385
396
|
value =
|
@@ -388,7 +399,7 @@ module Protobuf
|
|
388
399
|
else
|
389
400
|
-(byte + 1) / 2
|
390
401
|
end
|
391
|
-
|
402
|
+
message_instance.send("#{name}=", value)
|
392
403
|
end
|
393
404
|
|
394
405
|
def get_bytes(value)
|
@@ -412,8 +423,8 @@ module Protobuf
|
|
412
423
|
-(2**(64/2) - 1)
|
413
424
|
end
|
414
425
|
|
415
|
-
def set_bytes(
|
416
|
-
|
426
|
+
def set_bytes(message_instance, bytes)
|
427
|
+
message_instance.send("#{name}=", bytes.unpack('E').first)
|
417
428
|
end
|
418
429
|
|
419
430
|
def get_bytes(value)
|
@@ -442,8 +453,8 @@ module Protobuf
|
|
442
453
|
-(2**(32/2) - 1)
|
443
454
|
end
|
444
455
|
|
445
|
-
def set_bytes(
|
446
|
-
|
456
|
+
def set_bytes(message_instance, bytes)
|
457
|
+
message_instance.send("#{name}=", bytes.unpack('e').first)
|
447
458
|
end
|
448
459
|
|
449
460
|
def get_bytes(value)
|
@@ -470,8 +481,8 @@ module Protobuf
|
|
470
481
|
0
|
471
482
|
end
|
472
483
|
|
473
|
-
def set_bytes(
|
474
|
-
|
484
|
+
def set_bytes(message_instance, bytes)
|
485
|
+
message_instance.send("#{name}=", bytes.unpack('L').first)
|
475
486
|
end
|
476
487
|
|
477
488
|
def get_bytes(value)
|
@@ -492,8 +503,8 @@ module Protobuf
|
|
492
503
|
0
|
493
504
|
end
|
494
505
|
|
495
|
-
def set_bytes(
|
496
|
-
|
506
|
+
def set_bytes(message_instance, bytes)
|
507
|
+
message_instance.send("#{name}=", bytes.unpack('l').first)
|
497
508
|
end
|
498
509
|
|
499
510
|
def get_bytes(value)
|
@@ -539,8 +550,8 @@ module Protobuf
|
|
539
550
|
true
|
540
551
|
end
|
541
552
|
|
542
|
-
def set_bytes(
|
543
|
-
|
553
|
+
def set_bytes(message_instance, bytes)
|
554
|
+
message_instance.send("#{name}=", bytes.first == 1)
|
544
555
|
end
|
545
556
|
|
546
557
|
def get_bytes(value)
|
@@ -566,18 +577,18 @@ module Protobuf
|
|
566
577
|
true
|
567
578
|
end
|
568
579
|
|
569
|
-
def set_bytes(
|
580
|
+
def set_bytes(message_instance, bytes)
|
570
581
|
message = type.new
|
571
582
|
#message.parse_from bytes
|
572
583
|
message.parse_from_string bytes.pack('U*') # TODO
|
573
|
-
|
584
|
+
message_instance.send("#{name}=", message)
|
574
585
|
end
|
575
586
|
|
576
|
-
def set_array(
|
587
|
+
def set_array(message_instance, bytes)
|
577
588
|
message = type.new
|
578
589
|
#message.parse_from bytes
|
579
590
|
message.parse_from_string bytes.pack('U*')
|
580
|
-
arr =
|
591
|
+
arr = message_instance.send name
|
581
592
|
arr << message
|
582
593
|
end
|
583
594
|
|
@@ -590,6 +601,10 @@ module Protobuf
|
|
590
601
|
#bytes + string_size
|
591
602
|
string_size + bytes.pack('C*')
|
592
603
|
end
|
604
|
+
|
605
|
+
def merge_value(message_instance, value)
|
606
|
+
message_instance[tag].merge_from value
|
607
|
+
end
|
593
608
|
end
|
594
609
|
|
595
610
|
class EnumField < VarintField
|