beefcake-spanx 0.3.4.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.
@@ -0,0 +1,2 @@
1
+ require 'beefcake/buffer/encode'
2
+ require 'beefcake/buffer/decode'
@@ -0,0 +1,98 @@
1
+ module Beefcake
2
+
3
+ class Buffer
4
+
5
+ MinUint32 = 0
6
+ MaxUint32 = (1<<32)-1
7
+ MinInt32 = -(1<<31)
8
+ MaxInt32 = (1<<31)-1
9
+
10
+ MinUint64 = 0
11
+ MaxUint64 = (1<<64)-1
12
+ MinInt64 = -(1<<63)
13
+ MaxInt64 = (1<<63)-1
14
+
15
+ def self.wire_for(type)
16
+ case type
17
+ when Class
18
+ if encodable?(type)
19
+ 2
20
+ else
21
+ raise UnknownType, type
22
+ end
23
+ when :int32, :uint32, :sint32, :int64, :uint64, :sint64, :bool, Module
24
+ 0
25
+ when :fixed64, :sfixed64, :double
26
+ 1
27
+ when :string, :bytes
28
+ 2
29
+ when :fixed32, :sfixed32, :float
30
+ 5
31
+ else
32
+ raise UnknownType, type
33
+ end
34
+ end
35
+
36
+ def self.encodable?(type)
37
+ return false if ! type.is_a?(Class)
38
+ pims = type.public_instance_methods
39
+ pims.include?(:encode) || pims.include?("encode")
40
+ end
41
+
42
+ attr_accessor :buf
43
+
44
+ alias :to_s :buf
45
+ alias :to_str :buf
46
+
47
+ class OutOfRangeError < StandardError
48
+ def initialize(n)
49
+ super("Value of of range: %d" % [n])
50
+ end
51
+ end
52
+
53
+ class BufferOverflowError < StandardError
54
+ def initialize(s)
55
+ super("Too many bytes read for %s" % [s])
56
+ end
57
+ end
58
+
59
+ class UnknownType < StandardError
60
+ def initialize(s)
61
+ super("Unknown type '%s'" % [s])
62
+ end
63
+ end
64
+
65
+ def initialize(buf="")
66
+ self.buf = buf
67
+ end
68
+
69
+ if ''.respond_to?(:force_encoding)
70
+ def buf=(buf)
71
+ @buf = buf.force_encoding('BINARY')
72
+ end
73
+ end
74
+
75
+ def length
76
+ @buf.respond_to?(:bytesize) ? @buf.bytesize : @buf.length
77
+ end
78
+
79
+ def <<(bytes)
80
+ buf << bytes
81
+ end
82
+
83
+ def read(n)
84
+ case n
85
+ when Class
86
+ n.decode(read_string)
87
+ when Symbol
88
+ __send__("read_#{n}")
89
+ when Module
90
+ read_uint64
91
+ else
92
+ buf.slice!(0, n)
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,107 @@
1
+ require 'beefcake/buffer/base'
2
+
3
+ module Beefcake
4
+
5
+ class Buffer
6
+
7
+ def read_info
8
+ n = read_uint64
9
+ fn = n >> 3
10
+ wire = n & 0x7
11
+
12
+ [fn, wire]
13
+ end
14
+
15
+ def read_string
16
+ read(read_uint64)
17
+ end
18
+ alias :read_bytes :read_string
19
+
20
+ def read_fixed32
21
+ bytes = read(4)
22
+ bytes.unpack("V").first
23
+ end
24
+
25
+ def read_fixed64
26
+ bytes = read(8)
27
+ x, y = bytes.unpack("VV")
28
+ x + (y << 32)
29
+ end
30
+
31
+ def read_int64
32
+ n = read_uint64
33
+ if n > MaxInt64
34
+ n -= (1 << 64)
35
+ end
36
+ n
37
+ end
38
+ alias :read_int32 :read_int64
39
+
40
+ def read_uint64
41
+ n = shift = 0
42
+ while true
43
+ if shift >= 64
44
+ raise BufferOverflowError, "varint"
45
+ end
46
+ b = buf.slice!(0)
47
+
48
+ ## 1.8.6 to 1.9 Compat
49
+ if b.respond_to?(:ord)
50
+ b = b.ord
51
+ end
52
+
53
+ n |= ((b & 0x7F) << shift)
54
+ shift += 7
55
+ if (b & 0x80) == 0
56
+ return n
57
+ end
58
+ end
59
+ end
60
+ alias :read_uint32 :read_uint64
61
+
62
+ def read_sint64
63
+ decode_zigzag(read_uint64)
64
+ end
65
+ alias :read_sint32 :read_sint64
66
+
67
+ def read_sfixed32
68
+ decode_zigzag(read_fixed32)
69
+ end
70
+
71
+ def read_sfixed64
72
+ decode_zigzag(read_fixed64)
73
+ end
74
+
75
+ def read_float
76
+ bytes = read(4)
77
+ bytes.unpack("e").first
78
+ end
79
+
80
+ def read_double
81
+ bytes = read(8)
82
+ bytes.unpack("E").first
83
+ end
84
+
85
+ def read_bool
86
+ read_int32 != 0
87
+ end
88
+
89
+ def skip(wire)
90
+ case wire
91
+ when 0 then read_uint64
92
+ when 1 then read_fixed64
93
+ when 2 then read_string
94
+ when 5 then read_fixed32
95
+ end
96
+ end
97
+
98
+
99
+ private
100
+
101
+ def decode_zigzag(n)
102
+ (n >> 1) ^ -(n & 1)
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,116 @@
1
+ require 'beefcake/buffer/base'
2
+
3
+ module Beefcake
4
+
5
+ class Buffer
6
+
7
+ def append(type, val, fn)
8
+ if fn != 0
9
+ wire = Buffer.wire_for(type)
10
+ append_info(fn, wire)
11
+ end
12
+
13
+ __send__("append_#{type}", val)
14
+ end
15
+
16
+ def append_info(fn, wire)
17
+ #self << ((fn << 3) | wire)
18
+ append_uint32((fn << 3) | wire)
19
+ end
20
+
21
+ def append_fixed32(n, tag=false)
22
+ if n < MinUint32 || n > MaxUint32
23
+ raise OutOfRangeError, n
24
+ end
25
+
26
+ self << [n].pack("V")
27
+ end
28
+
29
+ def append_fixed64(n)
30
+ if n < MinUint64 || n > MaxUint64
31
+ raise OutOfRangeError, n
32
+ end
33
+
34
+ self << [n & 0xFFFFFFFF, n >> 32].pack("VV")
35
+ end
36
+
37
+ def append_int32(n)
38
+ if n < MinInt32 || n > MaxInt32
39
+ raise OutOfRangeError, n
40
+ end
41
+
42
+ append_int64(n)
43
+ end
44
+
45
+ def append_uint32(n)
46
+ if n < MinUint32 || n > MaxUint32
47
+ raise OutOfRangeError, n
48
+ end
49
+
50
+ append_uint64(n)
51
+ end
52
+
53
+ def append_int64(n)
54
+ if n < MinInt64 || n > MaxInt64
55
+ raise OutOfRangeError, n
56
+ end
57
+
58
+ if n < 0
59
+ n += (1 << 64)
60
+ end
61
+
62
+ append_uint64(n)
63
+ end
64
+
65
+ def append_sint32(n)
66
+ append_uint32((n << 1) ^ (n >> 31))
67
+ end
68
+
69
+ def append_sfixed32(n)
70
+ append_fixed32((n << 1) ^ (n >> 31))
71
+ end
72
+
73
+ def append_sint64(n)
74
+ append_uint64((n << 1) ^ (n >> 63))
75
+ end
76
+
77
+ def append_sfixed64(n)
78
+ append_fixed64((n << 1) ^ (n >> 63))
79
+ end
80
+
81
+ def append_uint64(n)
82
+ if n < MinUint64 || n > MaxUint64
83
+ raise OutOfRangeError, n
84
+ end
85
+
86
+ while true
87
+ bits = n & 0x7F
88
+ n >>= 7
89
+ if n == 0
90
+ return self << bits
91
+ end
92
+ self << (bits | 0x80)
93
+ end
94
+ end
95
+
96
+ def append_float(n)
97
+ self << [n].pack("e")
98
+ end
99
+
100
+ def append_double(n)
101
+ self << [n].pack("E")
102
+ end
103
+
104
+ def append_bool(n)
105
+ append_int64(n ? 1 : 0)
106
+ end
107
+
108
+ def append_string(s)
109
+ append_uint64(s.length)
110
+ self << s
111
+ end
112
+ alias :append_bytes :append_string
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,288 @@
1
+ # encoding: ASCII-8BIT
2
+ # The above line allows concatenation of constant strings like ".pb.rb" to
3
+ # maintain the internal format of the buffers, rather than converting the
4
+ # buffer to US-ASCII
5
+
6
+ require 'beefcake'
7
+ require 'stringio'
8
+
9
+ class CodeGeneratorRequest
10
+ include Beefcake::Message
11
+
12
+
13
+ class FieldDescriptorProto
14
+ include Beefcake::Message
15
+
16
+ module Type
17
+ ## 0 is reserved for errors.
18
+ ## Order is weird for historical reasons.
19
+ TYPE_DOUBLE = 1
20
+ TYPE_FLOAT = 2
21
+ TYPE_INT64 = 3 ## Not ZigZag encoded. Negative numbers
22
+ ## take 10 bytes. Use TYPE_SINT64 if negative
23
+ ## values are likely.
24
+ TYPE_UINT64 = 4
25
+ TYPE_INT32 = 5 ## Not ZigZag encoded. Negative numbers
26
+ ## take 10 bytes. Use TYPE_SINT32 if negative
27
+ ## values are likely.
28
+ TYPE_FIXED64 = 6
29
+ TYPE_FIXED32 = 7
30
+ TYPE_BOOL = 8
31
+ TYPE_STRING = 9
32
+ TYPE_GROUP = 10 ## Tag-delimited aggregate.
33
+ TYPE_MESSAGE = 11 ## Length-delimited aggregate.
34
+
35
+ ## New in version 2.
36
+ TYPE_BYTES = 12
37
+ TYPE_UINT32 = 13
38
+ TYPE_ENUM = 14
39
+ TYPE_SFIXED32 = 15
40
+ TYPE_SFIXED64 = 16
41
+ TYPE_SINT32 = 17 ## Uses ZigZag encoding.
42
+ TYPE_SINT64 = 18 ## Uses ZigZag encoding.
43
+ end
44
+
45
+ module Label
46
+ LABEL_OPTIONAL = 1
47
+ LABEL_REQUIRED = 2
48
+ LABEL_REPEATED = 3
49
+ end
50
+
51
+ optional :name, :string, 1
52
+ optional :number, :int32, 3
53
+ optional :label, Label, 4
54
+
55
+ ## If type_name is set, this need not be set. If both this and type_name
56
+ ## are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
57
+ optional :type, Type, 5
58
+
59
+ ## For message and enum types, this is the name of the type. If the name
60
+ ## starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
61
+ ## rules are used to find the type (i.e. first the nested types within this
62
+ ## message are searched, then within the parent, on up to the root
63
+ ## namespace).
64
+ optional :type_name, :string, 6
65
+
66
+ ## For extensions, this is the name of the type being extended. It is
67
+ ## resolved in the same manner as type_name.
68
+ optional :extended, :string, 2
69
+
70
+ ## For numeric types, contains the original text representation of the value.
71
+ ## For booleans, "true" or "false".
72
+ ## For strings, contains the default text contents (not escaped in any way).
73
+ ## For bytes, contains the C escaped value. All bytes >= 128 are escaped.
74
+ optional :default_value, :string, 7
75
+ end
76
+
77
+
78
+ class EnumValueDescriptorProto
79
+ include Beefcake::Message
80
+
81
+ optional :name, :string, 1
82
+ optional :number, :int32, 2
83
+ # optional EnumValueOptions options = 3;
84
+ end
85
+
86
+ class EnumDescriptorProto
87
+ include Beefcake::Message
88
+
89
+ optional :name, :string, 1
90
+ repeated :value, EnumValueDescriptorProto, 2
91
+ # optional :options, EnumOptions, 3
92
+ end
93
+
94
+ class DescriptorProto
95
+ include Beefcake::Message
96
+
97
+ optional :name, :string, 1
98
+
99
+ repeated :field, FieldDescriptorProto, 2
100
+ repeated :extended, FieldDescriptorProto, 6
101
+ repeated :nested_type, DescriptorProto, 3
102
+ repeated :enum_type, EnumDescriptorProto, 4
103
+ end
104
+
105
+
106
+ class FileDescriptorProto
107
+ include Beefcake::Message
108
+
109
+ optional :name, :string, 1 # file name, relative to root of source tree
110
+ optional :package, :string, 2 # e.g. "foo", "foo.bar", etc.
111
+
112
+ repeated :message_type, DescriptorProto, 4;
113
+ end
114
+
115
+
116
+ repeated :file_to_generate, :string, 1
117
+ optional :parameter, :string, 2
118
+
119
+ repeated :proto_file, FileDescriptorProto, 15
120
+ end
121
+
122
+ class CodeGeneratorResponse
123
+ include Beefcake::Message
124
+
125
+ class File
126
+ include Beefcake::Message
127
+
128
+ optional :name, :string, 1
129
+ optional :content, :string, 15
130
+ end
131
+
132
+ repeated :file, File, 15
133
+ end
134
+
135
+ module Beefcake
136
+ class Generator
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
+ attr_reader :c
158
+
159
+ def initialize(c)
160
+ @c = c
161
+ @n = 0
162
+ end
163
+
164
+ def file!(file)
165
+ puts "## Generated from #{file.name} for #{file.package}"
166
+
167
+ file.message_type.each do |mt|
168
+ message!("", mt)
169
+ end
170
+ end
171
+
172
+ def indent(&blk)
173
+ @n += 1
174
+ blk.call
175
+ @n -= 1
176
+ end
177
+
178
+ def indent!(n)
179
+ @n = n
180
+ end
181
+
182
+ def message!(pkg, mt)
183
+ puts
184
+ puts "class #{mt.name}"
185
+
186
+ indent do
187
+ puts "include Beefcake::Message"
188
+ puts
189
+
190
+ Array(mt.enum_type).each do |et|
191
+ enum!(et)
192
+ end
193
+
194
+ ## Generate Types
195
+ Array(mt.nested_type).each do |nt|
196
+ message!(pkg, nt)
197
+ end
198
+ puts
199
+
200
+ ## Generate fields
201
+ Array(mt.field).each do |f|
202
+ field!(pkg, f)
203
+ end
204
+ puts
205
+ end
206
+
207
+ puts "end"
208
+ end
209
+
210
+ def enum!(et)
211
+ puts "module #{et.name}"
212
+ indent do
213
+ et.value.each do |v|
214
+ puts "%s = %d" % [v.name, v.number]
215
+ end
216
+ end
217
+ puts "end"
218
+ end
219
+
220
+ def field!(pkg, f)
221
+ # Turn the label into Ruby
222
+ label = name_for(f, L, f.label)
223
+
224
+ # Turn the name into a Ruby
225
+ name = ":#{f.name}"
226
+
227
+ # Determine the type-name and convert to Ruby
228
+ type = if f.type_name
229
+ # We have a type_name so we will use it after converting to a
230
+ # Ruby friendly version
231
+ t = f.type_name
232
+ t = t.gsub(pkg, "") # Remove the leading package name
233
+ t = t.gsub(/^\.*/, "") # Remove leading `.`s
234
+
235
+ t.gsub(".", "::") # Convert to Ruby namespacing syntax
236
+ else
237
+ ":#{name_for(f, T, f.type)}"
238
+ end
239
+
240
+ # Finally, generate the declaration
241
+ out = "%s %s, %s, %d" % [label, name, type, f.number]
242
+
243
+ if f.default_value
244
+ out += ", :default => #{f.default_value}"
245
+ end
246
+
247
+ puts out
248
+ end
249
+
250
+ # Determines the name for a
251
+ def name_for(b, mod, val)
252
+ b.name_for(mod, val).to_s.gsub(/.*_/, "").downcase
253
+ end
254
+
255
+ def compile(ns, file)
256
+ puts "## Generated from #{file.name} for #{file.package}"
257
+ puts "require \"beefcake\""
258
+ puts
259
+
260
+ ns!(ns) do
261
+ file.message_type.each do |mt|
262
+ message!(file.package, mt)
263
+ end
264
+ end
265
+ end
266
+
267
+ def ns!(modules, &blk)
268
+ if modules.empty?
269
+ blk.call
270
+ else
271
+ puts "module #{modules.first}"
272
+ indent do
273
+ ns!(modules[1..-1], &blk)
274
+ end
275
+ puts "end"
276
+ end
277
+ end
278
+
279
+ def puts(msg=nil)
280
+ if msg
281
+ c.puts((" " * @n) + msg)
282
+ else
283
+ c.puts
284
+ end
285
+ end
286
+
287
+ end
288
+ end