boss-protocol 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +21 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +77 -0
- data/Rakefile +1 -0
- data/boss-protocol.gemspec +23 -0
- data/lib/boss-protocol/version.rb +3 -0
- data/lib/boss-protocol.rb +471 -0
- data/spec/boss_spec.rb +467 -0
- data/spec/spec_helper.rb +17 -0
- metadata +92 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008-2012 sergeych
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Boss Protocol
|
2
|
+
|
3
|
+
BOSS is acronym for Binary Object Streamable Storage.
|
4
|
+
|
5
|
+
The very space-effective, platfomr-independent streamable and traversable typed binary protocol.
|
6
|
+
Allow to effectively store small or
|
7
|
+
any
|
8
|
+
sized
|
9
|
+
integers, strings or binary data of any size, floats and doubles, arrays and hashes in a very effective way. It caches
|
10
|
+
repeating objects and stores/restores links to objects.
|
11
|
+
|
12
|
+
Streamable means that you can use a pipe (tcp/ip, wahtever), put the object at one side and load it on other, one-by-one,
|
13
|
+
and caching and links will be restored properly.
|
14
|
+
|
15
|
+
Initially, this protocol was intended to be used in secure communications. Its
|
16
|
+
main goal was to very effective data sending and is a great replacement for json/boss/whatever. For example, typical
|
17
|
+
JSON reduces in size twice with Boss.
|
18
|
+
|
19
|
+
Boss protocol also allow to transparently compress its representations.
|
20
|
+
|
21
|
+
*Attention* ruby version is under final development, its streaming support may not work as expected, while the rest
|
22
|
+
seem to work just fine.
|
23
|
+
|
24
|
+
There are versions in C and Python that are in most part ready.
|
25
|
+
|
26
|
+
## Installation
|
27
|
+
|
28
|
+
Add this line to your application's Gemfile:
|
29
|
+
|
30
|
+
gem 'boss-protocol'
|
31
|
+
|
32
|
+
And then execute:
|
33
|
+
|
34
|
+
$ bundle
|
35
|
+
|
36
|
+
Or install it yourself as:
|
37
|
+
|
38
|
+
$ gem install boss-protocol
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
1.9.3-p327 :011 > require 'boss-protocol'
|
43
|
+
=> false
|
44
|
+
1.9.3-p327 :012 > data = { 'test' => [1, 2, -1.22, 'great!'] }
|
45
|
+
=> {"test"=>[1, 2, -1.22, "great!"]}
|
46
|
+
1.9.3-p327 :013 > x = Boss.dump data
|
47
|
+
=> "\x0F#test&\b\x109\x85\xEBQ\xB8\x1E\x85\xF3\xBF3great!"
|
48
|
+
1.9.3-p327 :014 > Marshal.dump data
|
49
|
+
=> "\x04\b{\x06I\"\ttest\x06:\x06ET[\ti\x06i\af\n-1.22I\"\vgreat!\x06;\x00T"
|
50
|
+
|
51
|
+
Note that boss representation is smaller than ruby's Marshal one
|
52
|
+
|
53
|
+
1.9.3-p327 :015 > Boss.load(x) == data
|
54
|
+
=> true
|
55
|
+
|
56
|
+
To use the transparent compression:
|
57
|
+
|
58
|
+
1.9.3-p327 :013 > data = "Boss is a very effective protocol!" * 4096; nil
|
59
|
+
=> nil
|
60
|
+
1.9.3-p327 :014 > data.length
|
61
|
+
=> 139264
|
62
|
+
1.9.3-p327 :015 > x = Boss.dump_compressed(data); nil
|
63
|
+
=> nil
|
64
|
+
1.9.3-p327 :016 > x.length
|
65
|
+
=> 147
|
66
|
+
1.9.3-p327 :017 > data == Boss.load(x)
|
67
|
+
=> true
|
68
|
+
|
69
|
+
Streaming docs are in progress. Please wait.
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
1. Fork it
|
74
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
75
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
76
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
77
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'boss-protocol/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "boss-protocol"
|
8
|
+
gem.version = Boss::VERSION
|
9
|
+
gem.authors = ["sergeych"]
|
10
|
+
gem.email = ["real.sergeych@gmail.com"]
|
11
|
+
gem.description = %q{Binary streamable bit-effective protocol to effectively store object tree hierarchies}
|
12
|
+
gem.summary = %q{Traversable and streamable to some extend protocol supports lists, hashes, caching,
|
13
|
+
compression and more}
|
14
|
+
gem.homepage = ""
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_dependency 'bzip2-ruby'
|
22
|
+
gem.add_development_dependency "rspec"
|
23
|
+
end
|
@@ -0,0 +1,471 @@
|
|
1
|
+
require "boss-protocol/version"
|
2
|
+
|
3
|
+
# Encoding: utf-8
|
4
|
+
require 'stringio'
|
5
|
+
require 'zlib'
|
6
|
+
require 'bzip2'
|
7
|
+
|
8
|
+
# Copyright (c) 2008-2012 by sergeych (real.sergeych@gmail.com)
|
9
|
+
#
|
10
|
+
# MIT License
|
11
|
+
#
|
12
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
13
|
+
# a copy of this software and associated documentation files (the
|
14
|
+
# "Software"), to deal in the Software without restriction, including
|
15
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
16
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
17
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
18
|
+
# the following conditions:
|
19
|
+
#
|
20
|
+
# The above copyright notice and this permission notice shall be
|
21
|
+
# included in all copies or substantial portions of the Software.
|
22
|
+
#
|
23
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
24
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
25
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
26
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
27
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
28
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
29
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.#
|
30
|
+
#
|
31
|
+
# sergey.chernov@thrift.ru
|
32
|
+
#
|
33
|
+
|
34
|
+
##
|
35
|
+
# Boss protocol version 1.2 basic implementation
|
36
|
+
#
|
37
|
+
# 1.2 version adds support for booelans and removes support for python __reduce__ - based objects
|
38
|
+
# as absolutely non portable. It also introduces
|
39
|
+
#
|
40
|
+
# 1.1 version changes the way to store bignums in header, now it is
|
41
|
+
# encoded <bytes_length> followed by the specified number of bytes
|
42
|
+
# LSB first
|
43
|
+
#
|
44
|
+
# No object serialization yet, no callables and bound methods - these appear to be
|
45
|
+
# non portable between platoforms.
|
46
|
+
#
|
47
|
+
module Boss
|
48
|
+
# Basic types
|
49
|
+
TYPE_INT = 0
|
50
|
+
TYPE_EXTRA = 1
|
51
|
+
TYPE_NINT = 2
|
52
|
+
|
53
|
+
TYPE_TEXT = 3
|
54
|
+
TYPE_BIN = 4
|
55
|
+
TYPE_CREF = 5
|
56
|
+
TYPE_LIST = 6
|
57
|
+
TYPE_DICT = 7
|
58
|
+
|
59
|
+
# Extra types:
|
60
|
+
|
61
|
+
DZERO = 0 #: float 0.0
|
62
|
+
FZERO = 1 #: double 0.0
|
63
|
+
|
64
|
+
DONE = 2 #: double 1.0
|
65
|
+
FONE = 3 #: float 1.0
|
66
|
+
DMINUSONE = 4 #: double -1.0
|
67
|
+
FMINUSONE = 5 #: float -1.0
|
68
|
+
|
69
|
+
TFLOAT = 6 #: 32-bit IEEE float
|
70
|
+
TDOUBLE = 7 #: 64-bit IEEE float
|
71
|
+
|
72
|
+
TOBJECT = 8 #: object record
|
73
|
+
TMETHOD = 9 #: instance method
|
74
|
+
TFUNCTION = 10 #: callable function
|
75
|
+
TGLOBREF = 11 #: global reference
|
76
|
+
|
77
|
+
TTRUE = 12
|
78
|
+
TFALSE = 13
|
79
|
+
|
80
|
+
TCOMPRESSED = 14
|
81
|
+
|
82
|
+
def checkArg(cond, msg=nil)
|
83
|
+
raise ArgumentError unless cond
|
84
|
+
end
|
85
|
+
|
86
|
+
class UnknownTypeException < Exception;
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Formats ruby object hierarchies with BOSS
|
91
|
+
# notation
|
92
|
+
#
|
93
|
+
class Formatter
|
94
|
+
|
95
|
+
include Boss # for checkArg
|
96
|
+
|
97
|
+
##
|
98
|
+
# Construct formatter for a given IO-like object
|
99
|
+
# or create StringIO one as output
|
100
|
+
#
|
101
|
+
def initialize(dst=nil)
|
102
|
+
@io = dst ? dst : StringIO.new('', 'wb')
|
103
|
+
@io.set_encoding 'binary'
|
104
|
+
@cache = { nil => 0 }
|
105
|
+
end
|
106
|
+
|
107
|
+
def put_compressed ob
|
108
|
+
data = Boss.dump(ob)
|
109
|
+
whdr TYPE_EXTRA, TCOMPRESSED
|
110
|
+
type = case data.length
|
111
|
+
when 0..160
|
112
|
+
0
|
113
|
+
when 161..8192
|
114
|
+
data = Zlib::Deflate.new.deflate(data, Zlib::FINISH)
|
115
|
+
1
|
116
|
+
else
|
117
|
+
data = Bzip2.compress data
|
118
|
+
2
|
119
|
+
end
|
120
|
+
whdr type, data.length
|
121
|
+
wbin data
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Put object tree routed as ob to the output.
|
126
|
+
# Alias: <<. It is possible to put more than one
|
127
|
+
# object to the same Formatter. Not that formatter
|
128
|
+
# has per-instance cache so put(x) put(x) put(x)
|
129
|
+
# will store one object and 2 more refs to it, so
|
130
|
+
# on load time only one object will be constructed and
|
131
|
+
# 2 more refs will be creted.
|
132
|
+
def put(ob)
|
133
|
+
case ob
|
134
|
+
when Fixnum, Bignum
|
135
|
+
if ob < 0
|
136
|
+
whdr TYPE_NINT, -ob
|
137
|
+
else
|
138
|
+
whdr TYPE_INT, ob
|
139
|
+
end
|
140
|
+
when String, Symbol
|
141
|
+
ob = ob.to_s unless ob.is_a?(String)
|
142
|
+
if notCached(ob)
|
143
|
+
if ob.encoding == Encoding::BINARY
|
144
|
+
whdr TYPE_BIN, ob.length
|
145
|
+
wbin ob
|
146
|
+
else
|
147
|
+
whdr TYPE_TEXT, ob.bytesize
|
148
|
+
wbin ob.dup.encode(Encoding::UTF_8)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
when Array
|
152
|
+
if notCached(ob)
|
153
|
+
whdr TYPE_LIST, ob.length
|
154
|
+
ob.each { |x| put(x) }
|
155
|
+
end
|
156
|
+
when Hash
|
157
|
+
if notCached(ob)
|
158
|
+
whdr TYPE_DICT, ob.length
|
159
|
+
ob.each { |k, v| self << k << v }
|
160
|
+
end
|
161
|
+
when Float
|
162
|
+
case ob
|
163
|
+
when 0
|
164
|
+
whdr TYPE_EXTRA, DZERO
|
165
|
+
when -1.0
|
166
|
+
whdr TYPE_EXTRA, DMINUSONE
|
167
|
+
when +1.0
|
168
|
+
whdr TYPE_EXTRA, DONE
|
169
|
+
else
|
170
|
+
whdr TYPE_EXTRA, TDOUBLE
|
171
|
+
wdouble ob
|
172
|
+
end
|
173
|
+
when TrueClass, FalseClass
|
174
|
+
whdr TYPE_EXTRA, ob ? TTRUE : TFALSE
|
175
|
+
when nil
|
176
|
+
whdr TYPE_CREF, 0
|
177
|
+
else
|
178
|
+
error = "error: not supported object: #{ob}, #{ob.class}"
|
179
|
+
p error
|
180
|
+
raise NotSupportedException, error
|
181
|
+
end
|
182
|
+
self
|
183
|
+
end
|
184
|
+
|
185
|
+
alias << put
|
186
|
+
|
187
|
+
##
|
188
|
+
# Get the result as string, may not work if
|
189
|
+
# some specific IO instance is passsed to constructor.
|
190
|
+
# works well with default contructor or StringIO
|
191
|
+
def string
|
192
|
+
# p "string!! #{@io.string}"
|
193
|
+
@io.string
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
##
|
199
|
+
# Write cache ref if the object is cached, and return true
|
200
|
+
# otherwise store object in the cache. Caller should
|
201
|
+
# write object to @io if notCached return true, and skip
|
202
|
+
# writing otherwise
|
203
|
+
def notCached(obj)
|
204
|
+
n = @cache[obj]
|
205
|
+
if n
|
206
|
+
whdr TYPE_CREF, n
|
207
|
+
false
|
208
|
+
else
|
209
|
+
@cache[obj] = @cache.length
|
210
|
+
true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
##
|
215
|
+
# Write variable-length positive integer
|
216
|
+
def wrenc(value)
|
217
|
+
checkArg value >= 0
|
218
|
+
while value > 0x7f
|
219
|
+
wbyte value & 0x7f
|
220
|
+
value >>= 7
|
221
|
+
end
|
222
|
+
wbyte value | 0x80
|
223
|
+
end
|
224
|
+
|
225
|
+
##
|
226
|
+
# write standard record header with code and value
|
227
|
+
#
|
228
|
+
def whdr(code, value)
|
229
|
+
checkArg code.between?(0, 7)
|
230
|
+
checkArg value >= 0
|
231
|
+
# p "WHDR #{code}, #{value}"
|
232
|
+
if value < 23
|
233
|
+
wbyte code | value<<3
|
234
|
+
else
|
235
|
+
# Get the size of the value (0..9)
|
236
|
+
if (n=sizeBytes(value)) < 9
|
237
|
+
wbyte code | (n+22) << 3
|
238
|
+
else
|
239
|
+
wbyte code | 0xF8
|
240
|
+
wrenc n
|
241
|
+
end
|
242
|
+
n.times { wbyte value & 0xff; value >>=8 }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
##
|
247
|
+
# Determine minimum amount of bytes needed to
|
248
|
+
# store value (should be positive integer)
|
249
|
+
def sizeBytes(value)
|
250
|
+
checkArg value >= 0
|
251
|
+
mval = 0x100
|
252
|
+
cnt = 1
|
253
|
+
while value >= mval
|
254
|
+
cnt += 1
|
255
|
+
mval <<= 8
|
256
|
+
end
|
257
|
+
cnt
|
258
|
+
end
|
259
|
+
|
260
|
+
##
|
261
|
+
# write binary value
|
262
|
+
#
|
263
|
+
def wbin(bb)
|
264
|
+
@io.syswrite bb
|
265
|
+
end
|
266
|
+
|
267
|
+
##
|
268
|
+
# write single byte
|
269
|
+
def wbyte(b)
|
270
|
+
@io.putc(b.chr)
|
271
|
+
end
|
272
|
+
|
273
|
+
def wdouble val
|
274
|
+
wbin [val].pack('E')
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
##
|
281
|
+
# Parser incapsulates IO-like cource and provides deserializing of
|
282
|
+
# BOSS objects. Parser can store multiple root objects and share same
|
283
|
+
# object cache for all them
|
284
|
+
class Parser
|
285
|
+
|
286
|
+
include Enumerable
|
287
|
+
|
288
|
+
##
|
289
|
+
# construct parser to read from the given string or IO-like
|
290
|
+
# object
|
291
|
+
def initialize(src=nil)
|
292
|
+
@io = src.class <= String ? StringIO.new(src) : src
|
293
|
+
@io.set_encoding Encoding::BINARY
|
294
|
+
@cache = [nil]
|
295
|
+
end
|
296
|
+
|
297
|
+
##
|
298
|
+
# Load the object (object tree) from the stream. Note that if there
|
299
|
+
# is more than one object in the stream that are stored with the same
|
300
|
+
# Formatter instance, they will share same cache and references,
|
301
|
+
# see Boss.Formatter.put for details.
|
302
|
+
# Note that nil is a valid restored object. Check eof? or catch
|
303
|
+
# EOFError, or use Boss.Parser.each to read all objects from the stream
|
304
|
+
def get
|
305
|
+
code, value = rhdr
|
306
|
+
case code
|
307
|
+
when TYPE_INT
|
308
|
+
return value
|
309
|
+
when TYPE_NINT
|
310
|
+
return -value
|
311
|
+
when TYPE_EXTRA
|
312
|
+
case value
|
313
|
+
when TTRUE
|
314
|
+
true
|
315
|
+
when TFALSE
|
316
|
+
false
|
317
|
+
when DZERO, FZERO
|
318
|
+
0
|
319
|
+
when DONE, FONE
|
320
|
+
1.0
|
321
|
+
when DMINUSONE, FMINUSONE
|
322
|
+
-1.0
|
323
|
+
when TDOUBLE
|
324
|
+
rdouble
|
325
|
+
when TCOMPRESSED
|
326
|
+
type, size = rhdr
|
327
|
+
data = rbin size
|
328
|
+
case type
|
329
|
+
when 0
|
330
|
+
Boss.load data
|
331
|
+
when 1
|
332
|
+
Boss.load Zlib::Inflate.new(Zlib::MAX_WBITS).inflate(data)
|
333
|
+
when 2
|
334
|
+
Boss.load Bzip2.uncompress data
|
335
|
+
else
|
336
|
+
raise UnknownTypeException, "type #{type}"
|
337
|
+
end
|
338
|
+
else
|
339
|
+
raise UnknownTypeException
|
340
|
+
end
|
341
|
+
when TYPE_TEXT, TYPE_BIN
|
342
|
+
s = rbin value
|
343
|
+
s.force_encoding code == TYPE_BIN ? Encoding::BINARY : Encoding::UTF_8
|
344
|
+
@cache << s
|
345
|
+
return s
|
346
|
+
when TYPE_LIST
|
347
|
+
# p "items", value
|
348
|
+
@cache << (list = [])
|
349
|
+
value.times { list << get }
|
350
|
+
return list
|
351
|
+
when TYPE_DICT
|
352
|
+
@cache << (dict = { })
|
353
|
+
value.times { dict[get] = get }
|
354
|
+
return dict
|
355
|
+
when TYPE_CREF
|
356
|
+
return @cache[value]
|
357
|
+
else
|
358
|
+
raise UnknownTypeException
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
##
|
363
|
+
# True is underlying IO-like object reached its end.
|
364
|
+
def eof?
|
365
|
+
@io.eof?
|
366
|
+
end
|
367
|
+
|
368
|
+
##
|
369
|
+
# yields all objects in the stream
|
370
|
+
def each
|
371
|
+
@io.rewind
|
372
|
+
yield get until eof?
|
373
|
+
end
|
374
|
+
|
375
|
+
private
|
376
|
+
|
377
|
+
##
|
378
|
+
# Read header and return code,value
|
379
|
+
def rhdr
|
380
|
+
b = rbyte
|
381
|
+
code, value = b & 7, b >> 3
|
382
|
+
case value
|
383
|
+
when 0..22
|
384
|
+
return code, value
|
385
|
+
when 23...31
|
386
|
+
return code, rlongint(value-22)
|
387
|
+
else
|
388
|
+
n = renc
|
389
|
+
return code, rlongint(n)
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
##
|
394
|
+
# read n-bytes long positive integer
|
395
|
+
def rlongint(bytes)
|
396
|
+
res = i = 0
|
397
|
+
bytes.times do
|
398
|
+
res |= rbyte << i
|
399
|
+
i += 8
|
400
|
+
end
|
401
|
+
res
|
402
|
+
end
|
403
|
+
|
404
|
+
##
|
405
|
+
# Read variable-length positive integer
|
406
|
+
def renc
|
407
|
+
value = i = 0
|
408
|
+
loop do
|
409
|
+
x = rbyte
|
410
|
+
value |= (x&0x7f) << i
|
411
|
+
return value if x & 0x80 != 0
|
412
|
+
i += 7
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def rbyte
|
417
|
+
@io.readbyte
|
418
|
+
end
|
419
|
+
|
420
|
+
def rdouble
|
421
|
+
rbin(8).unpack('E')[0]
|
422
|
+
end
|
423
|
+
|
424
|
+
def rbin(length)
|
425
|
+
@io.sysread length
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
##
|
430
|
+
# If block is given, yields all objects from the
|
431
|
+
# src (that can be either string or IO), passes it to the block and stores
|
432
|
+
# what block returns in the array, unless block returns nil. The array
|
433
|
+
# is then returned.
|
434
|
+
#
|
435
|
+
# Otherwise, reads and return first object from src
|
436
|
+
def Boss.load(src)
|
437
|
+
p = Parser.new(src)
|
438
|
+
if block_given?
|
439
|
+
res = []
|
440
|
+
res << yield(p.get) while !p.eof?
|
441
|
+
res
|
442
|
+
else
|
443
|
+
p.get
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
# Load all objects from the src and return them as an array
|
448
|
+
def Boss.load_all src
|
449
|
+
p = Parser.new(src)
|
450
|
+
res = []
|
451
|
+
res << p.get while !p.eof?
|
452
|
+
res
|
453
|
+
end
|
454
|
+
|
455
|
+
##
|
456
|
+
# convert all arguments into successive BOSS encoeded
|
457
|
+
# object, so all them will share same global reference
|
458
|
+
# cache.
|
459
|
+
def Boss.dump(*roots)
|
460
|
+
f = f = Formatter.new
|
461
|
+
roots.each { |r| f << r }
|
462
|
+
f.string
|
463
|
+
end
|
464
|
+
|
465
|
+
def Boss.dump_compressed(*roots)
|
466
|
+
f = f = Formatter.new
|
467
|
+
roots.each { |r| f.put_compressed r }
|
468
|
+
f.string
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
data/spec/boss_spec.rb
ADDED
@@ -0,0 +1,467 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'json'
|
5
|
+
require 'zlib'
|
6
|
+
require 'base64'
|
7
|
+
require 'boss-protocol'
|
8
|
+
|
9
|
+
describe 'Boss' do
|
10
|
+
|
11
|
+
it 'should perform compatible encode' do
|
12
|
+
Vectors.each do |a, b|
|
13
|
+
Boss.load(a).should == b
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should perform compatible decode' do
|
18
|
+
Vectors.each do |a,b|
|
19
|
+
Boss.load(a).should == b
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should properly encode positive and negative floats' do
|
24
|
+
round_check 0
|
25
|
+
round_check 1.0
|
26
|
+
round_check -1.0
|
27
|
+
round_check 2.0
|
28
|
+
round_check -2.0
|
29
|
+
round_check 1.11
|
30
|
+
round_check -1.11
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should encode booleans' do
|
34
|
+
round_check true
|
35
|
+
round_check false
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should properly encode nil' do
|
39
|
+
round_check(1)
|
40
|
+
round_check(nil)
|
41
|
+
round_check([1])
|
42
|
+
round_check([nil,nil,nil,3,4,5, nil])
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should cache data' do
|
46
|
+
a = [1,2,3,4]
|
47
|
+
ca = { 1 => 55 }
|
48
|
+
b, c, d, e, f, g = Boss.load(Boss.dump([a,a,ca,ca, "oops", "oops"]))
|
49
|
+
a.should == b
|
50
|
+
b.should == c
|
51
|
+
b.should be_eql(c)
|
52
|
+
|
53
|
+
ca.should == d
|
54
|
+
ca.should == e
|
55
|
+
d.should be_equal(e)
|
56
|
+
|
57
|
+
f.should == "oops"
|
58
|
+
g.should == f
|
59
|
+
g.should be_equal(f)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should properly encode very big integers' do
|
63
|
+
val = 1<<1024 * 7 + 117
|
64
|
+
round_check val
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should decode one by one using block' do
|
68
|
+
args = [1,2,3,4,5]
|
69
|
+
s = Boss.dump(*args)
|
70
|
+
res = []
|
71
|
+
res = Boss.load(s) { |x| x }
|
72
|
+
args.should == res
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should cache arrays and hashes too' do
|
76
|
+
d = { "Hello" => "world" }
|
77
|
+
a = [112,11]
|
78
|
+
r = Boss.load_all(Boss.dump( a,d,a,d ))
|
79
|
+
[a,d,a,d].should == r
|
80
|
+
r[1].should be_equal(r[3])
|
81
|
+
r[0].should be_equal(r[2])
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should properly encode multilevel structures' do
|
85
|
+
root = { "level" => 1}
|
86
|
+
p = root
|
87
|
+
200.times { |n|
|
88
|
+
x = { "level" => n+2}
|
89
|
+
p['data'] = x
|
90
|
+
p['payload'] = 'great'
|
91
|
+
p = x
|
92
|
+
}
|
93
|
+
round_check root
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
it 'should effectively compress/decompress' do
|
98
|
+
# No compression
|
99
|
+
data = "Too short"
|
100
|
+
x0 = Boss.dump_compressed data
|
101
|
+
Boss.load(x0).should == data
|
102
|
+
x0.length.should <= (data.length + 3)
|
103
|
+
|
104
|
+
# short compression: zlib
|
105
|
+
data = "z" * 1024
|
106
|
+
x1 = Boss.dump_compressed data
|
107
|
+
Boss.load(x1).should == data
|
108
|
+
x1.length.should <= (data.length/10)
|
109
|
+
|
110
|
+
# hevay compression on big data
|
111
|
+
data = JSON.parse(Zlib::Inflate.new(Zlib::MAX_WBITS).inflate(Base64::decode64(CompressedTestJson)))
|
112
|
+
round_check data
|
113
|
+
x2 = Boss.dump_compressed(data)
|
114
|
+
Boss.load(x2).should == data
|
115
|
+
x2.length.should < 13700
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
def round_check(ob)
|
120
|
+
ob.should == Boss.load(Boss.dump(ob))
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
##
|
125
|
+
# Set (force) string str encoding to binary
|
126
|
+
def self.bytes!(str)
|
127
|
+
str.force_encoding Encoding::BINARY
|
128
|
+
str
|
129
|
+
end
|
130
|
+
|
131
|
+
Vectors = [['8', 7], ["\xb8F", 70], [".\x00\x08\n8:", [0, 1, -1, 7, -7]], ["\xc8p\x11\x01", 70000],
|
132
|
+
['+Hello', 'Hello'], [',Hello', bytes!('Hello'), 2, 4, 4, 1]]
|
133
|
+
|
134
|
+
CompressedTestJson = <<-End
|
135
|
+
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
|
465
|
+
End
|
466
|
+
|
467
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: boss-protocol
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- sergeych
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bzip2-ruby
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Binary streamable bit-effective protocol to effectively store object
|
47
|
+
tree hierarchies
|
48
|
+
email:
|
49
|
+
- real.sergeych@gmail.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- .rspec
|
56
|
+
- Gemfile
|
57
|
+
- LICENSE.txt
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- boss-protocol.gemspec
|
61
|
+
- lib/boss-protocol.rb
|
62
|
+
- lib/boss-protocol/version.rb
|
63
|
+
- spec/boss_spec.rb
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
homepage: ''
|
66
|
+
licenses: []
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.8.24
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: Traversable and streamable to some extend protocol supports lists, hashes,
|
89
|
+
caching, compression and more
|
90
|
+
test_files:
|
91
|
+
- spec/boss_spec.rb
|
92
|
+
- spec/spec_helper.rb
|