macks-ruby_protobuf 0.3.2.1

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