Class: SimpleData::IOCompressedRead

Inherits:
Object
  • Object
show all
Defined in:
lib/simple-data/compression.rb

Instance Method Summary collapse

Constructor Details

#initialize(io, read: 16 * 1024) ⇒ IOCompressedRead

Returns a new instance of IOCompressedRead.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/simple-data/compression.rb', line 42

def initialize(io, read: 16 * 1024)
    @io         = io
    @sio        = StringIO.new
    @read_size  = read

    # Peek at data for magic number
    pos = io.tell
    max = MAGIC.keys.map(&:size).max
    str = io.read(max)
    io.seek(pos)

    # Magic number lookup
    type = MAGIC.find {|k, v| str.start_with?(k) }&.last

    # Sanity check
    raise "data is not Zstd compressed" if type != :zstd

    # Decoder
    zstd = Zstd::StreamingDecompress.new
    @decoder = ->(str) { zstd.decompress(str) }
end

Instance Method Details

#closeObject



76
77
78
# File 'lib/simple-data/compression.rb', line 76

def close
    @io.close
end

#each_byte(&block) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/simple-data/compression.rb', line 106

def each_byte(&block)
    return to_enum(:each_byte) if block.nil?
    loop do
        @sio.each_byte(&block)
        break unless cstr = @io.read(@read_size)
        @sio.string = @decoder.call(cstr)
    end
end

#eof?Boolean

Returns:

  • (Boolean)


64
65
66
67
68
69
70
71
72
73
74
# File 'lib/simple-data/compression.rb', line 64

def eof?
    return false unless @sio.eof?
    return true  if     @io.eof?

    # Refill
    cstr = @io.read(@read_size)
    @sio.string = @decoder.call(cstr)

    # Recheck
    @io.eof? && @sio.eof?
end

#read(size) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/simple-data/compression.rb', line 80

def read(size)
    data = @sio.read(size)

    # End of buffer
    if data.nil?
        if cstr = @io.read(@read_size)
            # Refill buffer
            @sio.string = @decoder.call(cstr)
            read(size)
        else
            # End of stream
            nil
        end

    # Partial buffer
    elsif data.size < size
        # Force a new read (will trigger a refill)
        odata = read(size - data.size)
        odata.nil? ? data : (data + odata)

    # Full data
    else
        data
    end
end