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 +5 -16
- data/bin/protoc-gen-beefcake +258 -0
- data/lib/beefcake.rb +7 -1
- data/test/message_test.rb +7 -2
- metadata +8 -7
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
|
-
#
|
70
|
+
# Generate code from `.proto` file
|
71
71
|
|
72
|
-
|
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
|
-
|
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
|
-
|
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)
|
data/lib/beefcake.rb
CHANGED
@@ -84,7 +84,10 @@ module Beefcake
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def encode!(buf, fld, fn)
|
87
|
-
|
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})"
|
data/test/message_test.rb
CHANGED
@@ -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, "
|
123
|
+
buf.append(:string, "test\ning", 1)
|
124
124
|
buf.append(:bytes, "unixisawesome", 2)
|
125
125
|
|
126
126
|
msg = LendelsMessage.new({
|
127
|
-
:string => "
|
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:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
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-
|
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: []
|