macks-ruby_protobuf 0.3.2.1

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.
Files changed (76) hide show
  1. data/History.txt +14 -0
  2. data/Manifest.txt +74 -0
  3. data/README.txt +58 -0
  4. data/Rakefile +18 -0
  5. data/bin/mk_parser +2 -0
  6. data/bin/rprotoc +36 -0
  7. data/examples/addressbook.pb.rb +56 -0
  8. data/examples/addressbook.proto +24 -0
  9. data/examples/reading_a_message.rb +32 -0
  10. data/examples/writing_a_message.rb +46 -0
  11. data/lib/protobuf/common/wire_type.rb +10 -0
  12. data/lib/protobuf/compiler/compiler.rb +54 -0
  13. data/lib/protobuf/compiler/nodes.rb +319 -0
  14. data/lib/protobuf/compiler/proto.y +203 -0
  15. data/lib/protobuf/compiler/proto2.ebnf +79 -0
  16. data/lib/protobuf/compiler/proto_parser.rb +1394 -0
  17. data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
  18. data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
  19. data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
  20. data/lib/protobuf/compiler/visitors.rb +288 -0
  21. data/lib/protobuf/descriptor/descriptor.proto +286 -0
  22. data/lib/protobuf/descriptor/descriptor.rb +54 -0
  23. data/lib/protobuf/descriptor/descriptor_builder.rb +144 -0
  24. data/lib/protobuf/descriptor/descriptor_proto.rb +119 -0
  25. data/lib/protobuf/descriptor/enum_descriptor.rb +33 -0
  26. data/lib/protobuf/descriptor/field_descriptor.rb +50 -0
  27. data/lib/protobuf/descriptor/file_descriptor.rb +38 -0
  28. data/lib/protobuf/message/decoder.rb +93 -0
  29. data/lib/protobuf/message/encoder.rb +37 -0
  30. data/lib/protobuf/message/enum.rb +28 -0
  31. data/lib/protobuf/message/extend.rb +8 -0
  32. data/lib/protobuf/message/field.rb +654 -0
  33. data/lib/protobuf/message/message.rb +308 -0
  34. data/lib/protobuf/message/protoable.rb +37 -0
  35. data/lib/protobuf/message/service.rb +9 -0
  36. data/lib/protobuf/rpc/client.rb +19 -0
  37. data/lib/protobuf/rpc/handler.rb +17 -0
  38. data/lib/protobuf/rpc/server.rb +39 -0
  39. data/lib/ruby_protobuf.rb +3 -0
  40. data/test/addressbook.rb +98 -0
  41. data/test/addressbook_base.rb +62 -0
  42. data/test/addressbook_ext.rb +12 -0
  43. data/test/check_unbuild.rb +30 -0
  44. data/test/collision.rb +18 -0
  45. data/test/data/data.bin +3 -0
  46. data/test/data/data_source.py +14 -0
  47. data/test/data/types.bin +0 -0
  48. data/test/data/types_source.py +22 -0
  49. data/test/data/unk.png +0 -0
  50. data/test/ext_collision.rb +25 -0
  51. data/test/ext_range.rb +23 -0
  52. data/test/merge.rb +40 -0
  53. data/test/nested.rb +25 -0
  54. data/test/proto/addressbook.proto +31 -0
  55. data/test/proto/addressbook_base.proto +26 -0
  56. data/test/proto/addressbook_ext.proto +6 -0
  57. data/test/proto/collision.proto +5 -0
  58. data/test/proto/ext_collision.proto +8 -0
  59. data/test/proto/ext_range.proto +7 -0
  60. data/test/proto/merge.proto +15 -0
  61. data/test/proto/nested.proto +7 -0
  62. data/test/proto/rpc.proto +6 -0
  63. data/test/proto/types.proto +17 -0
  64. data/test/test_addressbook.rb +43 -0
  65. data/test/test_compiler.rb +313 -0
  66. data/test/test_descriptor.rb +122 -0
  67. data/test/test_extension.rb +40 -0
  68. data/test/test_message.rb +106 -0
  69. data/test/test_optional_field.rb +68 -0
  70. data/test/test_parse.rb +15 -0
  71. data/test/test_ruby_protobuf.rb +1 -0
  72. data/test/test_serialize.rb +42 -0
  73. data/test/test_standard_message.rb +96 -0
  74. data/test/test_types.rb +181 -0
  75. data/test/types.rb +22 -0
  76. metadata +150 -0
