boss-protocol 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -11
- data/lib/boss-protocol/version.rb +1 -1
- data/lib/boss-protocol.rb +6 -0
- data/spec/boss_spec.rb +31 -24
- metadata +1 -1
data/README.md
CHANGED
@@ -23,10 +23,21 @@ 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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
Supported types:
|
27
|
+
|
28
|
+
* Signed integers of any length
|
29
|
+
* Signed floats and doubles (4 or 8 bytes)
|
30
|
+
* Boolean values (true/false)
|
31
|
+
* UTF-8 encoded texts, any length
|
32
|
+
* Binary data, any length
|
33
|
+
* Time objects (rounded to 1s resolution)
|
34
|
+
* Arrays with any number of elements
|
35
|
+
* Hashes with any keys and values and unlimited length
|
36
|
+
* Reference to the object that already was serialized
|
37
|
+
|
38
|
+
There is a pending extension to serialize user types that will be available
|
39
|
+
soon or even faster - leave me a request in issues. There are also versions
|
40
|
+
in C and Python that are in most part ready but are parts
|
30
41
|
in other systems and need to be extracted first.
|
31
42
|
|
32
43
|
## Installation
|
@@ -74,9 +85,8 @@ To use the transparent compression:
|
|
74
85
|
|
75
86
|
## Streaming sample
|
76
87
|
|
77
|
-
|
78
|
-
|
79
|
-
This sample shows boss object passing between 2 forked processes:
|
88
|
+
This sample shows boss object hierarchies passing between 2 forked processes
|
89
|
+
using a pipe:
|
80
90
|
|
81
91
|
if fork
|
82
92
|
wr.close
|
@@ -96,15 +106,16 @@ This sample shows boss object passing between 2 forked processes:
|
|
96
106
|
out << ["Foo", "bar"]
|
97
107
|
out.put_compressed "Zz"*62
|
98
108
|
out << ["Hello", "world", "!"]
|
99
|
-
out << { "
|
109
|
+
out << { "That's all" => "folks!" }
|
100
110
|
wr.close
|
101
111
|
end
|
102
112
|
|
103
|
-
|
113
|
+
Both ways in the sample are identical; second one (with get) may be sometimes
|
104
114
|
more convenient, say, to terminate object polling on some condition before eof.
|
105
115
|
|
106
|
-
|
107
|
-
read/write binary data. Usual files,
|
116
|
+
All you need is IO-like object that provide io.read(length) on the read side
|
117
|
+
and io.write(data) on another, capable to read/write binary data. Usual files,
|
118
|
+
pipes, tcp sockets, stringIO - everything is ok.
|
108
119
|
|
109
120
|
The protocol could be very effectively used to form higher level protocols over the
|
110
121
|
network as it caches data on the fly and can provide links (if used with
|
data/lib/boss-protocol.rb
CHANGED
@@ -82,6 +82,7 @@ module Boss
|
|
82
82
|
TFALSE = 13
|
83
83
|
|
84
84
|
TCOMPRESSED = 14
|
85
|
+
TTIME = 15
|
85
86
|
|
86
87
|
def checkArg(cond, msg=nil)
|
87
88
|
raise ArgumentError unless cond
|
@@ -182,6 +183,9 @@ module Boss
|
|
182
183
|
whdr TYPE_EXTRA, ob ? TTRUE : TFALSE
|
183
184
|
when nil
|
184
185
|
whdr TYPE_CREF, 0
|
186
|
+
when Time
|
187
|
+
whdr TYPE_EXTRA, TTIME
|
188
|
+
wrenc ob.to_i
|
185
189
|
else
|
186
190
|
error = "error: not supported object: #{ob}, #{ob.class}"
|
187
191
|
p error
|
@@ -340,6 +344,8 @@ module Boss
|
|
340
344
|
else
|
341
345
|
raise UnknownTypeException, "type #{type}"
|
342
346
|
end
|
347
|
+
when TTIME
|
348
|
+
Time.at renc
|
343
349
|
else
|
344
350
|
raise UnknownTypeException
|
345
351
|
end
|
data/spec/boss_spec.rb
CHANGED
@@ -15,7 +15,7 @@ describe 'Boss' do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should perform compatible decode' do
|
18
|
-
Vectors.each do |a,b|
|
18
|
+
Vectors.each do |a, b|
|
19
19
|
Boss.load(a).should == b
|
20
20
|
end
|
21
21
|
end
|
@@ -36,16 +36,23 @@ describe 'Boss' do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'should properly encode nil' do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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 encode Time' do
|
46
|
+
# Time is rounded to seconds on serialization, so we need
|
47
|
+
# take care of the comparison
|
48
|
+
t = Time.now
|
49
|
+
Boss.load(Boss.dump t).should be_within(1).of(t)
|
43
50
|
end
|
44
51
|
|
45
52
|
it 'should cache data' do
|
46
|
-
a
|
47
|
-
ca
|
48
|
-
b, c, d, e, f, g = Boss.load(Boss.dump([a,a,ca,ca, "oops", "oops"]))
|
53
|
+
a = [1, 2, 3, 4]
|
54
|
+
ca = { 1 => 55 }
|
55
|
+
b, c, d, e, f, g = Boss.load(Boss.dump([a, a, ca, ca, "oops", "oops"]))
|
49
56
|
a.should == b
|
50
57
|
b.should == c
|
51
58
|
b.should be_eql(c)
|
@@ -65,30 +72,30 @@ describe 'Boss' do
|
|
65
72
|
end
|
66
73
|
|
67
74
|
it 'should decode one by one using block' do
|
68
|
-
args = [1,2,3,4,5]
|
69
|
-
s
|
70
|
-
res
|
71
|
-
res
|
75
|
+
args = [1, 2, 3, 4, 5]
|
76
|
+
s = Boss.dump(*args)
|
77
|
+
res = []
|
78
|
+
res = Boss.load(s) { |x| x }
|
72
79
|
args.should == res
|
73
80
|
end
|
74
81
|
|
75
82
|
it 'should cache arrays and hashes too' do
|
76
83
|
d = { "Hello" => "world" }
|
77
|
-
a = [112,11]
|
78
|
-
r = Boss.load_all(Boss.dump(
|
79
|
-
[a,d,a,d].should == r
|
84
|
+
a = [112, 11]
|
85
|
+
r = Boss.load_all(Boss.dump(a, d, a, d))
|
86
|
+
[a, d, a, d].should == r
|
80
87
|
r[1].should be_equal(r[3])
|
81
88
|
r[0].should be_equal(r[2])
|
82
89
|
end
|
83
90
|
|
84
91
|
it 'should properly encode multilevel structures' do
|
85
|
-
root = { "level" => 1}
|
86
|
-
p
|
92
|
+
root = { "level" => 1 }
|
93
|
+
p = root
|
87
94
|
200.times { |n|
|
88
|
-
x
|
89
|
-
p['data']
|
95
|
+
x = { "level" => n+2 }
|
96
|
+
p['data'] = x
|
90
97
|
p['payload'] = 'great'
|
91
|
-
p
|
98
|
+
p = x
|
92
99
|
}
|
93
100
|
round_check root
|
94
101
|
end
|
@@ -97,13 +104,13 @@ describe 'Boss' do
|
|
97
104
|
it 'should effectively compress/decompress' do
|
98
105
|
# No compression
|
99
106
|
data = "Too short"
|
100
|
-
x0
|
107
|
+
x0 = Boss.dump_compressed data
|
101
108
|
Boss.load(x0).should == data
|
102
109
|
x0.length.should <= (data.length + 3)
|
103
110
|
|
104
111
|
# short compression: zlib
|
105
112
|
data = "z" * 1024
|
106
|
-
x1
|
113
|
+
x1 = Boss.dump_compressed data
|
107
114
|
Boss.load(x1).should == data
|
108
115
|
x1.length.should <= (data.length/10)
|
109
116
|
|
@@ -131,7 +138,7 @@ describe 'Boss' do
|
|
131
138
|
Vectors = [['8', 7], ["\xb8F", 70], [".\x00\x08\n8:", [0, 1, -1, 7, -7]], ["\xc8p\x11\x01", 70000],
|
132
139
|
['+Hello', 'Hello'], [',Hello', bytes!('Hello'), 2, 4, 4, 1]]
|
133
140
|
|
134
|
-
CompressedTestJson =
|
141
|
+
CompressedTestJson = <<-End
|
135
142
|
eJztfVlz20iy7vv5FQi9dHcExca++OWGLLvdXmTrWOrxmbm+MVEkimRZIMDG
|
136
143
|
Ipk+0f/9ZmZVAQVQpETKmhhPaKKn3ZaIIlCV+SGXLzP/978s+N/RktfsyHpm
|
137
144
|
/e9RVbO6qY6eHRVXR3+N5G9LXq2KvOLyE6LmS/jA/4X/So+e+bEzOsrZksMl
|
@@ -462,6 +469,6 @@ mizfqNHM4GxlFv0UHm8hpGOGRQjy2UGa17xW1dcpFlyBMPF0PL5HbDcJfHsz
|
|
462
469
|
GOPFwUaiO8beVd7QYfG/2yg0t2XZnuHHyrU8/A4qXN/xDugS4Wqi7R3L/rgI
|
463
470
|
ZPRlks8o0Gc+RzbVHfjjBc+8ffGnPSaQaU6ZDxOCIu82CDqxTouy6UhoFPN1
|
464
471
|
NhpXhYHtuZti57hJEhySiPp/f/3XX//1/wEcUSZF
|
465
|
-
End
|
472
|
+
End
|
466
473
|
|
467
474
|
end
|