boss-protocol 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
19
+ .idea
20
+ .rbx
21
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in boss-protocol.gemspec
4
+ gemspec
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,3 @@
1
+ module Boss
2
+ VERSION = "0.0.1"
3
+ 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
@@ -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