class Boss::Parser
Parser
implements IO-like behavior and provides deserializing of BOSS objects. Parser
can store multiple root objects and share same object cache for all them
Public Class Methods
construct parser to read from the given string or IO-like object
# File lib/boss-protocol.rb, line 338 def initialize(src=nil) @io = src.class <= String ? StringIO.new(src) : src @io.set_encoding Encoding::BINARY if @io.respond_to? :set_encoding @rbyte = @io.respond_to?(:readbyte) ? -> { @io.readbyte } : -> { @io.read(1).ord } @cache = [nil] @stream_mode = false end
Public Instance Methods
yields all objects in the stream
# File lib/boss-protocol.rb, line 438 def each yield get until eof? end
True is underlying IO-like object reached its end.
# File lib/boss-protocol.rb, line 432 def eof? @io.eof? end
Load the object (object tree) from the stream. Note that if there is more than one object in the stream that are stored with the same Formatter
instance, they will share same cache and references, see Boss
.Formatter.put for details. Note that nil is a valid restored object. Check eof? or catch EOFError, or use Boss
.Parser.each to read all objects from the stream
# File lib/boss-protocol.rb, line 364 def get code, value = rhdr case code when TYPE_INT value when TYPE_NINT -value when TYPE_EXTRA case value when TTRUE true when TFALSE false when DZERO, FZERO 0 when DONE, FONE 1.0 when DMINUSONE, FMINUSONE -1.0 when TDOUBLE rdouble when TCOMPRESSED type, size = rhdr data = rbin size case type when 0 Boss.load data when 1 Boss.load Zlib::Inflate.new(Zlib::MAX_WBITS).inflate(data) #when 2 # Boss.load Bzip2.uncompress data else raise UnknownTypeException, "type #{type}" end when TTIME Time.at renc when XT_STREAM_MODE @cache = [nil] @stream_mode = true get else raise UnknownTypeException end when TYPE_TEXT, TYPE_BIN s = rbin value s.force_encoding code == TYPE_BIN ? Encoding::BINARY : Encoding::UTF_8 cache_object s s when TYPE_LIST # p "items", value cache_object (list = []) value.times { list << get } list when TYPE_DICT cache_object (dict = {}) value.times { dict[get] = get } dict when TYPE_CREF x = @cache[value] x.freeze if x.is_a?(String) x else raise UnknownTypeException end end
Load the object (object tree) from the stream. Note that if there is more than one object in the stream that are stored with the same Formatter
instance, they will share same cache and references, see Boss
.Formatter.put for details. Note that nil is a valid restored object. Check eof? or catch EOFError, or use Boss
.Parser.each to read all objects from the stream
# File lib/boss-protocol.rb, line 353 def read get end
Private Instance Methods
# File lib/boss-protocol.rb, line 444 def cache_object object # Stream mode? unless @stream_mode @cache << object end end
# File lib/boss-protocol.rb, line 502 def rbin(length) @io.read length end
# File lib/boss-protocol.rb, line 490 def rbyte @rbyte.call end
# File lib/boss-protocol.rb, line 494 def rdouble rbin(8).unpack('E')[0] end
Read variable-length positive integer
# File lib/boss-protocol.rb, line 480 def renc value = i = 0 loop do x = rbyte value |= (x&0x7f) << i return value if x & 0x80 != 0 i += 7 end end
# File lib/boss-protocol.rb, line 498 def rfloat rbin(4).unpack('e')[0] end
Read header and return code,value
# File lib/boss-protocol.rb, line 453 def rhdr b = rbyte code, value = b & 7, b >> 3 case value when 0..22 return code, value when 23...31 return code, rlongint(value-22) else n = renc return code, rlongint(n) end end
read n-bytes long positive integer
# File lib/boss-protocol.rb, line 469 def rlongint(bytes) res = i = 0 bytes.times do res |= rbyte << i i += 8 end res end