beefcake 0.2.1 → 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/README.md CHANGED
@@ -67,25 +67,14 @@ Any object responding to `<<` can accept encoding
67
67
  Ruby deserves and needs first-class ProtoBuf support.
68
68
  Other libs didn't feel very "Ruby" to me and were hard to parse.
69
69
 
70
- # Caveats
70
+ # Generate code from `.proto` file
71
71
 
72
- Currently Beefcake doesn't parse `.proto` files. This is OK for now.
73
- In the simple case, you can create message types by hand; This is Ruby
74
- after all.
72
+ $ protoc --beefcake_out output/path -I path/to/proto/files/dir path/to/proto/file
75
73
 
76
- Example (for the above):
74
+ You can set the BEEFCAKE_NAMESPACE variable to generate the classes under a
75
+ desired namespace. (i.e. App::Foo::Bar)
77
76
 
78
- message Variety {
79
- required int32 x = 1
80
- required int32 y = 2
81
- optional string tag = 3
82
-
83
- ...
84
- }
85
-
86
- In the near future, a generator would be nice. I welcome anyone willing
87
- to work on it to submit patches. The other ruby libs lacked things I would
88
- like, such as an optional namespace param rather than installing on (main).
77
+ # Misc
89
78
 
90
79
  This library was built with EventMachine in mind. Not just blocking-IO.
91
80
 
@@ -0,0 +1,258 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+
4
+ require 'beefcake'
5
+ require 'stringio'
6
+
7
+
8
+ class CodeGeneratorRequest
9
+ include Beefcake::Message
10
+
11
+
12
+ class FieldDescriptorProto
13
+ include Beefcake::Message
14
+
15
+ module Type
16
+ ## 0 is reserved for errors.
17
+ ## Order is weird for historical reasons.
18
+ TYPE_DOUBLE = 1
19
+ TYPE_FLOAT = 2
20
+ TYPE_INT64 = 3 ## Not ZigZag encoded. Negative numbers
21
+ ## take 10 bytes. Use TYPE_SINT64 if negative
22
+ ## values are likely.
23
+ TYPE_UINT64 = 4
24
+ TYPE_INT32 = 5 ## Not ZigZag encoded. Negative numbers
25
+ ## take 10 bytes. Use TYPE_SINT32 if negative
26
+ ## values are likely.
27
+ TYPE_FIXED64 = 6
28
+ TYPE_FIXED32 = 7
29
+ TYPE_BOOL = 8
30
+ TYPE_STRING = 9
31
+ TYPE_GROUP = 10 ## Tag-delimited aggregate.
32
+ TYPE_MESSAGE = 11 ## Length-delimited aggregate.
33
+
34
+ ## New in version 2.
35
+ TYPE_BYTES = 12
36
+ TYPE_UINT32 = 13
37
+ TYPE_ENUM = 14
38
+ TYPE_SFIXED32 = 15
39
+ TYPE_SFIXED64 = 16
40
+ TYPE_SINT32 = 17 ## Uses ZigZag encoding.
41
+ TYPE_SINT64 = 18 ## Uses ZigZag encoding.
42
+ end
43
+
44
+ module Label
45
+ LABEL_OPTIONAL = 1
46
+ LABEL_REQUIRED = 2
47
+ LABEL_REPEATED = 3
48
+ end
49
+
50
+ optional :name, :string, 1
51
+ optional :number, :int32, 3
52
+ optional :label, Label, 4
53
+
54
+ ## If type_name is set, this need not be set. If both this and type_name
55
+ ## are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
56
+ optional :type, Type, 5
57
+
58
+ ## For message and enum types, this is the name of the type. If the name
59
+ ## starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
60
+ ## rules are used to find the type (i.e. first the nested types within this
61
+ ## message are searched, then within the parent, on up to the root
62
+ ## namespace).
63
+ optional :type_name, :string, 6
64
+
65
+ ## For extensions, this is the name of the type being extended. It is
66
+ ## resolved in the same manner as type_name.
67
+ optional :extended, :string, 2
68
+
69
+ ## For numeric types, contains the original text representation of the value.
70
+ ## For booleans, "true" or "false".
71
+ ## For strings, contains the default text contents (not escaped in any way).
72
+ ## For bytes, contains the C escaped value. All bytes >= 128 are escaped.
73
+ optional :default_value, :string, 7
74
+ end
75
+
76
+
77
+ class EnumValueDescriptorProto
78
+ include Beefcake::Message
79
+
80
+ optional :name, :string, 1
81
+ optional :number, :int32, 2
82
+ # optional EnumValueOptions options = 3;
83
+ end
84
+
85
+ class EnumDescriptorProto
86
+ include Beefcake::Message
87
+
88
+ optional :name, :string, 1
89
+ repeated :value, EnumValueDescriptorProto, 2
90
+ # optional :options, EnumOptions, 3
91
+ end
92
+
93
+ class DescriptorProto
94
+ include Beefcake::Message
95
+
96
+ optional :name, :string, 1
97
+
98
+ repeated :field, FieldDescriptorProto, 2
99
+ repeated :extended, FieldDescriptorProto, 6
100
+ repeated :nested_type, DescriptorProto, 3
101
+ repeated :enum_type, EnumDescriptorProto, 4
102
+ end
103
+
104
+
105
+ class FileDescriptorProto
106
+ include Beefcake::Message
107
+
108
+ optional :name, :string, 1 # file name, relative to root of source tree
109
+ optional :package, :string, 2 # e.g. "foo", "foo.bar", etc.
110
+
111
+ repeated :message_type, DescriptorProto, 4;
112
+ end
113
+
114
+
115
+ repeated :file_to_generate, :string, 1
116
+ optional :parameter, :string, 2
117
+
118
+ repeated :proto_file, FileDescriptorProto, 15
119
+ end
120
+
121
+ class CodeGeneratorResponse
122
+ include Beefcake::Message
123
+
124
+ class File
125
+ include Beefcake::Message
126
+
127
+ optional :name, :string, 1
128
+ optional :content, :string, 15
129
+ end
130
+
131
+ repeated :file, File, 15
132
+ end
133
+
134
+
135
+ module Beefcake
136
+ class Generator < Struct.new(:c)
137
+
138
+ L = CodeGeneratorRequest::FieldDescriptorProto::Label
139
+ T = CodeGeneratorRequest::FieldDescriptorProto::Type
140
+
141
+
142
+ def self.compile(ns, req)
143
+ file = req.proto_file.map do |file|
144
+ g = new(StringIO.new)
145
+ g.compile(ns, file)
146
+
147
+ g.c.rewind
148
+ CodeGeneratorResponse::File.new(
149
+ :name => File.basename(file.name, ".proto") + ".pb.rb",
150
+ :content => g.c.read
151
+ )
152
+ end
153
+
154
+ CodeGeneratorResponse.new(:file => file)
155
+ end
156
+
157
+ def file!(file)
158
+ c.puts "## Generated from #{file.name} for #{file.package}"
159
+
160
+ file.message_type.each do |mt|
161
+ message!(mt)
162
+ end
163
+ end
164
+
165
+ def message!(pkg, mt)
166
+ c.puts
167
+ c.puts "class #{mt.name}"
168
+ c.puts " include Beefcake::Message"
169
+ c.puts
170
+
171
+ mt.enum_type.each do |et|
172
+ enum!(et)
173
+ end
174
+
175
+ ## Generate Types
176
+ (mt.nested_type || []).each do |nt|
177
+ message!(nt)
178
+ end
179
+ c.puts
180
+
181
+ ## Generate fields
182
+ (mt.field || []).each do |f|
183
+ field!(pkg, f)
184
+ end
185
+ c.puts
186
+
187
+ c.puts "end"
188
+ end
189
+
190
+ def enum!(et)
191
+ c.puts " module #{et.name}"
192
+ et.value.each do |v|
193
+ c.puts " %s = %d" % [v.name, v.number]
194
+ end
195
+ c.puts " end"
196
+ end
197
+
198
+ def field!(pkg, f)
199
+ # Turn the label into Ruby
200
+ label = name_for(f, L, f.label)
201
+
202
+ # Turn the name into a Ruby
203
+ name = ":#{f.name}"
204
+
205
+ # Determine the type-name and convert to Ruby
206
+ type = if f.type_name
207
+ # We have a type_name so we will use it after converting to a
208
+ # Ruby friendly version
209
+ t = f.type_name
210
+ t = t.gsub(pkg, "") # Remove the leading package name
211
+ t = t.gsub(/^\.*/, "") # Remove leading `.`s
212
+
213
+ t.gsub(".", "::") # Convert to Ruby namespacing syntax
214
+ else
215
+ ":#{name_for(f, T, f.type)}"
216
+ end
217
+
218
+ # Finally, generate the declaration
219
+ c.print " %s %s, %s, %d" % [label, name, type, f.number]
220
+
221
+ if f.default_value
222
+ c.print ", :default => #{f.default_value}"
223
+ end
224
+
225
+ c.puts
226
+ end
227
+
228
+ # Determines the name for a
229
+ def name_for(b, mod, val)
230
+ b.name_for(mod, val).gsub(/.*_/, "").downcase
231
+ end
232
+
233
+ def compile(ns, file)
234
+ c.puts "## Generated from #{file.name} for #{file.package}"
235
+
236
+ ns.each do |name|
237
+ c.puts "module #{name}"
238
+ end
239
+
240
+ file.message_type.each do |mt|
241
+ message!(file.package, mt)
242
+ end
243
+
244
+ ns.each do |name|
245
+ c.puts "end"
246
+ end
247
+ end
248
+
249
+ end
250
+ end
251
+
252
+ ns = (ENV["BEEFCAKE_NAMESPACE"] || "").split("::")
253
+
254
+ req = CodeGeneratorRequest.decode(STDIN.read)
255
+ res = Beefcake::Generator.compile(ns, req)
256
+
257
+ # Send it out!
258
+ STDOUT.print(res.encode)
@@ -84,7 +84,10 @@ module Beefcake
84
84
  end
