Class: Omnizip::Algorithms::LZMA::LzmaAloneDecoder

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb

Overview

Decoder for .lzma (LZMA_Alone) format

This is the legacy LZMA_Alone format used by LZMA Utils 4.32.x. It is DIFFERENT from the XZ format's LZMA2 compression!

File format:

  • Properties (1 byte): encodes lc, lp, pb values
  • Dictionary size (4 bytes, little-endian)
  • Uncompressed size (8 bytes, little-endian, UINT64_MAX = unknown)
  • LZMA1 compressed stream (no footer, no CRC32)

Reference: /Users/mulgogi/src/external/xz/src/liblzma/common/alone_decoder.c

This decoder uses the same LZMA1 decoding engine as XZ format, but with the legacy .lzma container format.

Examples:

Decode .lzma file

data = File.binread("file.lzma")
decoder = Omnizip::Algorithms::LZMA::LzmaAloneDecoder.new(StringIO.new(data))
result = decoder.decode_stream

Constant Summary collapse

MAX_UNCOMPRESSED_SIZE =

Maximum valid uncompressed size (256 GiB) From alone_decoder.c:118

(1 << 38)
MAX_PROPERTY_BYTE =

Property byte validation limits From lzma_decoder.c:1218

(((4 * 5) + 4) * 9) + 8

Instance Method Summary collapse

Constructor Details

#initialize(input, options = {}) ⇒ LzmaAloneDecoder

Initialize the decoder with .lzma format input

Parameters:

  • input (IO)

    Input stream of .lzma compressed data

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

    Decoding options

Options Hash (options):

  • :picky (Boolean)

    If true, reject files unlikely to be .lzma (default: false)

Raises:

  • (RuntimeError)

    If header is invalid or unsupported



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb', line 65

def initialize(input, options = {})
  @input = input
  @picky = options.fetch(:picky, false)

  # Parse .lzma header
  parse_header

  # Create a wrapper stream that starts after the header
  # The XzUtilsDecoder will read from this stream
  @lzma_stream = @input

  # Initialize the XZ Utils LZMA decoder with parsed parameters
  # validate_size=true because .lzma format has explicit uncompressed size
  # allow_eopm=true because .lzma format allows EOPM even with known size
  # Reference: alone_decoder.c:127 (LZMA_LZMA1EXT_ALLOW_EOPM)
  @decoder = XzUtilsDecoder.new(@lzma_stream,
                                lzma2_mode: true,
                                validate_size: true,
                                allow_eopm: true,
                                lc: @lc,
                                lp: @lp,
                                pb: @pb,
                                dict_size: @dict_size,
                                uncompressed_size: @uncompressed_size)
end

Instance Method Details

#decode_stream(output = nil) ⇒ String, Integer

Decode the .lzma stream

Parameters:

  • output (IO, nil) (defaults to: nil)

    Optional output stream

Returns:

  • (String, Integer)

    Decompressed data or bytes written



95
96
97
98
99
# File 'lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb', line 95

def decode_stream(output = nil)
  # .lzma format allows EOPM even when uncompressed size is known
  # Reference: alone_decoder.c:127 (LZMA_LZMA1EXT_ALLOW_EOPM)
  @decoder.decode_stream(output, check_rc_finished: false)
end