@@ -0,0 +1,308 @@
1
+ require 'pp'
2
+ require 'stringio'
3
+ require 'protobuf/descriptor/descriptor'
4
+ require 'protobuf/message/decoder'
5
+ require 'protobuf/message/encoder'
6
+ require 'protobuf/message/field'
7
+ require 'protobuf/message/protoable'
8
+
9
+ module Protobuf
10
+ OPTIONS = {}
11
+
12
+ class Message
13
+ class TagCollisionError < StandardError; end
14
+
15
+ class ExtensionFields < Hash
16
+ def initialize(key_range=0..-1)
17
+ @key_range = key_range
18
+ end
19
+
20
+ def []=(key, value)
21
+ raise RangeError.new("#{key} is not in #{@key_range}") unless @key_range.include? key
22
+ super
23
+ end
24
+
25
+ def include_tag?(tag)
26
+ @key_range.include? tag
27
+ end
28
+ end
29
+
30
+ class <<self
31
+ include Protobuf::Protoable
32
+ def fields; @fields ||= {} end
33
+
34
+ def extensions(range)
35
+ @extension_fields = ExtensionFields.new range
36
+ end
37
+
38
+ def required(type, name, tag, opts={})
39
+ define_field :required, type, name, tag, opts
40
+ end
41
+
42
+ def optional(type, name, tag, opts={})
43
+ define_field :optional, type, name, tag, opts
44
+ end
45
+
46
+ def repeated(type, name, tag, opts={})
47
+ define_field :repeated, type, name, tag, opts
48
+ end
49
+
50
+ def define_field(rule, type, fname, tag, opts={})
51
+ field_hash = opts[:extension] ? extension_fields : (@fields ||= {})
52
+ raise Protobuf::Message::TagCollisionError.new(<<-eos.strip) if field_hash.keys.include? tag
53
+ Field number #{tag} has already been used in "#{self.name}" by field "#{fname}".
54
+ eos
55
+ field_hash[tag] = Protobuf::Field.build self, rule, type, fname, tag, opts
56
+ end
57
+
58
+ def extension_tag?(tag)
59
+ extension_fields.include_tag? tag
60
+ end
61
+
62
+ def extension_fields
63
+ @extension_fields ||= ExtensionFields.new
64
+ end
65
+
66
+ def get_field_by_name(name)
67
+ fields.values.find {|field| field.name == name.to_sym}
68
+ end
69
+
70
+ def get_field_by_tag(tag)
71
+ fields[tag]
72
+ end
73
+
74
+ def get_field(tag_or_name)
75
+ case tag_or_name
76
+ when Integer; get_field_by_tag tag_or_name
77
+ when String, Symbol; get_field_by_name tag_or_name
78
+ else; raise TypeError.new(tag_or_name.class)
79
+ end
80
+ end
81
+
82
+ #TODO merge to get_field_by_name
83
+ def get_ext_field_by_name(name)
84
+ extension_fields.values.find {|field| field.name == name.to_sym}
85
+ end
86
+
87
+ #TODO merge to get_field_by_tag
88
+ def get_ext_field_by_tag(tag)
89
+ extension_fields[tag]
90
+ end
91
+
92
+ #TODO merge to get_field
93
+ def get_ext_field(tag_or_name)
94
+ case tag_or_name
95
+ when Integer; get_ext_field_by_tag tag_or_name
96
+ when String, Symbol; get_ext_field_by_name tag_or_name
97
+ else; raise TypeError.new(tag_or_name.class)
98
+ end
99
+ end
100
+
101
+ def descriptor
102
+ @descriptor ||= Protobuf::Descriptor::Descriptor.new(self)
103
+ end
104
+ end
105
+
106
+ def initialize(values={})
107
+ @values = {}
108
+
109
+ fields.each do |tag, field|
110
+ unless field.ready?
111
+ field = field.setup
112
+ self.class.class_eval {@fields[tag] = field}
113
+ end
114
+ field.define_accessor self
115
+ end
116
+
117
+ # TODO
118
+ self.class.extension_fields.each do |tag, field|
119
+ unless field.ready?
120
+ field = field.setup
121
+ self.class.class_eval {@extension_fields[tag] = field}
122
+ end
123
+ field.define_accessor self
124
+ end
125
+
126
+ values.each {|tag, val| self[tag] = val}
127
+ end
128
+
129
+ def initialized?
130
+ fields.to_a.inject(true) do |result, (tag, field)|
131
+ result and field.initialized?(self)
132
+ end and
133
+ extension_fields.to_a.inject(true) do |result, (tag, field)|
134
+ result and field.initialized?(self)
135
+ end
136
+ end
137
+
138
+ def has_field?(tag_or_name)
139
+ field = get_field(tag_or_name) || get_ext_field(tag_or_name)
140
+ raise ArgumentError.new("unknown field: #{tag_or_name.inspect}") unless field
141
+ @values.has_key?(field.name)
142
+ end
143
+
144
+ def ==(obj)
145
+ return false unless obj.is_a? self.class
146
+ each_field do |field, value|
147
+ return false unless value == obj[field.name]
148
+ end
149
+ true
150
+ end
151
+
152
+ def clear!
153
+ each_field do |field, value|
154
+ field.clear self
155
+ end
156
+ end
157
+
158
+ def dup
159
+ ret = self.class.new
160
+ each_field do |field, value|
161
+ if field.repeated?
162
+ value.each do |v|
163
+ ret[field.name] << (v.is_a?(Numeric) ? v : v.dup)
164
+ end
165
+ else
166
+ ret[field.name] = value.is_a?(Numeric) ? value : value.dup
167
+ end
168
+ end
169
+ ret
170
+ end
171
+
172
+ def inspect(indent=0)
173
+ ret = ''
174
+ i = ' ' * indent
175
+ field_value_to_string = lambda do |field, value|
176
+ ret +=
177
+ if field.is_a? Protobuf::Field::MessageField
178
+ if value.nil?
179
+ if $DEBUG
180
+ "#{i}#{field.name} {\n#{' ' * (indent + 1)}nil\n#{i}}\n"
181
+ else
182
+ "#{i}#{field.name} {}\n"
183
+ end
184
+ else
185
+ "#{i}#{field.name} {\n#{value.inspect(indent + 1)}#{i}}\n"
186
+ end
187
+ elsif field.is_a? Protobuf::Field::EnumField
188
+ if field.optional? and not has_field?(field.name)
189
+ ''
190
+ else
191
+ "#{i}#{field.name}: #{field.type.name_by_value(value)}\n"
192
+ end
193
+ else
194
+ if $DEBUG
195
+ "#{i}#{field.name}: #{value.inspect}\n"
196
+ else
197
+ if field.optional? and not has_field?(field.name)
198
+ ''
199
+ else
200
+ "#{i}#{field.name}: #{value.inspect}\n"
201
+ end
202
+ end
203
+ end
204
+ end
205
+ each_field do |field, value|
206
+ if field.repeated?
207
+ value.each do |v|
208
+ field_value_to_string.call field, v
209
+ end
210
+ else
211
+ field_value_to_string.call field, value
212
+ end
213
+ end
214
+ ret
215
+ end
216
+
217
+ def parse_from_string(string)
218
+ parse_from StringIO.new(string)
219
+ end
220
+
221
+ def parse_from_file(filename)
222
+ if filename.is_a? File
223
+ parse_from filename
224
+ else
225
+ File.open(filename, 'r') do |f|
226
+ parse_from f
227
+ end
228
+ end
229
+ end
230
+
231
+ def parse_from(stream)
232
+ Protobuf::Decoder.decode stream, self
233
+ end
234
+
235
+ def serialize_to_string(string='')
236
+ io = StringIO.new string
237
+ serialize_to io
238
+ io.string
239
+ end
240
+ alias to_s serialize_to_string
241
+
242
+ def serialize_to_file(filename)
243
+ if filename.is_a? File
244
+ serialize_to filename
245
+ else
246
+ File.open(filename, 'w') do |f|
247
+ serialize_to f
248
+ end
249
+ end
250
+ end
251
+
252
+ def serialize_to(stream)
253
+ Protobuf::Encoder.encode stream, self
254
+ end
255
+
256
+ def merge_from(message)
257
+ # TODO
258
+ fields.each {|tag, field| merge_field tag, message[tag]}
259
+ self.class.extension_fields.each {|tag, field| merge_field tag, message[tag]}
260
+ end
261
+
262
+ def set_field(tag, bytes)
263
+ #get_field_by_tag(tag).set self, bytes # TODO
264
+ (get_field_by_tag(tag) or get_ext_field_by_tag(tag)).set self, bytes
265
+ end
266
+
267
+ def merge_field(tag, value)
268
+ #get_field_by_tag(tag).merge self, bytes #TODO
269
+ (get_field_by_tag(tag) or get_ext_field_by_tag(tag)).merge self, value
270
+ end
271
+
272
+ def [](tag_or_name)
273
+ if field = get_field(tag_or_name)
274
+ send field.name
275
+ elsif field = get_ext_field(tag_or_name)
276
+ send field.name
277
+ else
278
+ raise NoMethodError.new("No such method: #{tag_or_name.inspect}")
279
+ end
280
+ end
281
+
282
+ def []=(tag_or_name, value)
283
+ if field = get_field(tag_or_name) and not field.repeated?
284
+ send "#{field.name}=", value
285
+ elsif field = get_ext_field(tag_or_name) and not field.repeated?
286
+ send "#{field.name}=", value
287
+ else
288
+ raise NoMethodError.new("No such method: #{tag_or_name.inspect}")
289
+ end
290
+ end
291
+
292
+ def fields; self.class.fields end
293
+ def get_field_by_name(name); self.class.get_field_by_name(name) end
294
+ def get_field_by_tag(tag); self.class.get_field_by_tag(tag) end
295
+ def get_field(tag_or_name); self.class.get_field(tag_or_name) end
296
+
297
+ def extension_fields; self.class.extension_fields end
298
+ def get_ext_field_by_name(name); self.class.get_ext_field_by_name(name) end
299
+ def get_ext_field_by_tag(tag); self.class.get_ext_field_by_tag(tag) end
300
+ def get_ext_field(tag_or_name); self.class.get_ext_field(tag_or_name) end
301
+
302
+ def each_field(&block)
303
+ (fields.merge extension_fields).to_a.sort{|(t1, f1), (t2, f2)| t1 <=> t2}.each do |tag, field|
304
+ block.call field, self[tag]
305
+ end
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,37 @@
1
+ module Protobuf
2
+ module Protoable
3
+ def defined_filenames
4
+ @defined_filenames ||= []
5
+ end
6
+
7
+ def defined_in(filename)
8
+ defined_filenames << File.expand_path(filename)
9
+ end
10
+
11
+ def proto_filenames
12
+ defined_filenames.map do |filename|
13
+ retrieve_header(File.read(filename)).first
14
+ end
15
+ end
16
+
17
+ def proto_contents
18
+ #TODO: temporary implementation because the result includes not only this message but also all messages
19
+ ret = {}
20
+ defined_filenames.map do |filename|
21
+ header = retrieve_header File.read(filename)
22
+ ret[header.first] = header.last
23
+ end
24
+ ret
25
+ end
26
+
27
+ def retrieve_header(contents)
28
+ if contents =~ /### Generated by rprotoc\. DO NOT EDIT!\n### <proto file: (.*)>\n((# .*\n)+)/
29
+ proto_filename = $1
30
+ proto_contents = $2.gsub(/^# /, '')
31
+ [proto_filename, proto_contents]
32
+ else
33
+ [nil, nil]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ module Protobuf
2
+ class Service
3
+ class <<self
4
+ def rpc(hash)
5
+ raise NotImplementedError('TODO')
6
+ end
7
+ end
8
+ end
9
+ 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
@@ -0,0 +1,3 @@
1
+ class RubyProtobuf
2
+ VERSION = '0.3.2.1'
3
+ end
@@ -0,0 +1,98 @@
1
+ ### Generated by rprotoc. DO NOT EDIT!
2
+ ### <proto file: test/addressbook.proto>
3
+ # package tutorial;
4
+ #
5
+ # message Person {
6
+ # required string name = 1;
7
+ # required int32 id = 2;
8
+ # optional string email = 3;
9
+ #
10
+ # enum PhoneType {
11
+ # MOBILE = 0;
12
+ # HOME = 1;
13
+ # WORK = 2;
14
+ # }
15
+ #
16
+ # message PhoneNumber {
17
+ # required string number = 1;
18
+ # optional PhoneType type = 2 [default = HOME];
19
+ # }
20
+ #
21
+ # repeated PhoneNumber phone = 4;
22
+ #
23
+ # extensions 100 to 200;
24
+ # }
25
+ #
26
+ # extend Person {
27
+ # optional int32 age = 100;
28
+ # }
29
+ #
30
+ # message AddressBook {
31
+ # repeated Person person = 1;
32
+ # }
33
+ require 'protobuf/message/message'
34
+ require 'protobuf/message/enum'
35
+ require 'protobuf/message/service'
36
+ require 'protobuf/message/extend'
37
+
38
+ module Tutorial
39
+
40
+ class Person < ::Protobuf::Message
41
+ defined_in __FILE__
42
+ required :string, :name, 1
43
+ required :int32, :id, 2
44
+ optional :string, :email, 3
45
+
46
+ class PhoneType < ::Protobuf::Enum
47
+ defined_in __FILE__
48
+ MOBILE = 0
49
+ HOME = 1
50
+ WORK = 2
51
+ end
52
+
53
+ class PhoneNumber < ::Protobuf::Message
54
+ defined_in __FILE__
55
+ required :string, :number, 1
56
+ optional :PhoneType, :type, 2, {:default => :HOME}
57
+ end
58
+
59
+ repeated :PhoneNumber, :phone, 4
60
+
61
+ #extensions 100..200
62
+ end
63
+
64
+ # see: addressbool_ext.rb
65
+ #class Person < ::Protobuf::Message
66
+ # optional :int32, :age, 100, :extension => true
67
+ #end
68
+
69
+ class AddressBook < ::Protobuf::Message
70
+ defined_in __FILE__
71
+ repeated :Person, :person, 1
72
+ end
73
+
74
+ #class SearchService < Protobuf::Service
75
+ # rpc :Search, :request => :SearchRequest, :response => :SearchResponse
76
+ #end
77
+
78
+ #Protobuf::OPTIONS[:optimize_for] = :SPEED
79
+ #Protobuf::OPTIONS[:java_package] = :'com.example.foo'
80
+ end
81
+
82
+ =begin
83
+ tutorial = Object.const_set :Tutorial, Module.new
84
+ person = tutorial.const_set :Person, Class.new(Protobuf::Message)
85
+ person.required :string, :name, 1
86
+ person.required :int32, :id, 2
87
+ person.optional :string, :email, 3
88
+ phone_type = person.const_set :PhoneType, Class.new(Protobuf::Enum)
89
+ phone_type.const_set :MOBILE, 0
90
+ phone_type.const_set :HOME, 1
91
+ phone_type.const_set :WORK, 2
92
+ phone_number = person.const_set :PhoneNumber, Class.new(Protobuf::Message)
93
+ phone_number.required :string, :number, 1
94
+ phone_number.optional :PhoneType, :type, 2, {:default => :HOME}
95
+ person.repeated :PhoneNumber, :phone, 4
96
+ address_book = tutorial.const_set :AddressBook, Class.new(Protobuf::Message)
97
+ address_book.repeated :Person, :person, 1
98
+ =end
@@ -0,0 +1,62 @@
1
+ require 'protobuf/message/message'
2
+ require 'protobuf/message/enum'
3
+ require 'protobuf/message/service'
4
+ require 'protobuf/message/extend'
5
+
6
+ module TutorialExt
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
+
26
+ extensions 100..200
27
+ end
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
35
+ repeated :Person, :person, 1
36
+ end
37
+
38
+ #class SearchService < Protobuf::Service
39
+ # rpc :Search => :SearchRequest, :returns => :SearchResponse
40
+ #end
41
+
42
+ #Protobuf::OPTIONS[:optimize_for] = :SPEED
43
+ #Protobuf::OPTIONS[:java_package] = :'com.example.foo'
44
+ end
45
+
46
+ =begin
47
+ tutorial = Object.const_set :Tutorial, Module.new
48
+ person = tutorial.const_set :Person, Class.new(Protobuf::Message)
49
+ person.required :string, :name, 1
50
+ person.required :int32, :id, 2
51
+ person.optional :string, :email, 3
52
+ phone_type = person.const_set :PhoneType, Class.new(Protobuf::Enum)
53
+ phone_type.const_set :MOBILE, 0
54
+ phone_type.const_set :HOME, 1
55
+ phone_type.const_set :WORK, 2
56
+ phone_number = person.const_set :PhoneNumber, Class.new(Protobuf::Message)
57
+ phone_number.required :string, :number, 1
58
+ phone_number.optional :PhoneType, :type, 2, {:default => :HOME}
59
+ person.repeated :PhoneNumber, :phone, 4
60
+ address_book = tutorial.const_set :AddressBook, Class.new(Protobuf::Message)
61
+ address_book.repeated :Person, :person, 1
62
+ =end
@@ -0,0 +1,12 @@
1
+ require 'protobuf/message/message'
2
+ require 'protobuf/message/enum'
3
+ require 'protobuf/message/service'
4
+ require 'protobuf/message/extend'
5
+
6
+ require 'addressbook_base'
7
+
8
+ module TutorialExt
9
+ class Person < ::Protobuf::Message
10
+ optional :int32, :age, 100, :extension => true
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.push "#{File.dirname(__FILE__)}/../lib"
4
+
5
+ require 'test/unit'
6
+ require 'protobuf/descriptor/descriptor_builder'
7
+ require 'protobuf/descriptor/descriptor_proto'
8
+
9
+ class DescriptorTest < Test::Unit::TestCase
10
+ def test_unbuild
11
+ tutorial_proto = Google::Protobuf::FileDescriptorProto.new
12
+ tutorial_proto.parse_from_file 'person.bin'
13
+ Protobuf::Descriptor::DescriptorBuilder.build tutorial_proto
14
+
15
+ assert_nothing_raised {Tutorial::Person}
16
+ assert_nothing_raised {Tutorial::Person.new}
17
+ assert_equal ['email', 'id', 'name', 'phone'],
18
+ Tutorial::Person.fields.map{|tag, field| field.name}.sort
19
+
20
+ assert_nothing_raised {Tutorial::Person::PhoneNumber}
21
+ assert_nothing_raised {Tutorial::Person::PhoneNumber.new}
22
+ assert_equal ['number', 'type'],
23
+ Tutorial::Person::PhoneNumber.fields.map{|tag, field| field.name}.sort
24
+
25
+ assert_nothing_raised {Tutorial::Person::PhoneType}
26
+ assert_equal 0, Tutorial::Person::PhoneType::MOBILE
27
+ assert_equal 1, Tutorial::Person::PhoneType::HOME
28
+ assert_equal 2, Tutorial::Person::PhoneType::WORK
29
+ end
30
+ end
data/test/collision.rb ADDED
@@ -0,0 +1,18 @@
1
+ ### Generated by rprotoc. DO NOT EDIT!
2
+ ### <proto file: test/proto/collision.proto>
3
+ # message CollisionTest {
4
+ # optional string a = 1;
5
+ # optional string b = 1;
6
+ # }
7
+ #
8
+
9
+ require 'protobuf/message/message'
10
+ require 'protobuf/message/enum'
11
+ require 'protobuf/message/service'
12
+ require 'protobuf/message/extend'
13
+
14
+ class CollisionTest < ::Protobuf::Message
15
+ defined_in __FILE__
16
+ optional :string, :a, 1
17
+ optional :string, :b, 1
18
+ end
@@ -0,0 +1,3 @@
1
+
2
+ John Doe� jdoe@example.com"
3
+ 555-4321
@@ -0,0 +1,14 @@
1
+ import addressbook_pb2
2
+ import sys
3
+
4
+ person = addressbook_pb2.Person()
5
+ person.id = 1234
6
+ person.name = "John Doe"
7
+ person.email = "jdoe@example.com"
8
+ phone = person.phone.add()
9
+ phone.number = "555-4321"
10
+ phone.type = addressbook_pb2.Person.HOME
11
+
12
+ f = open('data.bin', 'wb')
13
+ f.write(person.SerializeToString())
14
+ f.close()
Binary file