85
85
 
86
86
  def encode!(buf, fld, fn)
87
- Array(self[fld.name]).each do |val|
87
+ v = self[fld.name]
88
+ v = v.is_a?(Array) ? v : [v]
89
+
90
+ v.compact.each do |val|
88
91
  case fld.type
89
92
  when Class # encodable
90
93
  # TODO: raise error if type != val.class
@@ -208,6 +211,7 @@ module Beefcake
208
211
  end
209
212
 
210
213
  def ==(o)
214
+ return false if o == nil
211
215
  fields.values.all? {|fld| self[fld.name] == o[fld.name] }
212
216
  end
213
217
 
@@ -218,6 +222,8 @@ module Beefcake
218
222
  val = self[fld.name]
219
223
 
220
224
  case fld.type
225
+ when Class
226
+ "#{fld.name}: #{val.inspect}"
221
227
  when Module
222
228
  title = name_for(fld.type, val) || "-NA-"
223
229
  "#{fld.name}: #{title}(#{val.inspect})"
@@ -120,11 +120,11 @@ class MessageTest < Test::Unit::TestCase
120
120
  def test_encode_strings
121
121
  buf = Beefcake::Buffer.new
122
122
 
123
- buf.append(:string, "testing", 1)
123
+ buf.append(:string, "test\ning", 1)
124
124
  buf.append(:bytes, "unixisawesome", 2)
125
125
 
126
126
  msg = LendelsMessage.new({
127
- :string => "testing",
127
+ :string => "test\ning",
128
128
  :bytes => "unixisawesome"
129
129
  })
130
130
 
@@ -325,6 +325,11 @@ class MessageTest < Test::Unit::TestCase
325
325
  assert_equal "<EnumsMessage a: -NA-(2)>", msg.inspect
326
326
  end
327
327
 
328
+ def test_inspect_nested_types
329
+ msg = CompositeMessage.new(:encodable => SimpleMessage.new(:a => 1))
330
+ assert_equal "<CompositeMessage encodable: <SimpleMessage a: 1>>", msg.inspect
331
+ end
332
+
328
333
  def test_to_hash
329
334
  msg = SimpleMessage.new :a => 1
330
335
  exp = { :a => 1 }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beefcake
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 1
10
- version: 0.2.1
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Blake Mizerany
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-15 00:00:00 -08:00
18
+ date: 2011-03-22 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -34,8 +34,8 @@ dependencies:
34
34
  version_requirements: *id001
35
35
  description: A sane protobuf library for Ruby
36
36
  email:
37
- executables: []
38
-
37
+ executables:
38
+ - protoc-gen-beefcake
39
39
  extensions: []
40
40
 
41
41
  extra_rdoc_files:
@@ -53,6 +53,7 @@ files:
53
53
  - test/buffer_encode_test.rb
54
54
  - test/buffer_test.rb
55
55
  - test/message_test.rb
56
+ - bin/protoc-gen-beefcake
56
57
  has_rdoc: true
57
58
  homepage: http://github.com/bmizerany/beefcake
58
59
  licenses: []