ruby_protobuf 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -1
- data/Manifest.txt +23 -2
- data/bin/rprotoc +5 -5
- data/examples/addressbook.proto +24 -0
- data/examples/addressbook.rb +30 -0
- data/examples/reading_a_message.rb +32 -0
- data/examples/writing_a_message.rb +46 -0
- data/lib/protobuf/compiler/compiler.rb +38 -74
- data/lib/protobuf/compiler/compiler_old.rb +123 -0
- data/lib/protobuf/compiler/nodes.rb +208 -0
- data/lib/protobuf/compiler/proto.y +198 -0
- data/lib/protobuf/compiler/proto2.ebnf +79 -0
- data/lib/protobuf/compiler/proto_parser.rb +1259 -0
- data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
- data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
- data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
- data/lib/protobuf/compiler/visitors.rb +132 -0
- data/lib/protobuf/message/decoder.rb +8 -3
- data/lib/protobuf/message/enum.rb +4 -0
- data/lib/protobuf/message/field.rb +31 -5
- data/lib/protobuf/message/message.rb +130 -14
- data/lib/protobuf/rpc/client.rb +19 -0
- data/lib/protobuf/rpc/handler.rb +17 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/ruby_protobuf.rb +1 -20
- data/test/addressbook.proto +6 -0
- data/test/addressbook.rb +17 -14
- data/test/addressbook_base.proto +26 -0
- data/test/addressbook_base.rb +62 -0
- data/test/addressbook_ext.proto +6 -0
- data/test/addressbook_ext.rb +12 -0
- data/test/rpc.proto +6 -0
- data/test/test_addressbook.rb +3 -2
- data/test/test_compiler.rb +98 -3
- data/test/test_extension.rb +40 -0
- data/test/test_standard_message.rb +83 -0
- data/test/test_types.rb +3 -3
- metadata +31 -8
- data/lib/protobuf/compiler/parser.y +0 -138
- data/test/data/data2.bin +0 -3
data/History.txt
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
=== 0.
|
1
|
+
=== 0.3.0 / 2008-08-19
|
2
2
|
|
3
|
+
* 0.3.0 RPC is available (rev.124)
|
4
|
+
* RPC is available
|
5
|
+
* New compiler using racc (ruby version of yacc)
|
6
|
+
* Rename `sample' directory to `example'
|
7
|
+
* 0.2.1 extensions and import are available (rev.82)
|
3
8
|
* 0.2.0 introduce descriptor (rev.75)
|
4
9
|
* Message structures can be restored from encoded data by means a descriptor object
|
5
10
|
* 0.1.0 fixed a small bug
|
data/Manifest.txt
CHANGED
@@ -3,9 +3,21 @@ Manifest.txt
|
|
3
3
|
README.txt
|
4
4
|
Rakefile
|
5
5
|
bin/rprotoc
|
6
|
+
examples/addressbook.proto
|
7
|
+
examples/addressbook.rb
|
8
|
+
examples/reading_a_message.rb
|
9
|
+
examples/writing_a_message.rb
|
6
10
|
lib/protobuf/common/wire_type.rb
|
7
11
|
lib/protobuf/compiler/compiler.rb
|
8
|
-
lib/protobuf/compiler/
|
12
|
+
lib/protobuf/compiler/compiler_old.rb
|
13
|
+
lib/protobuf/compiler/nodes.rb
|
14
|
+
lib/protobuf/compiler/proto.y
|
15
|
+
lib/protobuf/compiler/proto2.ebnf
|
16
|
+
lib/protobuf/compiler/proto_parser.rb
|
17
|
+
lib/protobuf/compiler/template/rpc_bin.erb
|
18
|
+
lib/protobuf/compiler/template/rpc_client.erb
|
19
|
+
lib/protobuf/compiler/template/rpc_service.erb
|
20
|
+
lib/protobuf/compiler/visitors.rb
|
9
21
|
lib/protobuf/descriptor/descriptor.proto
|
10
22
|
lib/protobuf/descriptor/descriptor.rb
|
11
23
|
lib/protobuf/descriptor/descriptor_builder.rb
|
@@ -20,22 +32,31 @@ lib/protobuf/message/extend.rb
|
|
20
32
|
lib/protobuf/message/field.rb
|
21
33
|
lib/protobuf/message/message.rb
|
22
34
|
lib/protobuf/message/service.rb
|
35
|
+
lib/protobuf/rpc/client.rb
|
36
|
+
lib/protobuf/rpc/handler.rb
|
37
|
+
lib/protobuf/rpc/server.rb
|
23
38
|
lib/ruby_protobuf.rb
|
24
39
|
test/addressbook.proto
|
25
40
|
test/addressbook.rb
|
41
|
+
test/addressbook_base.proto
|
42
|
+
test/addressbook_base.rb
|
43
|
+
test/addressbook_ext.proto
|
44
|
+
test/addressbook_ext.rb
|
26
45
|
test/check_unbuild.rb
|
27
46
|
test/data/data.bin
|
28
|
-
test/data/data2.bin
|
29
47
|
test/data/data_source.py
|
30
48
|
test/data/types.bin
|
31
49
|
test/data/types_source.py
|
50
|
+
test/rpc.proto
|
32
51
|
test/test_addressbook.rb
|
33
52
|
test/test_compiler.rb
|
34
53
|
test/test_descriptor.rb
|
54
|
+
test/test_extension.rb
|
35
55
|
test/test_message.rb
|
36
56
|
test/test_parse.rb
|
37
57
|
test/test_ruby_protobuf.rb
|
38
58
|
test/test_serialize.rb
|
59
|
+
test/test_standard_message.rb
|
39
60
|
test/test_types.rb
|
40
61
|
test/types.proto
|
41
62
|
test/types.rb
|
data/bin/rprotoc
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
#!/usr/
|
1
|
+
#!/usr/bin/ruby
|
2
2
|
$: << "#{File.dirname(__FILE__)}/../lib"
|
3
3
|
require 'optparse'
|
4
4
|
require 'ruby_protobuf'
|
5
|
+
#require 'protobuf/compiler/compiler_old'
|
6
|
+
require 'protobuf/compiler/compiler'
|
5
7
|
|
6
8
|
|
7
9
|
COMMAND_LINE = "#{$0} #{ARGV.join(' ')} PROTO_FILE"
|
8
10
|
OPT = {}
|
9
11
|
opts = OptionParser.new
|
10
|
-
|
12
|
+
opts.on('-p', '--proto_path <PATH>', 'Specify the directory in which to search for imports. The current directory is default.'){|v| OPT[:proto_path] = v}
|
11
13
|
opts.on('-o', '--out <OUT_DIR>', 'Specify the directory in which Ruby source file is generated. The current directory is default.'){|v| OPT[:out] = v}
|
12
14
|
opts.on_tail('-v', '--version', 'Show version.'){puts(opts.ver); exit}
|
13
15
|
opts.on_tail('-h', '--help', 'Show this message.'){puts(opts.help); exit}
|
@@ -16,6 +18,4 @@ opts.on_tail('-h', '--help', 'Show this message.'){puts(opts.help); exit}
|
|
16
18
|
opts.order! ARGV
|
17
19
|
PROTO_FILE = ARGV.shift
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
Protobuf::Compiler.compile(PROTO_FILE, (OPT[:proto_path] or '.'), (OPT[:out] or '.'))
|
@@ -0,0 +1,24 @@
|
|
1
|
+
package tutorial;
|
2
|
+
|
3
|
+
message Person {
|
4
|
+
required string name = 1;
|
5
|
+
required int32 id = 2;
|
6
|
+
optional string email = 3;
|
7
|
+
|
8
|
+
enum PhoneType {
|
9
|
+
MOBILE = 0;
|
10
|
+
HOME = 1;
|
11
|
+
WORK = 2;
|
12
|
+
}
|
13
|
+
|
14
|
+
message PhoneNumber {
|
15
|
+
required string number = 1;
|
16
|
+
optional PhoneType type = 2 [default = HOME];
|
17
|
+
}
|
18
|
+
|
19
|
+
repeated PhoneNumber phone = 4;
|
20
|
+
}
|
21
|
+
|
22
|
+
message AddressBook {
|
23
|
+
repeated Person person = 1;
|
24
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'protobuf/message/message'
|
2
|
+
require 'protobuf/message/enum'
|
3
|
+
require 'protobuf/message/service'
|
4
|
+
require 'protobuf/message/extend'
|
5
|
+
|
6
|
+
module Tutorial
|
7
|
+
|
8
|
+
class Person < ::Protobuf::Message
|
9
|
+
required :string, :name, 1
|
10
|
+
required :int32, :id, 2
|
11
|
+
optional :string, :email, 3
|
12
|
+
|
13
|
+
class PhoneType < ::Protobuf::Enum
|
14
|
+
MOBILE = 0
|
15
|
+
HOME = 1
|
16
|
+
WORK = 2
|
17
|
+
end
|
18
|
+
|
19
|
+
class PhoneNumber < ::Protobuf::Message
|
20
|
+
required :string, :number, 1
|
21
|
+
optional :PhoneType, :type, 2, {:default => :HOME}
|
22
|
+
end
|
23
|
+
|
24
|
+
repeated :PhoneNumber, :phone, 4
|
25
|
+
end
|
26
|
+
|
27
|
+
class AddressBook < ::Protobuf::Message
|
28
|
+
repeated :Person, :person, 1
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'addressbook'
|
4
|
+
|
5
|
+
def list_people(address_book)
|
6
|
+
address_book.person.each do |person|
|
7
|
+
puts "Person ID: #{person.id}"
|
8
|
+
puts " Name: #{person.name}"
|
9
|
+
puts " E-mail: #{person.email}" unless person.email.empty?
|
10
|
+
person.phone.each do |phone_number|
|
11
|
+
print(case phone_number.type
|
12
|
+
when Tutorial::Person::PhoneType::MOBILE
|
13
|
+
' Mobile phone #: '
|
14
|
+
when Tutorial::Person::PhoneType::HOME
|
15
|
+
' Home phone #: '
|
16
|
+
when Tutorial::Person::PhoneType::WORK
|
17
|
+
' Work phone #: '
|
18
|
+
end)
|
19
|
+
puts phone_number.number
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
unless ARGV.size == 1
|
25
|
+
puts "Usage: #{$0} ADDRESS_BOOK_FILE"
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
address_book = Tutorial::AddressBook.new
|
30
|
+
address_book.parse_from_file ARGV[0]
|
31
|
+
|
32
|
+
list_people address_book
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'addressbook'
|
4
|
+
|
5
|
+
def prompt_for_address(person)
|
6
|
+
print 'Enter person ID number: '
|
7
|
+
person.id = STDIN.gets.strip.to_i
|
8
|
+
print 'Enter name: '
|
9
|
+
person.name = STDIN.gets.strip
|
10
|
+
print 'Enter email address (blank for none): '
|
11
|
+
email = STDIN.gets.strip
|
12
|
+
person.email = email unless email.empty?
|
13
|
+
|
14
|
+
loop do
|
15
|
+
print 'Enter a phone number (or leave blank to finish): '
|
16
|
+
break if (number = STDIN.gets.strip).empty?
|
17
|
+
|
18
|
+
person.phone << Tutorial::Person::PhoneNumber.new
|
19
|
+
person.phone.last.number = number
|
20
|
+
|
21
|
+
print 'Is this a mobile, home, or work phone? '
|
22
|
+
person.phone.last.type =
|
23
|
+
case type = STDIN.gets.strip
|
24
|
+
when 'mobile'
|
25
|
+
Tutorial::Person::PhoneType::MOBILE
|
26
|
+
when 'home'
|
27
|
+
Tutorial::Person::PhoneType::HOME
|
28
|
+
when 'work'
|
29
|
+
Tutorial::Person::PhoneType::WORK
|
30
|
+
else
|
31
|
+
puts 'Unknown phone type; leaving as default value.'
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
unless ARGV.size == 1
|
38
|
+
puts "Usage: #{$0} ADDRESS_BOOK_FILE"
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
address_book = Tutorial::AddressBook.new
|
43
|
+
address_book.parse_from_file ARGV[0] if File.exist? ARGV[0]
|
44
|
+
address_book.person << Tutorial::Person.new
|
45
|
+
prompt_for_address address_book.person.last
|
46
|
+
address_book.serialize_to_file ARGV[0]
|
@@ -1,90 +1,54 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'fileutils'
|
2
|
+
require 'protobuf/compiler/proto_parser'
|
3
|
+
require 'protobuf/compiler/nodes'
|
4
|
+
require 'protobuf/compiler/visitors'
|
3
5
|
|
4
6
|
module Protobuf
|
5
7
|
class Compiler
|
6
|
-
|
8
|
+
def self.compile(proto_file, proto_dir='.', out_dir='.', file_create=true)
|
9
|
+
self.new.compile proto_file, proto_dir, out_dir, file_create
|
10
|
+
end
|
7
11
|
|
8
|
-
def
|
9
|
-
|
12
|
+
def compile(proto_file, proto_dir='.', out_dir='.', file_create=true)
|
13
|
+
create_message proto_file, proto_dir, out_dir, file_create
|
14
|
+
create_rpc proto_file, proto_dir, out_dir, file_create
|
10
15
|
end
|
11
16
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
require 'protobuf/message/message'
|
16
|
-
require 'protobuf/message/enum'
|
17
|
-
require 'protobuf/message/service'
|
18
|
-
require 'protobuf/message/extend'
|
17
|
+
def create_message(proto_file, proto_dir='.', out_dir='.', file_create=true)
|
18
|
+
rb_file = "#{out_dir}/#{proto_file.sub(/\.proto$/, '.rb')}"
|
19
|
+
proto_path = validate_existence proto_file, proto_dir
|
19
20
|
|
20
|
-
|
21
|
+
message_visitor = Protobuf::Visitor::CreateMessageVisitor.new proto_dir, out_dir
|
22
|
+
File.open proto_path, 'r' do |file|
|
23
|
+
message_visitor.visit Protobuf::ProtoParser.new.parse(file)
|
24
|
+
end
|
25
|
+
if file_create
|
26
|
+
puts "#{rb_file} writing..."
|
27
|
+
FileUtils.mkpath File.dirname(rb_file)
|
28
|
+
File.open(rb_file, 'w') {|f| f.write message_visitor.to_s}
|
29
|
+
else
|
30
|
+
message_visitor.to_s
|
31
|
+
end
|
21
32
|
end
|
22
33
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
34
|
+
def create_rpc(proto_file, proto_dir='.', out_dir='.', file_create=true)
|
35
|
+
rb_file = "#{out_dir}/#{proto_file.sub(/\.proto$/, '.rb')}"
|
36
|
+
proto_path = validate_existence proto_file, proto_dir
|
26
37
|
|
27
|
-
|
28
|
-
|
29
|
-
|
38
|
+
rpc_visitor = Protobuf::Visitor::CreateRpcVisitor.new# proto_dir, out_dir
|
39
|
+
File.open proto_path, 'r' do |file|
|
40
|
+
rpc_visitor.visit Protobuf::ProtoParser.new.parse(file)
|
41
|
+
end
|
42
|
+
rpc_visitor.create_files rb_file, out_dir, file_create
|
30
43
|
end
|
31
|
-
alias putswi puts_with_indent
|
32
44
|
|
33
|
-
def
|
34
|
-
File.
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
case line
|
39
|
-
when /^package\s+(\w+(\.\w+)?)\s*;$/
|
40
|
-
$1.split('.').each do |path|
|
41
|
-
putswi "module #{path.capitalize}"
|
42
|
-
@indent_level += 1
|
43
|
-
end
|
44
|
-
when /^message\s+(\w+)\s*\{$/
|
45
|
-
putswi "class #{$1} < ::Protobuf::Message"
|
46
|
-
@indent_level += 1
|
47
|
-
when /^(required|optional|repeated)\s+(\w+(\.\w+)?)\s+(\w+)\s*=\s*(\d+)\s*(\[\s*default\s*=\s*(\w+)\s*\])?\s*;$/
|
48
|
-
rule, type, name, tag, default = $1, $2, $4, $5, $7
|
49
|
-
if default
|
50
|
-
default = default =~ /\d+(\.\d+)/ \
|
51
|
-
? ", {:default => #{default}}" \
|
52
|
-
: ", {:default => :#{default}}"
|
53
|
-
end
|
54
|
-
putswi "#{rule} :#{type}, :#{name}, #{tag}#{default}"
|
55
|
-
when /^enum\s+(\w+)\s*\{$/
|
56
|
-
putswi "class #{$1} < ::Protobuf::Enum"
|
57
|
-
@indent_level += 1
|
58
|
-
when /^(\w+)\s*=\s*(\w+)\s*;$/
|
59
|
-
putswi "#{$1} = #{$2}"
|
60
|
-
when /^extensions\s+(\w+)\s+to\s+(\w+)\s*;/
|
61
|
-
low, high = $1, $2
|
62
|
-
low = '::Protobuf::Extend.MIN' if low == 'min'
|
63
|
-
high = '::Protobuf::Extend.MAX' if high == 'max'
|
64
|
-
putswi "extensions #{min}..#{max}"
|
65
|
-
when /^extend\s+(\w+)\s*\{/
|
66
|
-
putswi "class #{$1} < ::Protobuf::Extend"
|
67
|
-
@indent_level += 1
|
68
|
-
when /^service\s+(\w+)\s*\{/
|
69
|
-
putswi "class #{$1} < ::Protobuf::Service"
|
70
|
-
@indent_level += 1
|
71
|
-
when /^rpc\s+(\w+)\s+\(\s*(\w+)\s*\)\s+returns\s+\(\s*(\w+)\s*\)\s*;/
|
72
|
-
putswi "rpc :#{$1} => :#{$2}, :#{$3} => :#{$4}"
|
73
|
-
when /^option\s+(\w+)\s*=\s*(.+)\s*;/
|
74
|
-
putswi "::Protobuf::OPTIONS[:#{$1}] = :#{$2}"
|
75
|
-
when /^\}\s*;?$/
|
76
|
-
@indent_level -= 1
|
77
|
-
putswi "end"
|
78
|
-
when ''
|
79
|
-
putswi ''
|
80
|
-
end
|
81
|
-
end
|
82
|
-
while 0 < @indent_level
|
83
|
-
@indent_level -= 1
|
84
|
-
putswi "end"
|
85
|
-
end
|
45
|
+
def validate_existence(path, base_dir)
|
46
|
+
if File.exist? path
|
47
|
+
elsif File.exist?(path = "#{base_dir or '.'}/#{path}")
|
48
|
+
else
|
49
|
+
raise ArgumentError.new("File does not exist: #{path}")
|
86
50
|
end
|
87
|
-
|
51
|
+
path
|
88
52
|
end
|
89
53
|
end
|
90
54
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# This is a quite temporary implementation.
|
2
|
+
# I'll create a compiler class using Racc.
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Protobuf
|
7
|
+
class Compiler
|
8
|
+
INDENT_UNIT = ' '
|
9
|
+
|
10
|
+
def self.compile(proto_file, proto_dir='.', out_dir='.', file_create=true)
|
11
|
+
self.new.compile proto_file, proto_dir, out_dir, file_create
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@indent_level = 0
|
16
|
+
@ret = <<-eos
|
17
|
+
require 'protobuf/message/message'
|
18
|
+
require 'protobuf/message/enum'
|
19
|
+
require 'protobuf/message/service'
|
20
|
+
require 'protobuf/message/extend'
|
21
|
+
|
22
|
+
eos
|
23
|
+
end
|
24
|
+
|
25
|
+
def indent
|
26
|
+
INDENT_UNIT * @indent_level
|
27
|
+
end
|
28
|
+
|
29
|
+
def puts_with_indent(string)
|
30
|
+
#puts "#{indent}#{string}"
|
31
|
+
@ret += "#{indent}#{string}\n"
|
32
|
+
end
|
33
|
+
alias putswi puts_with_indent
|
34
|
+
|
35
|
+
def compile(proto_file, proto_dir='.', out_dir='.', file_create=true)
|
36
|
+
rb_file = "#{out_dir}/#{proto_file.sub(/\.proto$/, '.rb')}"
|
37
|
+
proto_path = validate_existence proto_file, proto_dir
|
38
|
+
File.open proto_path, 'r' do |file|
|
39
|
+
file.each_line do |line|
|
40
|
+
line.sub!(/^(.*)\/\/.*/, '\1')
|
41
|
+
line.strip!
|
42
|
+
case line
|
43
|
+
when /^package\s+(\w+(\.\w+)?)\s*;$/
|
44
|
+
$1.split('.').each do |path|
|
45
|
+
putswi "module #{path.capitalize}"
|
46
|
+
@indent_level += 1
|
47
|
+
end
|
48
|
+
when /^import\s+"((?:[^"\\]+|\\.)*)"\s*;$/
|
49
|
+
putswi "require '#{required_message_from_proto $1, proto_dir, out_dir}'"
|
50
|
+
when /^message\s+(\w+)\s*\{$/
|
51
|
+
putswi "class #{$1} < ::Protobuf::Message"
|
52
|
+
@extension = false
|
53
|
+
@indent_level += 1
|
54
|
+
when /^(required|optional|repeated)\s+(\w+(\.\w+)?)\s+(\w+)\s*=\s*(\d+)\s*(\[\s*default\s*=\s*(\w+)\s*\])?\s*;$/
|
55
|
+
rule, type, name, tag, default = $1, $2, $4, $5, $7
|
56
|
+
if default
|
57
|
+
default = default =~ /\d+(\.\d+)/ \
|
58
|
+
? ", {:default => #{default}}" \
|
59
|
+
: ", {:default => :#{default}}"
|
60
|
+
end
|
61
|
+
extension = @extension ? ', :extension => true' : ''
|
62
|
+
putswi "#{rule} :#{type}, :#{name}, #{tag}#{default}#{extension}"
|
63
|
+
when /^enum\s+(\w+)\s*\{$/
|
64
|
+
putswi "class #{$1} < ::Protobuf::Enum"
|
65
|
+
@indent_level += 1
|
66
|
+
when /^(\w+)\s*=\s*(\w+)\s*;$/
|
67
|
+
putswi "#{$1} = #{$2}"
|
68
|
+
when /^extensions\s+(\w+)\s+to\s+(\w+)\s*;/
|
69
|
+
low, high = $1, $2
|
70
|
+
low = '::Protobuf::Extend.MIN' if low == 'min'
|
71
|
+
high = '::Protobuf::Extend.MAX' if high == 'max'
|
72
|
+
putswi "extensions #{low}..#{high}"
|
73
|
+
when /^extend\s+(\w+)\s*\{/
|
74
|
+
putswi "class #{$1} < ::Protobuf::Message"
|
75
|
+
@extension = true
|
76
|
+
@indent_level += 1
|
77
|
+
when /^service\s+(\w+)\s*\{/
|
78
|
+
putswi "class #{$1} < ::Protobuf::Service"
|
79
|
+
@indent_level += 1
|
80
|
+
when /^rpc\s+(\w+)\s+\(\s*(\w+)\s*\)\s+returns\s+\(\s*(\w+)\s*\)\s*;/
|
81
|
+
putswi "rpc :#{$1} => :#{$2}, :#{$3} => :#{$4}"
|
82
|
+
when /^option\s+(\w+)\s*=\s*(.+)\s*;/
|
83
|
+
putswi "::Protobuf::OPTIONS[:#{$1}] = :#{$2}"
|
84
|
+
when /^\}\s*;?$/
|
85
|
+
@indent_level -= 1
|
86
|
+
putswi "end"
|
87
|
+
when ''
|
88
|
+
putswi ''
|
89
|
+
end
|
90
|
+
end
|
91
|
+
while 0 < @indent_level
|
92
|
+
@indent_level -= 1
|
93
|
+
putswi "end"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
if file_create
|
97
|
+
puts "#{rb_file} writing..."
|
98
|
+
FileUtils.mkpath File.dirname(rb_file)
|
99
|
+
File.open(rb_file, 'w') {|f| f.write @ret}
|
100
|
+
end
|
101
|
+
@ret
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate_existence(path, base_dir)
|
105
|
+
if File.exist? path
|
106
|
+
elsif File.exist?(path = "#{base_dir or '.'}/#{path}")
|
107
|
+
else
|
108
|
+
raise ArgumentError.new("File does not exist: #{path}")
|
109
|
+
end
|
110
|
+
path
|
111
|
+
end
|
112
|
+
|
113
|
+
def required_message_from_proto(proto_file, proto_dir, out_dir)
|
114
|
+
rb_path = proto_file.sub(/\.proto$/, '.rb')
|
115
|
+
proto_dir ||= '.'
|
116
|
+
out_dir ||= '.'
|
117
|
+
unless File.exist?("#{out_dir}/#{rb_path}")
|
118
|
+
Compiler.compile proto_file, proto_dir, out_dir
|
119
|
+
end
|
120
|
+
rb_path
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Node
|
3
|
+
class Base
|
4
|
+
def accept_rpc_creator(vistor)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class ProtoNode < Base
|
9
|
+
attr_reader :children
|
10
|
+
|
11
|
+
def initialize(children)
|
12
|
+
@children = children
|
13
|
+
end
|
14
|
+
|
15
|
+
def accept_message_creator(visitor)
|
16
|
+
visitor.write <<-eos
|
17
|
+
require 'protobuf/message/message'
|
18
|
+
require 'protobuf/message/enum'
|
19
|
+
require 'protobuf/message/service'
|
20
|
+
require 'protobuf/message/extend'
|
21
|
+
eos
|
22
|
+
@children.map{|child| child.accept_message_creator visitor}
|
23
|
+
visitor.close_ruby
|
24
|
+
end
|
25
|
+
|
26
|
+
def accept_rpc_creator(visitor)
|
27
|
+
@children.map{|child| child.accept_rpc_creator visitor}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ImportNode < Base
|
32
|
+
def initialize(path)
|
33
|
+
@path = path
|
34
|
+
end
|
35
|
+
|
36
|
+
def accept_message_creator(visitor)
|
37
|
+
visitor.write "require '#{visitor.required_message_from_proto @path}'"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class PackageNode < Base
|
42
|
+
def initialize(path_list)
|
43
|
+
@path_list = path_list
|
44
|
+
end
|
45
|
+
|
46
|
+
def accept_message_creator(visitor)
|
47
|
+
@path_list.each do |path|
|
48
|
+
visitor.write "module #{path.to_s.capitalize}"
|
49
|
+
visitor.increment
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def accept_rpc_creator(visitor)
|
54
|
+
visitor.package = @path_list.dup
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class OptionNode < Base
|
59
|
+
def initialize(name_list, value)
|
60
|
+
@name_list, @value = name_list, value
|
61
|
+
end
|
62
|
+
|
63
|
+
def accept_message_creator(visitor)
|
64
|
+
visitor.write "::Protobuf::OPTIONS[:#{@name_list.join('.').inspect}] = #{@value.inspect}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class MessageNode < Base
|
69
|
+
def initialize(name, children)
|
70
|
+
@name, @children = name, children
|
71
|
+
end
|
72
|
+
|
73
|
+
def accept_message_creator(visitor)
|
74
|
+
visitor.write "class #{@name} < ::Protobuf::Message"
|
75
|
+
visitor.in_context self.class do
|
76
|
+
@children.each {|child| child.accept_message_creator visitor}
|
77
|
+
end
|
78
|
+
visitor.write "end"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class ExtendNode < Base
|
83
|
+
def initialize(name, children)
|
84
|
+
@name, @children = name, children
|
85
|
+
end
|
86
|
+
|
87
|
+
def accept_message_creator(visitor)
|
88
|
+
visitor.write "class #{@name} < ::Protobuf::Message"
|
89
|
+
visitor.in_context self.class do
|
90
|
+
@children.each {|child| child.accept_message_creator visitor}
|
91
|
+
end
|
92
|
+
visitor.write "end"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class EnumNode < Base
|
97
|
+
def initialize(name, children)
|
98
|
+
@name, @children = name, children
|
99
|
+
end
|
100
|
+
|
101
|
+
def accept_message_creator(visitor)
|
102
|
+
visitor.write "class #{@name} < ::Protobuf::Enum"
|
103
|
+
visitor.in_context self.class do
|
104
|
+
@children.each {|child| child.accept_message_creator visitor}
|
105
|
+
end
|
106
|
+
visitor.write "end"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class EnumFieldNode < Base
|
111
|
+
def initialize(name, value)
|
112
|
+
@name, @value = name, value
|
113
|
+
end
|
114
|
+
|
115
|
+
def accept_message_creator(visitor)
|
116
|
+
visitor.write "#{@name} = #{@value}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class ServiceNode < Base
|
121
|
+
def initialize(name, children)
|
122
|
+
@name, @children = name, children
|
123
|
+
end
|
124
|
+
|
125
|
+
def accept_message_creator(visitor)
|
126
|
+
# do nothing
|
127
|
+
#visitor.write "class #{@name} < ::Protobuf::Service"
|
128
|
+
#visitor.in_context self.class do
|
129
|
+
# @children.each {|child| child.accept_message_creator visitor}
|
130
|
+
#end
|
131
|
+
#visitor.write "end"
|
132
|
+
end
|
133
|
+
|
134
|
+
def accept_rpc_creator(visitor)
|
135
|
+
visitor.current_service = @name
|
136
|
+
@children.each {|child| child.accept_rpc_creator visitor}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class RpcNode < Base
|
141
|
+
def initialize(name, request, response)
|
142
|
+
@name, @request, @response = name, request, response
|
143
|
+
end
|
144
|
+
|
145
|
+
def accept_message_creator(visitor)
|
146
|
+
# do nothing
|
147
|
+
#visitor.write "rpc :#{@name}, :request => :#{@request}, :response => :#{@response}"
|
148
|
+
end
|
149
|
+
|
150
|
+
def accept_rpc_creator(visitor)
|
151
|
+
visitor.add_rpc @name, @request, @response
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class GroupNode < Base
|
156
|
+
def initialize(label, name, value, children)
|
157
|
+
@label, @name, @value, @children = label, name, value, children
|
158
|
+
end
|
159
|
+
|
160
|
+
def accept_message_creator(visitor)
|
161
|
+
raise ArgumentError.new('have not implement')
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class FieldNode < Base
|
166
|
+
def initialize(label, type, name, value, opts=[])
|
167
|
+
@label, @type, @name, @value, @opts = label, type, name, value, opts
|
168
|
+
end
|
169
|
+
|
170
|
+
def accept_message_creator(visitor)
|
171
|
+
opts = @opts.empty? ? '' : ", #{@opts.map{|k, v| ":#{k} => :#{v}"}.join(', ')}"
|
172
|
+
if visitor.context.first == Protobuf::Node::ExtendNode
|
173
|
+
opts += ', :extension => true'
|
174
|
+
end
|
175
|
+
visitor.write "#{@label} :#{@type}, :#{@name}, #{@value}#{opts}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class ExtensionsNode < Base
|
180
|
+
def initialize(range)
|
181
|
+
@range = range
|
182
|
+
end
|
183
|
+
|
184
|
+
def accept_message_creator(visitor)
|
185
|
+
visitor.write "extensions #{@range.to_s}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
class ExtensionRangeNode < Base
|
190
|
+
def initialize(low, high=nil)
|
191
|
+
@low, @high = low, high
|
192
|
+
end
|
193
|
+
|
194
|
+
#def accept_message_creator(visitor)
|
195
|
+
#end
|
196
|
+
|
197
|
+
def to_s
|
198
|
+
if @high.nil?
|
199
|
+
@low.to_s
|
200
|
+
elsif @high == :max
|
201
|
+
"#{@low}..Protobuf::Extend::MAX"
|
202
|
+
else
|
203
|
+
"#{@low}..#{@high}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|