boss-protocol 0.0.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.
- 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
|