Class: Omnizip::Formats::Rar::RarFormatBase Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/formats/rar/rar_format_base.rb

Overview

This class is abstract.

Subclass and override #read_archive, #write_archive, #compress, and #decompress to implement a RAR version strategy.

Base class for RAR format implementations

This class provides common functionality for RAR v3 and RAR v5 formats, following the Strategy pattern where each version has its own implementation strategy.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(spec_name) ⇒ RarFormatBase

Initialize a RAR format handler

Parameters:

  • spec_name (String)

    The format specification name (e.g., "rar3", "rar5")



27
28
29
30
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 27

def initialize(spec_name)
  @spec = FormatSpecLoader.load(spec_name)
  @version = @spec.version
end

Instance Attribute Details

#specObject (readonly)

Returns the value of attribute spec.



21
22
23
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 21

def spec
  @spec
end

#versionObject (readonly)

Returns the value of attribute version.



21
22
23
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 21

def version
  @version
end

Instance Method Details

#block_type_code(type) ⇒ Integer

Get block type code from symbol

Parameters:

  • type (Symbol)

    The block type name

Returns:

  • (Integer)

    The block type code

Raises:



132
133
134
135
136
137
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 132

def block_type_code(type)
  code = spec.format.block_types[type]
  return code if code

  raise FormatError, "Unknown block type: #{type}"
end

#block_type_name(code) ⇒ Symbol

Get block type symbol from code

Parameters:

  • code (Integer)

    The block type code

Returns:

  • (Symbol)

    The block type name

Raises:



144
145
146
147
148
149
150
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 144

def block_type_name(code)
  types = spec.format.block_types
  name = types.key(code)
  return name if name

  raise FormatError, "Unknown block type code: #{code}"
end

#compress(data, method: :normal, **options) ⇒ String

Compress data

Parameters:

  • data (String)

    The data to compress

  • method (Symbol) (defaults to: :normal)

    The compression method

  • options (Hash)

    Compression options

Returns:

  • (String)

    The compressed data

Raises:

  • (NotImplementedError)

    Must be implemented by subclasses



60
61
62
63
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 60

def compress(data, method: :normal, **options)
  raise NotImplementedError,
        "#{self.class} must implement #compress"
end

#compression_method_code(method) ⇒ Integer

Get compression method code from symbol

Parameters:

  • method (Symbol)

    The method name (e.g., :normal, :best)

Returns:

  • (Integer)

    The method code

Raises:



93
94
95
96
97
98
99
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 93

def compression_method_code(method)
  code = spec.format.compression_methods[method]
  return code if code

  raise FormatError,
        "Unsupported compression method: #{method}"
end

#compression_method_name(code) ⇒ Symbol

Get compression method symbol from code

Parameters:

  • code (Integer)

    The method code

Returns:

  • (Symbol)

    The method name

Raises:



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 106

def compression_method_name(code)
  methods = spec.format.compression_methods
  name = methods.key(code)
  return name if name

  # Handle unknown method codes gracefully
  # RAR can have version-specific or PPMd methods not in standard list
  case code
  when 0x00..0x2F then :store      # Very old or stored
  when 0x30 then :store
  when 0x31 then :fastest
  when 0x32 then :fast
  when 0x33 then :normal
  when 0x34 then :good
  when 0x35 then :best
  when 0x36..0x40 then :normal     # Extended range
  when 0x80..0xFF then :ppmd       # PPMd or version-specific
  else :unknown
  end
end

#decompress(data, method: :normal, **options) ⇒ String

Decompress data

Parameters:

  • data (String)

    The compressed data

  • method (Symbol) (defaults to: :normal)

    The compression method

  • options (Hash)

    Decompression options

Returns:

  • (String)

    The decompressed data

Raises:

  • (NotImplementedError)

    Must be implemented by subclasses



72
73
74
75
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 72

def decompress(data, method: :normal, **options)
  raise NotImplementedError,
        "#{self.class} must implement #decompress"
end

#dictionary_size_code(level) ⇒ Integer

Get dictionary size for compression level

Parameters:

  • level (Symbol)

    The compression level

Returns:

  • (Integer)

    The dictionary size code



181
182
183
184
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 181

def dictionary_size_code(level)
  spec.format.dictionary_sizes[level] ||
    spec.format.dictionary_sizes[:auto]
end

#encryption_algorithmString?

Get encryption algorithm

Returns:

  • (String, nil)

    The encryption algorithm or nil



170
171
172
173
174
175
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 170

def encryption_algorithm
  return nil unless spec.format.encryption&.supported

  algorithms = spec.format.encryption.algorithms
  algorithms&.first
end

#read_archive(io) ⇒ Array<Entry>

Read a RAR archive

Parameters:

  • io (IO)

    The input stream

Returns:

  • (Array<Entry>)

    The archive entries

Raises:

  • (NotImplementedError)

    Must be implemented by subclasses



37
38
39
40
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 37

def read_archive(io)
  raise NotImplementedError,
        "#{self.class} must implement #read_archive"
end

#supports_feature?(feature) ⇒ Boolean

Check if format supports a feature

Parameters:

  • feature (Symbol)

    The feature name

Returns:

  • (Boolean)

    True if supported



156
157
158
159
160
161
162
163
164
165
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 156

def supports_feature?(feature)
  features = spec.format.features || {}
  compression_features = spec.format.compression_features || {}
  advanced_features = spec.format.advanced_features || {}

  features[feature] ||
    compression_features[feature] ||
    advanced_features[feature] ||
    false
end

#verify_magic_bytes(io) ⇒ Boolean

Verify magic bytes match this format

Parameters:

  • io (IO)

    The input stream

Returns:

  • (Boolean)

    True if magic bytes match



81
82
83
84
85
86
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 81

def verify_magic_bytes(io)
  magic = spec.magic_bytes.pack("C*")
  bytes = io.read(magic.bytesize)
  io.rewind
  bytes == magic
end

#write_archive(io, entries) ⇒ void

This method returns an undefined value.

Write a RAR archive

Parameters:

  • io (IO)

    The output stream

  • entries (Array<Entry>)

    The entries to write

Raises:

  • (NotImplementedError)

    Must be implemented by subclasses



48
49
50
51
# File 'lib/omnizip/formats/rar/rar_format_base.rb', line 48

def write_archive(io, entries)
  raise NotImplementedError,
        "#{self.class} must implement #write_archive"
end