Class: Omnizip::Formats::Rar::Rar5::Compression::Lzss

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/formats/rar/rar5/compression/lzss.rb

Overview

RAR5 LZSS compression method

RAR5 compression methods 1-5 use a proprietary LZSS-based algorithm with Huffman coding. This is the algorithm used by official RAR tools.

Based on libarchive/archive_read_support_format_rar5.c

Defined Under Namespace

Classes: BitReader, Decoder, HuffmanTable

Constant Summary collapse

METHOD_STORE =

Compression method identifiers

0
METHOD_FASTEST =
1
METHOD_FAST =
2
METHOD_NORMAL =
3
METHOD_GOOD =
4
METHOD_BEST =
5
HUFF_BC =

Huffman code constants (from libarchive)

20
HUFF_NC =

Number of bit length codes

306
HUFF_DC =

Number of literal/length codes

64
HUFF_LDC =

Number of distance codes

16
HUFF_RC =

Number of low distance codes

44
HUFF_TABLE_SIZE =

Number of repeat codes

HUFF_NC + HUFF_DC + HUFF_LDC + HUFF_RC
DIST_CACHE_SIZE =

Distance cache size

4
MIN_MATCH =

Minimum match length

3

Class Method Summary collapse

Class Method Details

.available?Boolean

Check if LZSS compression is available for official RAR compatibility

Returns:

  • (Boolean)

    true if implemented



44
45
46
47
48
49
50
# File 'lib/omnizip/formats/rar/rar5/compression/lzss.rb', line 44

def available?
  # Decoder is implemented; the encoder is NOT compatible
  # with official RAR tools (unrar "tests" its output as
  # OK while extracting empty files). Callers fall back
  # to STORE until a RAR-compatible encoder lands.
  false
end

.compress(data, options = {}) ⇒ Hash

Compress data using RAR5 LZSS

Parameters:

  • data (String)

    Data to compress

  • options (Hash) (defaults to: {})

    Compression options

Options Hash (options):

  • :level (Integer)

    Compression level (1-5)

  • :dict_size (Integer)

    Dictionary size

Returns:

  • (Hash)

    Hash with :data, :properties, and :method



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/omnizip/formats/rar/rar5/compression/lzss.rb', line 59

def compress(data, options = {})
  level = options[:level] || METHOD_NORMAL
  options[:dict_size] || dictionary_size_for_level(level)

  # For now, use STORE method until encoder is compatible
  # with official RAR tools
  {
    data: data,
    properties: nil,
    method: METHOD_STORE,
  }
end

.compression_info(level = METHOD_NORMAL) ⇒ Integer

Get compression info VINT value

Parameters:

  • level (Integer) (defaults to: METHOD_NORMAL)

    Compression level (1-5)

Returns:

  • (Integer)

    Compression info value



99
100
101
102
# File 'lib/omnizip/formats/rar/rar5/compression/lzss.rb', line 99

def compression_info(level = METHOD_NORMAL)
  method = method_id(level)
  method & 0x3F
end

.decompress(data, options = {}) ⇒ String

Decompress RAR5 LZSS data

Parameters:

  • data (String)

    Compressed data

  • options (Hash) (defaults to: {})

    Decompression options

Options Hash (options):

  • :uncompressed_size (Integer)

    Expected size

  • :window_size (Integer)

    Dictionary size

Returns:

  • (String)

    Decompressed data



79
80
81
82
83
84
85
# File 'lib/omnizip/formats/rar/rar5/compression/lzss.rb', line 79

def decompress(data, options = {})
  uncompressed_size = options[:uncompressed_size]
  window_size = options[:window_size] || (1 << 20) # Default 1MB

  decoder = Decoder.new(data, window_size)
  decoder.decode(uncompressed_size)
end

.method_id(level = METHOD_NORMAL) ⇒ Integer

Get compression method identifier

Parameters:

  • level (Integer) (defaults to: METHOD_NORMAL)

    Compression level (1-5)

Returns:

  • (Integer)

    Method ID



91
92
93
# File 'lib/omnizip/formats/rar/rar5/compression/lzss.rb', line 91

def method_id(level = METHOD_NORMAL)
  level.clamp(METHOD_FASTEST, METHOD_BEST)
end