boss-protocol 0.1.3 → 1.3.0
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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/README.md +12 -4
- data/lib/boss-protocol/version.rb +1 -1
- data/lib/boss-protocol.rb +68 -11
- data/samples/testp.rb +6 -2
- data/spec/boss_spec.rb +22 -0
- metadata +10 -13
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 48d7d49095b00c5a6c7c1fc9c349e623cb52bc62
|
4
|
+
data.tar.gz: e15a3c17f710e7e07af4922ab85a70a01990e6a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5d8586643c80b3bf34e73e624ca496733ad7e3c5e659f8021d59a42f4c4cb936f4e5385aaaeb0a874197febd98c31a0d56a13b1f7fce1624eb5eecc017de812b
|
7
|
+
data.tar.gz: d4835694296bd13626adaaeb10bc5cc1d950e53f1a1c71d9a5d868f38028f7bdc4f1baf8a8e97c1df511767c6dae49f7afbbdad9259329f332f3e2656e178248
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Boss Protocol
|
2
2
|
|
3
|
-
BOSS is acronym for Binary Object
|
3
|
+
BOSS is an acronym for Binary Object Streaming Specification.
|
4
4
|
|
5
|
-
The
|
5
|
+
The bit-effective, platform-independent streamable and traversable
|
6
6
|
typed binary protocol. Allow to effectively store small or any sized integers,
|
7
7
|
strings or binary data of any size, floats and doubles, arrays and hashes in a
|
8
8
|
very effective way. It caches repeating objects and stores/restores links to
|
@@ -13,7 +13,7 @@ size, signed integers of absolutely any size, arrays and hashes with no limit
|
|
13
13
|
on items and overall gross size. It is desirable to use build-in compression when
|
14
14
|
appropriate.
|
15
15
|
|
16
|
-
Streamable means that you can use a pipe (tcp/ip
|
16
|
+
Streamable means that you can use a pipe (for example tcp/ip), put the object at
|
17
17
|
one side and load it on other, one-by-one, and caching and links will be
|
18
18
|
restored properly.
|
19
19
|
|
@@ -23,6 +23,14 @@ json/boss/whatever. For example, typical JSON reduces in size twice with Boss.
|
|
23
23
|
|
24
24
|
Boss protocol also allow to transparently compress its representations.
|
25
25
|
|
26
|
+
Boss also supports "stream mode" that lacks tree reconstruction but could be
|
27
|
+
effectively use when implementing long-living streams (e.g. stream protocols).
|
28
|
+
In regular mode it causes unlimited cache grows as Boss would try to reconstruct
|
29
|
+
all possible references to already serialized objects. In the stream mode only
|
30
|
+
strings are cached, and cache size and capacity are dynamically limited.
|
31
|
+
Boss writes stream mode marker and handles stream mode on receiving end
|
32
|
+
automatically.
|
33
|
+
|
26
34
|
Supported types:
|
27
35
|
|
28
36
|
* Signed integers of any length
|
@@ -86,7 +94,7 @@ To use the transparent compression:
|
|
86
94
|
## Streaming sample
|
87
95
|
|
88
96
|
This sample shows boss object hierarchies passing between 2 forked processes
|
89
|
-
using a pipe:
|
97
|
+
using a pipe (see samples/):
|
90
98
|
|
91
99
|
if fork
|
92
100
|
wr.close
|
data/lib/boss-protocol.rb
CHANGED
@@ -36,6 +36,8 @@ require 'zlib'
|
|
36
36
|
# Attn! We removed Bzip2 compression for the sake of compatibility. We may add it back when situation
|
37
37
|
# with bz2 implementations on various platforms will be eased
|
38
38
|
#
|
39
|
+
# 1.3 Stream mode added
|
40
|
+
#
|
39
41
|
# 1.2 version adds support for booelans and removes support for python __reduce__ - based objects
|
40
42
|
# as absolutely non portable. It also introduces
|
41
43
|
#
|
@@ -51,8 +53,9 @@ require 'zlib'
|
|
51
53
|
|
52
54
|
module Boss
|
53
55
|
|
54
|
-
class NotSupportedException < StandardError;
|
55
|
-
|
56
|
+
class NotSupportedException < StandardError;
|
57
|
+
end
|
58
|
+
# Basic types
|
56
59
|
TYPE_INT = 0
|
57
60
|
TYPE_EXTRA = 1
|
58
61
|
TYPE_NINT = 2
|
@@ -85,7 +88,9 @@ module Boss
|
|
85
88
|
TFALSE = 13
|
86
89
|
|
87
90
|
TCOMPRESSED = 14
|
88
|
-
TTIME
|
91
|
+
TTIME = 15
|
92
|
+
|
93
|
+
XT_STREAM_MODE = 16
|
89
94
|
|
90
95
|
def checkArg(cond, msg=nil)
|
91
96
|
raise ArgumentError unless cond
|
@@ -94,7 +99,6 @@ module Boss
|
|
94
99
|
class UnknownTypeException < Exception;
|
95
100
|
end
|
96
101
|
|
97
|
-
##
|
98
102
|
# Formats ruby object hierarchies with BOSS
|
99
103
|
# notation
|
100
104
|
#
|
@@ -112,6 +116,20 @@ module Boss
|
|
112
116
|
@cache = { nil => 0 }
|
113
117
|
end
|
114
118
|
|
119
|
+
|
120
|
+
# Switch to stream mode. Stream mode limits cache using to strings only in LRU
|
121
|
+
# mode using specified parameters. Stream mode writes a marker into output so
|
122
|
+
# decoder knows it.
|
123
|
+
# @param max_string_size maximum allowed size of the string to be cached.
|
124
|
+
# longer strings will not be cached
|
125
|
+
# @param max_cache_entries
|
126
|
+
def stream_mode max_cache_entries, max_string_size
|
127
|
+
@max_cache_entries, @max_string_size = max_cache_entries, max_string_size
|
128
|
+
whdr TYPE_EXTRA, XT_STREAM_MODE
|
129
|
+
self << max_cache_entries.to_i << max_string_size.to_i
|
130
|
+
@cache = { nil => 0 }
|
131
|
+
end
|
132
|
+
|
115
133
|
##
|
116
134
|
# same as put but automatically select and use proper compression. Parser.get
|
117
135
|
# will automatically decompress.
|
@@ -128,8 +146,8 @@ module Boss
|
|
128
146
|
else
|
129
147
|
data = Zlib::Deflate.new.deflate(data, Zlib::FINISH)
|
130
148
|
1
|
131
|
-
|
132
|
-
|
149
|
+
#data = Bzip2.compress data
|
150
|
+
#2
|
133
151
|
end
|
134
152
|
whdr type, data.length
|
135
153
|
wbin data
|
@@ -211,18 +229,39 @@ module Boss
|
|
211
229
|
|
212
230
|
private
|
213
231
|
|
214
|
-
##
|
215
232
|
# Write cache ref if the object is cached, and return true
|
216
233
|
# otherwise store object in the cache. Caller should
|
217
234
|
# write object to @io if notCached return true, and skip
|
218
235
|
# writing otherwise
|
236
|
+
|
219
237
|
def notCached(obj)
|
220
238
|
n = @cache[obj]
|
221
239
|
if n
|
222
240
|
whdr TYPE_CREF, n
|
223
241
|
false
|
224
242
|
else
|
225
|
-
|
243
|
+
# Check stream mode
|
244
|
+
if @max_string_size
|
245
|
+
if obj.is_a?(String) && obj.length <= @max_string_size
|
246
|
+
if @cache.length > @max_cache_entries
|
247
|
+
minIndex = @cache.length - @max_cache_entries
|
248
|
+
key = nil
|
249
|
+
@cache.each { |k, v|
|
250
|
+
next if k == nil
|
251
|
+
if v == minIndex
|
252
|
+
key = k
|
253
|
+
else
|
254
|
+
@cache[k] = v - 1
|
255
|
+
end
|
256
|
+
}
|
257
|
+
key == nil and raise "Cache implementation failed"
|
258
|
+
@cache.delete key
|
259
|
+
end
|
260
|
+
@cache[obj] = @cache.length
|
261
|
+
end
|
262
|
+
else
|
263
|
+
@cache[obj] = @cache.length
|
264
|
+
end
|
226
265
|
true
|
227
266
|
end
|
228
267
|
end
|
@@ -351,21 +390,26 @@ module Boss
|
|
351
390
|
end
|
352
391
|
when TTIME
|
353
392
|
Time.at renc
|
393
|
+
when XT_STREAM_MODE
|
394
|
+
@cache = [nil]
|
395
|
+
@max_cache_entries = get + 1 # Count 0th element (always 0)
|
396
|
+
@max_string_size = get
|
397
|
+
get
|
354
398
|
else
|
355
399
|
raise UnknownTypeException
|
356
400
|
end
|
357
401
|
when TYPE_TEXT, TYPE_BIN
|
358
402
|
s = rbin value
|
359
403
|
s.force_encoding code == TYPE_BIN ? Encoding::BINARY : Encoding::UTF_8
|
360
|
-
|
404
|
+
cache_object s
|
361
405
|
s
|
362
406
|
when TYPE_LIST
|
363
407
|
# p "items", value
|
364
|
-
|
408
|
+
cache_object (list = [])
|
365
409
|
value.times { list << get }
|
366
410
|
list
|
367
411
|
when TYPE_DICT
|
368
|
-
|
412
|
+
cache_object (dict = {})
|
369
413
|
value.times { dict[get] = get }
|
370
414
|
dict
|
371
415
|
when TYPE_CREF
|
@@ -391,6 +435,19 @@ module Boss
|
|
391
435
|
|
392
436
|
private
|
393
437
|
|
438
|
+
def cache_object object
|
439
|
+
# Stream mode?
|
440
|
+
if @max_cache_entries
|
441
|
+
if object.is_a?(String) && object.length <= @max_string_size
|
442
|
+
# Should cache
|
443
|
+
@cache << object
|
444
|
+
@cache.delete_at(1) if @cache.length > @max_cache_entries
|
445
|
+
end
|
446
|
+
else
|
447
|
+
@cache << object
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
394
451
|
##
|
395
452
|
# Read header and return code,value
|
396
453
|
def rhdr
|
data/samples/testp.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
|
+
# The interprocess communication using BOSS through
|
2
|
+
# pipes
|
3
|
+
|
1
4
|
require '../lib/boss-protocol'
|
2
5
|
|
3
6
|
rd, wr = IO.pipe
|
4
7
|
|
5
8
|
if fork
|
6
9
|
wr.close
|
7
|
-
|
10
|
+
# There is more than one way:
|
11
|
+
if true
|
8
12
|
# You can do it with block:
|
9
13
|
Boss::Parser.new(rd).each { |obj| puts "Got an object: #{obj}" }
|
10
14
|
else
|
11
|
-
# You can do it without block
|
15
|
+
# You can do it without block:
|
12
16
|
input = Boss::Parser.new rd
|
13
17
|
puts "Got an object: #{input.get}" while !input.eof?
|
14
18
|
end
|
data/spec/boss_spec.rb
CHANGED
@@ -152,6 +152,28 @@ describe 'Boss' do
|
|
152
152
|
-> { Boss.dump MyObject.new }.should raise_error(Boss::NotSupportedException)
|
153
153
|
end
|
154
154
|
|
155
|
+
it 'should implement stream mode' do
|
156
|
+
out = Boss::Formatter.new
|
157
|
+
out.stream_mode 3, 10
|
158
|
+
3.times { out << "String too long" }
|
159
|
+
(1..6).each { |n| out << "test#{n}" }
|
160
|
+
(4..6).each { |n| out << "test#{n}" }
|
161
|
+
(4..6).each { |n| out << "test#{n}" }
|
162
|
+
out << "test7"
|
163
|
+
|
164
|
+
res = "\x81\x18P{String too long{String too long{String too long+test1+test2+test3+test4+test5+test6\r\x15\x1D\r\x15\x1D+test7"
|
165
|
+
res.force_encoding 'binary'
|
166
|
+
out.string.should == res
|
167
|
+
|
168
|
+
inp = Boss::Parser.new out.string
|
169
|
+
|
170
|
+
3.times { inp.get.should == "String too long" }
|
171
|
+
(1..6).each { |n| inp.get.should == "test#{n}" }
|
172
|
+
(4..6).each { |n| inp.get.should == "test#{n}" }
|
173
|
+
(4..6).each { |n| inp.get.should == "test#{n}" }
|
174
|
+
inp.get.should == "test7"
|
175
|
+
end
|
176
|
+
|
155
177
|
def round_check(ob)
|
156
178
|
ob.should == Boss.load(Boss.dump(ob))
|
157
179
|
end
|
metadata
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boss-protocol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 1.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- sergeych
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rspec
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
description: Binary streamable bit-effective protocol to effectively store object
|
@@ -37,6 +34,7 @@ extra_rdoc_files: []
|
|
37
34
|
files:
|
38
35
|
- .gitignore
|
39
36
|
- .rspec
|
37
|
+
- .ruby-version
|
40
38
|
- Gemfile
|
41
39
|
- LICENSE.txt
|
42
40
|
- README.md
|
@@ -49,27 +47,26 @@ files:
|
|
49
47
|
- spec/spec_helper.rb
|
50
48
|
homepage: ''
|
51
49
|
licenses: []
|
50
|
+
metadata: {}
|
52
51
|
post_install_message:
|
53
52
|
rdoc_options: []
|
54
53
|
require_paths:
|
55
54
|
- lib
|
56
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
56
|
requirements:
|
59
|
-
- -
|
57
|
+
- - '>='
|
60
58
|
- !ruby/object:Gem::Version
|
61
59
|
version: '0'
|
62
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
61
|
requirements:
|
65
|
-
- -
|
62
|
+
- - '>='
|
66
63
|
- !ruby/object:Gem::Version
|
67
64
|
version: '0'
|
68
65
|
requirements: []
|
69
66
|
rubyforge_project:
|
70
|
-
rubygems_version:
|
67
|
+
rubygems_version: 2.0.6
|
71
68
|
signing_key:
|
72
|
-
specification_version:
|
69
|
+
specification_version: 4
|
73
70
|
summary: Traversable and streamable to protocol supports lists, hashes, caching, compression
|
74
71
|
and more
|
75
72
|
test_files:
|