beefcake-spanx 0.3.4.1

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