Class: ZipKit::Streamer::Heuristic

Inherits:
Writable
  • Object
show all
Includes:
ZlibCleanup
Defined in:
lib/zip_kit/streamer/heuristic.rb

Overview

Will be used to pick whether to store a file in the stored or deflated mode, by compressing the first N bytes of the file and comparing the stored and deflated data sizes. If deflate produces a sizable compression gain for this data, it will create a deflated file inside the ZIP archive. If the file doesn't compress well, it will use the "stored" mode for the entry. About 128KB of the file will be buffered to pick the appropriate storage mode. The Heuristic will call either write_stored_file or write_deflated_file on the Streamer passed into it once it knows which compression method should be applied

Constant Summary collapse

BYTES_WRITTEN_THRESHOLD =
128 * 1024
MINIMUM_VIABLE_COMPRESSION =
0.75

Instance Method Summary collapse

Methods included from ZlibCleanup

#safely_dispose_of_incomplete_deflater

Methods included from WriteShovel

#write

Constructor Details

#initialize(streamer, filename, **write_file_options) ⇒ Heuristic

Returns a new instance of Heuristic.



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/zip_kit/streamer/heuristic.rb', line 21

def initialize(streamer, filename, **write_file_options)
  @streamer = streamer
  @filename = filename
  @write_file_options = write_file_options

  @buf = +"".b # Just use a mutable String
  @deflater = ::Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION, -::Zlib::MAX_WBITS)
  @bytes_deflated = 0

  @winner = nil
  @started_closing = false
end

Instance Method Details

#<<(bytes) ⇒ Object



34
35
36
37
38
39
40
41
42
43
# File 'lib/zip_kit/streamer/heuristic.rb', line 34

def <<(bytes)
  if @winner
    @winner << bytes
  else
    @buf << bytes
    @deflater.deflate(bytes) { |chunk| @bytes_deflated += chunk.bytesize }
    decide if @buf.bytesize > BYTES_WRITTEN_THRESHOLD
  end
  self
end

#closeObject



45
46
47
48
49
50
51
# File 'lib/zip_kit/streamer/heuristic.rb', line 45

def close
  return if @started_closing
  @started_closing = true # started_closing because an exception may get raised inside close(), as we add an entry there

  decide unless @winner
  @winner.close
end

#release_resources_on_failure!Object



53
54
55
56
# File 'lib/zip_kit/streamer/heuristic.rb', line 53

def release_resources_on_failure!
  safely_dispose_of_incomplete_deflater(@deflater)
  @winner&.release_resources_on_failure!
end