boss-protocol 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +56 -15
- data/boss-protocol.gemspec +1 -1
- data/lib/boss-protocol.rb +28 -16
- data/lib/boss-protocol/version.rb +1 -1
- data/samples/testp.rb +25 -0
- metadata +4 -3
data/README.md
CHANGED
@@ -2,26 +2,32 @@
|
|
2
2
|
|
3
3
|
BOSS is acronym for Binary Object Streamable Storage.
|
4
4
|
|
5
|
-
The very space-effective,
|
6
|
-
Allow to effectively store small or
|
7
|
-
any
|
8
|
-
|
9
|
-
|
10
|
-
repeating objects and stores/restores links to objects.
|
5
|
+
The very space-effective, platform-independent^ streamable and traversable
|
6
|
+
typed binary protocol. Allow to effectively store small or any sized integers,
|
7
|
+
strings or binary data of any size, floats and doubles, arrays and hashes in a
|
8
|
+
very effective way. It caches repeating objects and stores/restores links to
|
9
|
+
objects.
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
The protocol allow to effectively store texts and binary data of absolutely any
|
12
|
+
size, signed integers of absolutely any size, arrays and hashes with no limit
|
13
|
+
on items and overall gross size. It is desirable to use build-in compression when
|
14
|
+
appropriate.
|
15
|
+
|
16
|
+
Streamable means that you can use a pipe (tcp/ip, wahtever), put the object at
|
17
|
+
one side and load it on other, one-by-one, and caching and links will be
|
18
|
+
restored properly.
|
14
19
|
|
15
20
|
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
|
17
|
-
JSON reduces in size twice with Boss.
|
21
|
+
main goal was to very effective data sending and is a great replacement for
|
22
|
+
json/boss/whatever. For example, typical JSON reduces in size twice with Boss.
|
18
23
|
|
19
24
|
Boss protocol also allow to transparently compress its representations.
|
20
25
|
|
21
|
-
*Attention* ruby version is under final development, its streaming support may
|
22
|
-
seem to work just fine.
|
26
|
+
*Attention* ruby version is under final development, its streaming support may
|
27
|
+
not work as expected, while the rest seem to work just fine.
|
23
28
|
|
24
|
-
There are versions in C and Python that are in most part ready
|
29
|
+
There are versions in C and Python that are in most part ready but are parts
|
30
|
+
in other systems and need to be extracted first.
|
25
31
|
|
26
32
|
## Installation
|
27
33
|
|
@@ -37,7 +43,7 @@ Or install it yourself as:
|
|
37
43
|
|
38
44
|
$ gem install boss-protocol
|
39
45
|
|
40
|
-
## Usage
|
46
|
+
## Simple Usage
|
41
47
|
|
42
48
|
1.9.3-p327 :011 > require 'boss-protocol'
|
43
49
|
=> false
|
@@ -66,7 +72,42 @@ To use the transparent compression:
|
|
66
72
|
1.9.3-p327 :017 > data == Boss.load(x)
|
67
73
|
=> true
|
68
74
|
|
69
|
-
Streaming
|
75
|
+
## Streaming sample
|
76
|
+
|
77
|
+
Cehck the code in samples folder.
|
78
|
+
|
79
|
+
This sample shows boss object passing between 2 forked processes:
|
80
|
+
|
81
|
+
if fork
|
82
|
+
wr.close
|
83
|
+
if true
|
84
|
+
# You can do it with block:
|
85
|
+
Boss::Parser.new(rd).each { |obj| puts "Got an object: #{obj}" }
|
86
|
+
else
|
87
|
+
# You can do it without block too:
|
88
|
+
input = Boss::Parser.new rd
|
89
|
+
puts "Got an object: #{input.get}" while !input.eof?
|
90
|
+
end
|
91
|
+
rd.close
|
92
|
+
Process.wait
|
93
|
+
else
|
94
|
+
rd.close
|
95
|
+
out = Boss::Formatter.new wr
|
96
|
+
out << ["Foo", "bar"]
|
97
|
+
out.put_compressed "Zz"*62
|
98
|
+
out << ["Hello", "world", "!"]
|
99
|
+
out << { "Thats all" => "folks!" }
|
100
|
+
wr.close
|
101
|
+
end
|
102
|
+
|
103
|
+
Boss ways in the sample are identical; second one (with get) may be sometimes
|
104
|
+
more convenient, say, to terminate object polling on some condition before eof.
|
105
|
+
|
106
|
+
So, all you need is IO-like object that provide io.read(length) and io.write(data) to
|
107
|
+
read/write binary data. Usual files, pipes, tcp sockets, stringIO - everything is ok.
|
108
|
+
|
109
|
+
The protocol could be very effectively used to form higher level protocols over the
|
110
|
+
network as it caches data on the fly and can provide links (if used with
|
70
111
|
|
71
112
|
## Contributing
|
72
113
|
|
data/boss-protocol.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ["sergeych"]
|
10
10
|
gem.email = ["real.sergeych@gmail.com"]
|
11
11
|
gem.description = %q{Binary streamable bit-effective protocol to effectively store object tree hierarchies}
|
12
|
-
gem.summary = %q{Traversable and streamable to
|
12
|
+
gem.summary = %q{Traversable and streamable to protocol supports lists, hashes, caching,
|
13
13
|
compression and more}
|
14
14
|
gem.homepage = ""
|
15
15
|
|
data/lib/boss-protocol.rb
CHANGED
@@ -44,8 +44,12 @@ require 'bzip2'
|
|
44
44
|
# No object serialization yet, no callables and bound methods - these appear to be
|
45
45
|
# non portable between platoforms.
|
46
46
|
#
|
47
|
+
# Please note that most of this code was developed in 2008 so it is kind of old ;)
|
48
|
+
# though working.
|
49
|
+
|
47
50
|
module Boss
|
48
|
-
|
51
|
+
|
52
|
+
# Basic types
|
49
53
|
TYPE_INT = 0
|
50
54
|
TYPE_EXTRA = 1
|
51
55
|
TYPE_NINT = 2
|
@@ -104,6 +108,10 @@ module Boss
|
|
104
108
|
@cache = { nil => 0 }
|
105
109
|
end
|
106
110
|
|
111
|
+
##
|
112
|
+
# same as put but automatically select and use proper compression. Parser.get
|
113
|
+
# will automatically decompress.
|
114
|
+
#
|
107
115
|
def put_compressed ob
|
108
116
|
data = Boss.dump(ob)
|
109
117
|
whdr TYPE_EXTRA, TCOMPRESSED
|
@@ -186,10 +194,9 @@ module Boss
|
|
186
194
|
|
187
195
|
##
|
188
196
|
# Get the result as string, may not work if
|
189
|
-
# some specific IO instance is
|
190
|
-
# works well with default
|
197
|
+
# some specific IO instance is passed to constructor.
|
198
|
+
# works well with default constructor or StringIO
|
191
199
|
def string
|
192
|
-
# p "string!! #{@io.string}"
|
193
200
|
@io.string
|
194
201
|
end
|
195
202
|
|
@@ -261,7 +268,7 @@ module Boss
|
|
261
268
|
# write binary value
|
262
269
|
#
|
263
270
|
def wbin(bb)
|
264
|
-
@io.
|
271
|
+
@io.write bb
|
265
272
|
end
|
266
273
|
|
267
274
|
##
|
@@ -273,12 +280,10 @@ module Boss
|
|
273
280
|
def wdouble val
|
274
281
|
wbin [val].pack('E')
|
275
282
|
end
|
276
|
-
|
277
|
-
|
278
283
|
end
|
279
284
|
|
280
285
|
##
|
281
|
-
# Parser
|
286
|
+
# Parser implements IO-like behavior and provides deserializing of
|
282
287
|
# BOSS objects. Parser can store multiple root objects and share same
|
283
288
|
# object cache for all them
|
284
289
|
class Parser
|
@@ -305,9 +310,9 @@ module Boss
|
|
305
310
|
code, value = rhdr
|
306
311
|
case code
|
307
312
|
when TYPE_INT
|
308
|
-
|
313
|
+
value
|
309
314
|
when TYPE_NINT
|
310
|
-
|
315
|
+
-value
|
311
316
|
when TYPE_EXTRA
|
312
317
|
case value
|
313
318
|
when TTRUE
|
@@ -342,18 +347,18 @@ module Boss
|
|
342
347
|
s = rbin value
|
343
348
|
s.force_encoding code == TYPE_BIN ? Encoding::BINARY : Encoding::UTF_8
|
344
349
|
@cache << s
|
345
|
-
|
350
|
+
s
|
346
351
|
when TYPE_LIST
|
347
352
|
# p "items", value
|
348
353
|
@cache << (list = [])
|
349
354
|
value.times { list << get }
|
350
|
-
|
355
|
+
list
|
351
356
|
when TYPE_DICT
|
352
357
|
@cache << (dict = { })
|
353
358
|
value.times { dict[get] = get }
|
354
|
-
|
359
|
+
dict
|
355
360
|
when TYPE_CREF
|
356
|
-
|
361
|
+
@cache[value]
|
357
362
|
else
|
358
363
|
raise UnknownTypeException
|
359
364
|
end
|
@@ -368,7 +373,6 @@ module Boss
|
|
368
373
|
##
|
369
374
|
# yields all objects in the stream
|
370
375
|
def each
|
371
|
-
@io.rewind
|
372
376
|
yield get until eof?
|
373
377
|
end
|
374
378
|
|
@@ -421,8 +425,12 @@ module Boss
|
|
421
425
|
rbin(8).unpack('E')[0]
|
422
426
|
end
|
423
427
|
|
428
|
+
def rfloat
|
429
|
+
rbin(4).unpack('e')[0]
|
430
|
+
end
|
431
|
+
|
424
432
|
def rbin(length)
|
425
|
-
@io.
|
433
|
+
@io.read length
|
426
434
|
end
|
427
435
|
end
|
428
436
|
|
@@ -462,6 +470,10 @@ module Boss
|
|
462
470
|
f.string
|
463
471
|
end
|
464
472
|
|
473
|
+
##
|
474
|
+
# Just like Boss.dump but automatically use proper compression
|
475
|
+
# depending on the data size. Boss.load or Boss.load_all will
|
476
|
+
# automatically decompress the data
|
465
477
|
def Boss.dump_compressed(*roots)
|
466
478
|
f = f = Formatter.new
|
467
479
|
roots.each { |r| f.put_compressed r }
|
data/samples/testp.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require '../lib/boss-protocol'
|
2
|
+
|
3
|
+
rd, wr = IO.pipe
|
4
|
+
|
5
|
+
if fork
|
6
|
+
wr.close
|
7
|
+
if false
|
8
|
+
# You can do it with block:
|
9
|
+
Boss::Parser.new(rd).each { |obj| puts "Got an object: #{obj}" }
|
10
|
+
else
|
11
|
+
# You can do it without block too:
|
12
|
+
input = Boss::Parser.new rd
|
13
|
+
puts "Got an object: #{input.get}" while !input.eof?
|
14
|
+
end
|
15
|
+
rd.close
|
16
|
+
Process.wait
|
17
|
+
else
|
18
|
+
rd.close
|
19
|
+
out = Boss::Formatter.new wr
|
20
|
+
out << ["Foo", "bar"]
|
21
|
+
out.put_compressed "Zz"*62
|
22
|
+
out << ["Hello", "world", "!"]
|
23
|
+
out << { "Thats all" => "folks!" }
|
24
|
+
wr.close
|
25
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boss-protocol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -60,6 +60,7 @@ files:
|
|
60
60
|
- boss-protocol.gemspec
|
61
61
|
- lib/boss-protocol.rb
|
62
62
|
- lib/boss-protocol/version.rb
|
63
|
+
- samples/testp.rb
|
63
64
|
- spec/boss_spec.rb
|
64
65
|
- spec/spec_helper.rb
|
65
66
|
homepage: ''
|
@@ -85,8 +86,8 @@ rubyforge_project:
|
|
85
86
|
rubygems_version: 1.8.24
|
86
87
|
signing_key:
|
87
88
|
specification_version: 3
|
88
|
-
summary: Traversable and streamable to
|
89
|
-
|
89
|
+
summary: Traversable and streamable to protocol supports lists, hashes, caching, compression
|
90
|
+
and more
|
90
91
|
test_files:
|
91
92
|
- spec/boss_spec.rb
|
92
93
|
- spec/spec_helper.rb
|