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 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 Streamable Storage.
3
+ BOSS is an acronym for Binary Object Streaming Specification.
4
4
 
5
- The very space-effective, platform-independent^ streamable and traversable
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, wahtever), put the object at
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
@@ -1,3 +1,3 @@
1
1
  module Boss
2
- VERSION = "0.1.3"
2
+ VERSION = "1.3.0"
3
3
  end
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; end
55
- # Basic types
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 = 15
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
- #data = Bzip2.compress data
132
- #2
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
- @cache[obj] = @cache.length
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
- @cache << s
404
+ cache_object s
361
405
  s
362
406
  when TYPE_LIST
363
407
  # p "items", value
364
- @cache << (list = [])
408
+ cache_object (list = [])
365
409
  value.times { list << get }
366
410
  list
367
411
  when TYPE_DICT
368
- @cache << (dict = { })
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
- if false
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 too:
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: 0.1.3
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-03-28 00:00:00.000000000 Z
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: 1.8.25
67
+ rubygems_version: 2.0.6
71
68
  signing_key:
72
- specification_version: 3
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: