ruby_protobuf 0.2.0 → 0.3.0
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 +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
|
+
}
|