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