Class: Omnizip::Formats::Rar::Compression::PPMd::Decoder

Inherits:
Algorithms::PPMd7::Decoder show all
Defined in:
lib/omnizip/formats/rar/compression/ppmd/decoder.rb

Overview

RAR PPMd variant H decoder

Implements decoding for RAR's PPMd variant H compression method. This adapts the standard PPMd7 algorithm for RAR-specific requirements:

  • Different memory model initialization
  • RAR-specific escape code handling
  • Modified context order selection
  • Different binary symbol encoding

Responsibilities:

  • ONE responsibility: Decode RAR PPMd variant H compressed data
  • Manage decoder state and context
  • Transform compressed bits to original bytes
  • Maintain synchronized model state

Constant Summary collapse

RAR_MAX_ORDER =

RAR variant H specific constants

16
RAR_MIN_ORDER =
2
RAR_DEFAULT_ORDER =
6
RAR_MEM_MULTIPLIER =

RAR memory size multiplier (MB to bytes)

1024 * 1024

Instance Attribute Summary

Attributes inherited from Algorithms::PPMd7::Decoder

#model

Instance Method Summary collapse

Constructor Details

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

Initialize the RAR PPMd decoder

Parameters:

  • input (IO)

    Input stream of compressed data

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

    Decoding options

Options Hash (options):

  • :model_order (Integer)

    Maximum context order

  • :mem_size (Integer)

    Memory size in MB for RAR



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/omnizip/formats/rar/compression/ppmd/decoder.rb', line 59

def initialize(input, options = {})
  @input = input
  @options = options

  # RAR uses memory size in MB, convert to bytes
  mem_size_mb = options[:mem_size] || 16
  mem_size_bytes = mem_size_mb * RAR_MEM_MULTIPLIER

  # Initialize model with RAR parameters
  @model = initialize_rar_model(
    options[:model_order] || RAR_DEFAULT_ORDER,
    mem_size_bytes,
  )

  # Use standard range decoder
  @range_decoder = Omnizip::Algorithms::LZMA::RangeDecoder.new(input)
end

Instance Method Details

#decode_stream(max_bytes = nil) ⇒ String

Decode a stream back to original bytes

RAR variant H decoding process:

  1. Read compressed bits using range decoder
  2. Use model to find corresponding symbol
  3. Update model to stay synchronized
  4. Handle RAR-specific escape codes

Parameters:

  • max_bytes (Integer, nil) (defaults to: nil)

    Maximum bytes to decode

Returns:

  • (String)

    Decoded data



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/omnizip/formats/rar/compression/ppmd/decoder.rb', line 87

def decode_stream(max_bytes = nil)
  result = String.new(encoding: Encoding::BINARY)

  loop do
    # Stop if we've decoded enough bytes
    break if max_bytes && result.length >= max_bytes

    symbol = decode_symbol
    break if symbol.nil?

    result << symbol.chr
  rescue EOFError
    # End of compressed data - stop decoding
    break
  rescue Omnizip::DecompressionError
    # If we have some data and hit an error, it might be end of stream
    # Otherwise, re-raise the error
    break if result.length.positive?

    raise
  end

  result
end