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
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require 'protobuf/rpc/client'
|
3
|
+
require '<%= required_file %>'
|
4
|
+
|
5
|
+
# build request
|
6
|
+
request = <%= message_module %>::<%= request %>.new
|
7
|
+
# TODO: setup a request
|
8
|
+
raise StandardError.new('setup a request')
|
9
|
+
|
10
|
+
# create blunk response
|
11
|
+
response = <%= message_module %>::<%= response %>.new
|
12
|
+
|
13
|
+
# execute rpc
|
14
|
+
Protobuf::Rpc::Client.new('localhost', <%= default_port %>).call :<%= underscore name %>, request, response
|
15
|
+
|
16
|
+
# show response
|
17
|
+
puts response
|
18
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'protobuf/rpc/server'
|
2
|
+
require 'protobuf/rpc/handler'
|
3
|
+
require '<%= required_file %>'
|
4
|
+
|
5
|
+
<%- rpcs.each do |name, request, response| -%>
|
6
|
+
class <%= module_name %>::<%= name %>Handler < Protobuf::Rpc::Handler
|
7
|
+
request <%= module_name %>::<%= request %>
|
8
|
+
response <%= module_name %>::<%= response %>
|
9
|
+
|
10
|
+
def self.process_request(request, response)
|
11
|
+
# TODO: edit this method
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
<%- end -%>
|
16
|
+
class <%= module_name %>::<%= service_name %> < Protobuf::Rpc::Server
|
17
|
+
def setup_handlers
|
18
|
+
@handlers = {
|
19
|
+
<%- rpcs.each do |name, | -%>
|
20
|
+
:<%= underscore name %> => <%= module_name %>::<%= name %>Handler,
|
21
|
+
<%- end -%>
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Visitor
|
5
|
+
class CreateMessageVisitor
|
6
|
+
attr_accessor :indent, :context
|
7
|
+
|
8
|
+
def initialize(proto_dir='.', out_dir='.')
|
9
|
+
@proto_dir, @out_dir = proto_dir, out_dir
|
10
|
+
@indent = 0
|
11
|
+
@context = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def write(str)
|
15
|
+
ruby << "#{' ' * @indent}#{str}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def increment
|
19
|
+
@indent += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
def decrement
|
23
|
+
@indent -= 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def close_ruby
|
27
|
+
while 0 < indent
|
28
|
+
decrement
|
29
|
+
write 'end'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def ruby
|
34
|
+
@ruby ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
@ruby.join "\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
def in_context(klass, &block)
|
42
|
+
increment
|
43
|
+
context.push klass
|
44
|
+
block.call
|
45
|
+
context.pop
|
46
|
+
decrement
|
47
|
+
end
|
48
|
+
|
49
|
+
def visit(node)
|
50
|
+
node.accept_message_creator self
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def required_message_from_proto(proto_file)
|
55
|
+
rb_path = proto_file.sub(/\.proto$/, '.rb')
|
56
|
+
unless File.exist?("#{@out_dir}/#{rb_path}")
|
57
|
+
Compiler.compile proto_file, @proto_dir, @out_dir
|
58
|
+
end
|
59
|
+
rb_path.sub /\.rb$/, ''
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class CreateRpcVisitor
|
64
|
+
attr_accessor :package, :services, :current_service, :file_contents
|
65
|
+
|
66
|
+
def initialize
|
67
|
+
@services = {}
|
68
|
+
@create_file = true
|
69
|
+
@file_contents = {}
|
70
|
+
end
|
71
|
+
|
72
|
+
def visit(node)
|
73
|
+
node.accept_rpc_creator self
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_rpc(name, request, response)
|
78
|
+
(@services[@current_service] ||= []) << [name, request.first, response.first]
|
79
|
+
end
|
80
|
+
|
81
|
+
#def create_files(message_file, out_dir, create_file=true)
|
82
|
+
def create_files(message_file, out_dir, create_file=false)
|
83
|
+
@create_file = create_file
|
84
|
+
default_port = 9999
|
85
|
+
@services.each do |service_name, rpcs|
|
86
|
+
underscored_name = underscore service_name.to_s
|
87
|
+
message_module = package.map{|p| p.to_s.capitalize}.join('::')
|
88
|
+
required_file = message_file.sub(/^\.\//, '').sub(/\.rb$/, '')
|
89
|
+
|
90
|
+
create_bin out_dir, underscored_name, message_module, service_name, default_port
|
91
|
+
create_service message_file, out_dir, underscored_name, message_module,
|
92
|
+
service_name, default_port, rpcs, required_file
|
93
|
+
rpcs.each do |name, request, response|
|
94
|
+
create_client out_dir, underscored_name, default_port, name, request, response, message_module, required_file
|
95
|
+
end
|
96
|
+
end
|
97
|
+
@file_contents
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_bin(out_dir, underscored_name, module_name, service_name, default_port)
|
101
|
+
bin_filename = "#{out_dir}/start_#{underscored_name}"
|
102
|
+
bin_contents = template_erb('rpc_bin').result binding
|
103
|
+
File.open(bin_filename, 'w') {|f| f.write bin_contents} if @create_file
|
104
|
+
@file_contents[bin_filename] = bin_contents
|
105
|
+
end
|
106
|
+
|
107
|
+
def create_service(message_file, out_dir, underscored_name, module_name, service_name, default_port, rpcs, required_file)
|
108
|
+
service_filename = "#{out_dir}/#{underscored_name}.rb"
|
109
|
+
service_contents = template_erb('rpc_service').result binding
|
110
|
+
File.open(service_filename, 'w') {|f| f.write service_contents} if @create_file
|
111
|
+
@file_contents[service_filename] = service_contents
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_client(out_dir, underscored_name, default_port, name, request, response, message_module, required_file)
|
115
|
+
client_filename = "#{out_dir}/client_#{underscore name}.rb"
|
116
|
+
client_contents = template_erb('rpc_client').result binding
|
117
|
+
File.open(client_filename, 'w') {|f| f.write client_contents} if @create_file
|
118
|
+
@file_contents[client_filename] = client_contents
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def underscore(str)
|
124
|
+
str.to_s.gsub(/\B[A-Z]/, '_\&').downcase
|
125
|
+
end
|
126
|
+
|
127
|
+
def template_erb(template)
|
128
|
+
ERB.new File.read("#{File.dirname(__FILE__)}/template/#{template}.erb"), nil, '-'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -42,10 +42,15 @@ module Protobuf
|
|
42
42
|
protected
|
43
43
|
|
44
44
|
def read_key(stream)
|
45
|
+
# TODO is there more clear way to do this?
|
46
|
+
bits = 0
|
45
47
|
bytes = read_varint stream
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
bytes.each_with_index do |byte, index|
|
49
|
+
byte &= 0b01111111
|
50
|
+
bits |= byte << (7 * index)
|
51
|
+
end
|
52
|
+
wire_type = bits & 0b00000111
|
53
|
+
tag = bits >> 3
|
49
54
|
[tag, wire_type]
|
50
55
|
end
|
51
56
|
|
@@ -31,18 +31,41 @@ module Protobuf
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def initialize(message_class, rule, type, name, tag, opts={})
|
34
|
-
@message_class, @rule, @type, @name, @tag, @default =
|
35
|
-
message_class, rule, type, name, tag, opts[:default]
|
34
|
+
@message_class, @rule, @type, @name, @tag, @default, @extension =
|
35
|
+
message_class, rule, type, name, tag, opts[:default], opts[:extension]
|
36
36
|
@error_message = 'Type invalid'
|
37
37
|
end
|
38
38
|
|
39
39
|
def ready?; true end
|
40
40
|
|
41
|
+
def initialized?(message)
|
42
|
+
case rule
|
43
|
+
when :required
|
44
|
+
return false if message[name].nil?
|
45
|
+
return false if is_a?(Protobuf::Field::MessageField) and not message[name].initialized?
|
46
|
+
when :repeated
|
47
|
+
return message[name].inject(true) do |result, msg|
|
48
|
+
result and msg.initialized?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def clear(message)
|
55
|
+
if repeated?
|
56
|
+
message[name].clear
|
57
|
+
else
|
58
|
+
message[name] = default_value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
41
62
|
def default_value
|
42
63
|
case rule
|
43
64
|
when :repeated
|
44
65
|
FieldArray.new self
|
45
|
-
when :required
|
66
|
+
when :required
|
67
|
+
nil
|
68
|
+
when :optional
|
46
69
|
typed_default_value default
|
47
70
|
else
|
48
71
|
raise InvalidRuleError
|
@@ -68,10 +91,13 @@ module Protobuf
|
|
68
91
|
end
|
69
92
|
|
70
93
|
def define_setter(message_instance)
|
94
|
+
extension = @extension
|
71
95
|
message_instance.instance_eval %Q{
|
72
96
|
def #{name}=(val)
|
73
|
-
field =
|
74
|
-
if
|
97
|
+
field = get_#{extension ? 'ext_' : ''}field_by_name #{name.inspect}
|
98
|
+
if val.nil?
|
99
|
+
@#{name} = field.default_value
|
100
|
+
elsif field.acceptable? val
|
75
101
|
@#{name} = val
|
76
102
|
end
|
77
103
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'pp'
|
1
2
|
require 'stringio'
|
2
3
|
require 'protobuf/message/decoder'
|
3
4
|
require 'protobuf/message/encoder'
|
@@ -7,12 +8,28 @@ require 'protobuf/descriptor/descriptor'
|
|
7
8
|
module Protobuf
|
8
9
|
OPTIONS = {}
|
9
10
|
|
11
|
+
|
10
12
|
class Message
|
13
|
+
class ExtensionFields < Hash
|
14
|
+
def initialize(key_range=0..-1)
|
15
|
+
@key_range = key_range
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
raise RangeError.new("#{key} is not in #{@key_range}") unless @key_range.include? key
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def include_tag?(tag)
|
24
|
+
@key_range.include? tag
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
11
28
|
class <<self
|
12
29
|
attr_reader :fields
|
13
30
|
|
14
31
|
def extensions(range)
|
15
|
-
|
32
|
+
@extension_fields = ExtensionFields.new range
|
16
33
|
end
|
17
34
|
|
18
35
|
def required(type, name, tag, opts={})
|
@@ -28,25 +45,51 @@ module Protobuf
|
|
28
45
|
end
|
29
46
|
|
30
47
|
def define_field(rule, type, name, tag, opts={})
|
31
|
-
|
48
|
+
field_hash = opts[:extension] ? extension_fields : (@fields ||= {})
|
49
|
+
field_hash[tag] = Protobuf::Field.build self, rule, type, name, tag, opts
|
50
|
+
#(@fields ||= {})[tag] = Protobuf::Field.build self, rule, type, name, tag, opts
|
51
|
+
end
|
52
|
+
|
53
|
+
def extension_tag?(tag)
|
54
|
+
extension_fields.include_tag? tag
|
55
|
+
end
|
56
|
+
|
57
|
+
def extension_fields
|
58
|
+
@extension_fields ||= ExtensionFields.new
|
32
59
|
end
|
33
60
|
|
34
61
|
def get_field_by_name(name)
|
35
|
-
|
62
|
+
fields.values.find {|field| field.name == name.to_sym}
|
36
63
|
end
|
37
64
|
|
38
65
|
def get_field_by_tag(tag)
|
39
|
-
|
66
|
+
fields[tag]
|
40
67
|
end
|
41
68
|
|
42
69
|
def get_field(tag_or_name)
|
43
70
|
case tag_or_name
|
44
|
-
when Integer
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
71
|
+
when Integer; get_field_by_tag tag_or_name
|
72
|
+
when String, Symbol; get_field_by_name tag_or_name
|
73
|
+
else; raise TypeError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
#TODO merge to get_field_by_name
|
78
|
+
def get_ext_field_by_name(name)
|
79
|
+
extension_fields.values.find {|field| field.name == name.to_sym}
|
80
|
+
end
|
81
|
+
|
82
|
+
#TODO merge to get_field_by_tag
|
83
|
+
def get_ext_field_by_tag(tag)
|
84
|
+
extension_fields[tag]
|
85
|
+
end
|
86
|
+
|
87
|
+
#TODO merge to get_field
|
88
|
+
def get_ext_field(tag_or_name)
|
89
|
+
case tag_or_name
|
90
|
+
when Integer; get_ext_field_by_tag tag_or_name
|
91
|
+
when String, Symbol; get_ext_field_by_name tag_or_name
|
92
|
+
else; raise TypeError
|
50
93
|
end
|
51
94
|
end
|
52
95
|
|
@@ -63,6 +106,69 @@ module Protobuf
|
|
63
106
|
end
|
64
107
|
field.define_accessor self
|
65
108
|
end
|
109
|
+
|
110
|
+
# TODO
|
111
|
+
self.class.extension_fields.each do |tag, field|
|
112
|
+
unless field.ready?
|
113
|
+
field = field.setup
|
114
|
+
self.class.class_eval {@extension_fields[tag] = field}
|
115
|
+
end
|
116
|
+
field.define_accessor self
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def initialized?
|
121
|
+
fields.to_a.inject(true) do |result, (tag, field)|
|
122
|
+
result and field.initialized?(self)
|
123
|
+
end and
|
124
|
+
extension_fields.to_a.inject(true) do |result, (tag, field)|
|
125
|
+
result and field.initialized?(self)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def clear!
|
130
|
+
each_field do |field, value|
|
131
|
+
field.clear self
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def dup
|
136
|
+
ret = self.class.new
|
137
|
+
each_field do |field, value|
|
138
|
+
if field.repeated?
|
139
|
+
value.each do |v|
|
140
|
+
ret[field.name] << (v.is_a?(Numeric) ? v : v.dup)
|
141
|
+
end
|
142
|
+
else
|
143
|
+
ret[field.name] = value.is_a?(Numeric) ? value : value.dup
|
144
|
+
end
|
145
|
+
end
|
146
|
+
ret
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_s(indent=0)
|
150
|
+
ret = ''
|
151
|
+
i = ' ' * indent
|
152
|
+
field_value_to_string = lambda do |field, value|
|
153
|
+
ret +=
|
154
|
+
if field.is_a? Protobuf::Field::MessageField
|
155
|
+
"#{i}#{field.name} {\n#{value.to_s(indent + 1)}#{i}}\n"
|
156
|
+
elsif field.is_a? Protobuf::Field::EnumField
|
157
|
+
"#{i}#{field.name}: #{field.type.name_by_value(value)}\n"
|
158
|
+
else
|
159
|
+
"#{i}#{field.name}: #{value.inspect}\n"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
each_field do |field, value|
|
163
|
+
if field.repeated?
|
164
|
+
value.each do |v|
|
165
|
+
field_value_to_string.call field, v
|
166
|
+
end
|
167
|
+
else
|
168
|
+
field_value_to_string.call field, value
|
169
|
+
end
|
170
|
+
end
|
171
|
+
ret
|
66
172
|
end
|
67
173
|
|
68
174
|
def parse_from_string(string)
|
@@ -104,7 +210,8 @@ module Protobuf
|
|
104
210
|
end
|
105
211
|
|
106
212
|
def set_field(tag, bytes)
|
107
|
-
get_field_by_tag(tag).set self, bytes
|
213
|
+
#get_field_by_tag(tag).set self, bytes
|
214
|
+
(get_field_by_tag(tag) or get_ext_field_by_tag(tag)).set self, bytes
|
108
215
|
end
|
109
216
|
|
110
217
|
def merge_field(tag, value)
|
@@ -115,16 +222,20 @@ module Protobuf
|
|
115
222
|
def [](tag_or_name)
|
116
223
|
if field = get_field(tag_or_name)
|
117
224
|
send field.name
|
225
|
+
elsif field = get_ext_field(tag_or_name)
|
226
|
+
send field.name
|
118
227
|
else
|
119
|
-
raise NoMethodError.new("No such method: #{tag_or_name}")
|
228
|
+
raise NoMethodError.new("No such method: #{tag_or_name.inspect}")
|
120
229
|
end
|
121
230
|
end
|
122
231
|
|
123
232
|
def []=(tag_or_name, value)
|
124
233
|
if field = get_field(tag_or_name) and not field.repeated?
|
125
234
|
send "#{field.name}=", value
|
235
|
+
elsif field = get_ext_field(tag_or_name) and not field.repeated?
|
236
|
+
send "#{field.name}=", value
|
126
237
|
else
|
127
|
-
raise NoMethodError.new("No such method: #{tag_or_name}
|
238
|
+
raise NoMethodError.new("No such method: #{tag_or_name.inspect}")
|
128
239
|
end
|
129
240
|
end
|
130
241
|
|
@@ -133,8 +244,13 @@ module Protobuf
|
|
133
244
|
def get_field_by_tag(tag); self.class.get_field_by_tag(tag) end
|
134
245
|
def get_field(tag_or_name); self.class.get_field(tag_or_name) end
|
135
246
|
|
247
|
+
def extension_fields; self.class.extension_fields end
|
248
|
+
def get_ext_field_by_name(name); self.class.get_ext_field_by_name(name) end
|
249
|
+
def get_ext_field_by_tag(tag); self.class.get_ext_field_by_tag(tag) end
|
250
|
+
def get_ext_field(tag_or_name); self.class.get_ext_field(tag_or_name) end
|
251
|
+
|
136
252
|
def each_field(&block)
|
137
|
-
fields.to_a.sort{|(t1, f1), (t2, f2)| t1 <=> t2}.each do |tag, field|
|
253
|
+
(fields.merge extension_fields).to_a.sort{|(t1, f1), (t2, f2)| t1 <=> t2}.each do |tag, field|
|
138
254
|
block.call field, self[tag]
|
139
255
|
end
|
140
256
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Rpc
|
5
|
+
class Client
|
6
|
+
def initialize(host, port)
|
7
|
+
@host, @port = host, port
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(name, request, response)
|
11
|
+
socket = TCPSocket.open @host, @port
|
12
|
+
socket.write "#{name}\n"
|
13
|
+
request.serialize_to socket
|
14
|
+
socket.close_write
|
15
|
+
response.parse_from socket
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
class Handler
|
4
|
+
class <<self
|
5
|
+
attr_reader :request_class, :response_class
|
6
|
+
|
7
|
+
def request(request_class)
|
8
|
+
@request_class = request_class
|
9
|
+
end
|
10
|
+
|
11
|
+
def response(response_class)
|
12
|
+
@response_class = response_class
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'webrick/config'
|
2
|
+
require 'webrick/server'
|
3
|
+
|
4
|
+
module Protobuf
|
5
|
+
module Rpc
|
6
|
+
class Server < WEBrick::GenericServer
|
7
|
+
def initialize(config={:Port => 9999}, default=WEBrick::Config::General)
|
8
|
+
super config, default
|
9
|
+
setup_handlers
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup_handlers
|
13
|
+
@handlers = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_handler(socket)
|
17
|
+
@handlers[socket.readline.strip.to_sym]
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(socket)
|
21
|
+
handler = get_handler socket
|
22
|
+
request = handler.request_class.new
|
23
|
+
request.parse_from socket
|
24
|
+
response = handler.response_class.new
|
25
|
+
begin
|
26
|
+
handler.process_request request, response
|
27
|
+
rescue StandardError => ex
|
28
|
+
@logger.error ex
|
29
|
+
ensure
|
30
|
+
begin
|
31
|
+
response.serialize_to socket
|
32
|
+
rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN => ex
|
33
|
+
@logger.error ex
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/ruby_protobuf.rb
CHANGED
@@ -1,22 +1,3 @@
|
|
1
|
-
require 'protobuf/compiler'
|
2
|
-
|
3
1
|
class RubyProtobuf
|
4
|
-
VERSION = '0.
|
5
|
-
|
6
|
-
def start(proto_file, options)
|
7
|
-
unless File.exist?(proto_file)
|
8
|
-
if File.exist? "#{proto_file}.proto"
|
9
|
-
proto_file = "#{proto_file}.proto"
|
10
|
-
else
|
11
|
-
raise ArgumentError.new("#{proto_file} does not exist.")
|
12
|
-
end
|
13
|
-
end
|
14
|
-
rb_filename = File.basename proto_file.dup
|
15
|
-
rb_filename += '.rb' unless rb_filename.sub!(/.\w+$/, '.rb')
|
16
|
-
rb_filepath = "#{options[:out] || '.'}/#{rb_filename}"
|
17
|
-
puts "#{rb_filepath} writting..."
|
18
|
-
File.open(rb_filepath, 'w') do |f|
|
19
|
-
f.write Protobuf::Compiler.compile(proto_file)
|
20
|
-
end
|
21
|
-
end
|
2
|
+
VERSION = '0.3.0'
|
22
3
|
end
|
data/test/addressbook.proto
CHANGED
data/test/addressbook.rb
CHANGED
@@ -4,36 +4,39 @@ require 'protobuf/message/service'
|
|
4
4
|
require 'protobuf/message/extend'
|
5
5
|
|
6
6
|
module Tutorial
|
7
|
-
|
7
|
+
|
8
|
+
class Person < ::Protobuf::Message
|
8
9
|
required :string, :name, 1
|
9
10
|
required :int32, :id, 2
|
10
11
|
optional :string, :email, 3
|
11
|
-
|
12
|
-
class PhoneType < Protobuf::Enum
|
12
|
+
|
13
|
+
class PhoneType < ::Protobuf::Enum
|
13
14
|
MOBILE = 0
|
14
15
|
HOME = 1
|
15
16
|
WORK = 2
|
16
17
|
end
|
17
|
-
|
18
|
-
class PhoneNumber < Protobuf::Message
|
18
|
+
|
19
|
+
class PhoneNumber < ::Protobuf::Message
|
19
20
|
required :string, :number, 1
|
20
21
|
optional :PhoneType, :type, 2, {:default => :HOME}
|
21
22
|
end
|
22
|
-
|
23
|
+
|
23
24
|
repeated :PhoneNumber, :phone, 4
|
24
|
-
|
25
|
-
#extensions 100..
|
26
|
-
#class Foo < Protobuf::Extend
|
27
|
-
# optional :int32, :bar, 126
|
28
|
-
#end
|
25
|
+
|
26
|
+
#extensions 100..200
|
29
27
|
end
|
30
|
-
|
31
|
-
|
28
|
+
|
29
|
+
# see: addressbool_ext.rb
|
30
|
+
#class Person < ::Protobuf::Message
|
31
|
+
# optional :int32, :age, 100, :extension => true
|
32
|
+
#end
|
33
|
+
|
34
|
+
class AddressBook < ::Protobuf::Message
|
32
35
|
repeated :Person, :person, 1
|
33
36
|
end
|
34
37
|
|
35
38
|
#class SearchService < Protobuf::Service
|
36
|
-
# rpc :Search => :SearchRequest, :
|
39
|
+
# rpc :Search, :request => :SearchRequest, :response => :SearchResponse
|
37
40
|
#end
|
38
41
|
|
39
42
|
#Protobuf::OPTIONS[:optimize_for] = :SPEED
|
@@ -0,0 +1,26 @@
|
|
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
|
+
extensions 100 to 200;
|
22
|
+
}
|
23
|
+
|
24
|
+
message AddressBook {
|
25
|
+
repeated Person person = 1;
|
26
|
+
}
|