omnizip 0.4.7-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +293 -0
- data/CHANGELOG.md +1647 -0
- data/CONTEXT.md +68 -0
- data/COPYING +502 -0
- data/Gemfile +19 -0
- data/LICENSE +12 -0
- data/README.adoc +1327 -0
- data/Rakefile +15 -0
- data/TODO.refactor/00-overview.md +67 -0
- data/TODO.refactor/01-registry-base-class.md +81 -0
- data/TODO.refactor/02-error-hierarchy.md +57 -0
- data/TODO.refactor/03-autoload-entry-point.md +69 -0
- data/TODO.refactor/04-filter-base-consolidation.md +49 -0
- data/TODO.refactor/05-send-private-methods.md +64 -0
- data/TODO.refactor/06-instance-variable-access.md +69 -0
- data/TODO.refactor/07-respond-to-replacement.md +237 -0
- data/TODO.refactor/08-spec-doubles.md +27 -0
- data/TODO.refactor/09-cli-shared-module.md +35 -0
- data/TODO.refactor/10-format-detector-ocp.md +34 -0
- data/TODO.refactor/11-convenience-decoupling.md +38 -0
- data/TODO.refactor/12-thread-safety.md +8 -0
- data/TODO.refactor/13-lutaml-model-migration.md +158 -0
- data/TODO.refactor/14-add-missing-specs.md +25 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +92 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +263 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +183 -0
- data/docs/getting-started/your-first-archive.adoc +219 -0
- data/docs/guides/advanced-features/encryption.adoc +277 -0
- data/docs/guides/advanced-features/index.adoc +59 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
- data/docs/guides/advanced-features/streaming.adoc +142 -0
- data/docs/guides/archive-formats/gzip-format.adoc +105 -0
- data/docs/guides/archive-formats/index.adoc +160 -0
- data/docs/guides/archive-formats/ole-format.adoc +151 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/rpm-format.adoc +108 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
- data/docs/guides/compression-algorithms/deflate.adoc +313 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +394 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
- data/docs/guides/creating-archives.adoc +348 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +228 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +187 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/rust-backend.md +0 -0
- data/docs/troubleshooting/index.adoc +207 -0
- data/docs/xar_format.md +216 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +176 -0
- data/lib/omnizip/algorithm_registry.rb +65 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
- data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
- data/lib/omnizip/algorithms/bzip2.rb +108 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
- data/lib/omnizip/algorithms/deflate.rb +135 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
- data/lib/omnizip/algorithms/deflate64.rb +118 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
- data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
- data/lib/omnizip/algorithms/lzma.rb +266 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +133 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +146 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +122 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
- data/lib/omnizip/algorithms/registration.rb +28 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
- data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
- data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
- data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
- data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
- data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +210 -0
- data/lib/omnizip/algorithms.rb +35 -0
- data/lib/omnizip/archive/builder.rb +48 -0
- data/lib/omnizip/archive/reader_session.rb +67 -0
- data/lib/omnizip/archive.rb +86 -0
- data/lib/omnizip/archive_handler.rb +82 -0
- data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
- data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
- data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
- data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
- data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
- data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
- data/lib/omnizip/archive_handlers.rb +18 -0
- data/lib/omnizip/backends.rb +160 -0
- data/lib/omnizip/buffer/memory_archive.rb +246 -0
- data/lib/omnizip/buffer/memory_extractor.rb +234 -0
- data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
- data/lib/omnizip/buffer.rb +187 -0
- data/lib/omnizip/checksum_registry.rb +41 -0
- data/lib/omnizip/checksums/crc32.rb +101 -0
- data/lib/omnizip/checksums/crc64.rb +102 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/registration.rb +16 -0
- data/lib/omnizip/checksums/verifier.rb +130 -0
- data/lib/omnizip/checksums.rb +11 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +123 -0
- data/lib/omnizip/chunked.rb +123 -0
- data/lib/omnizip/cli/output_formatter.rb +112 -0
- data/lib/omnizip/cli.rb +604 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +245 -0
- data/lib/omnizip/commands/archive_extract_command.rb +231 -0
- data/lib/omnizip/commands/archive_list_command.rb +204 -0
- data/lib/omnizip/commands/archive_repair_command.rb +129 -0
- data/lib/omnizip/commands/archive_verify_command.rb +115 -0
- data/lib/omnizip/commands/compress_command.rb +115 -0
- data/lib/omnizip/commands/decompress_command.rb +149 -0
- data/lib/omnizip/commands/list_command.rb +51 -0
- data/lib/omnizip/commands/metadata_command.rb +215 -0
- data/lib/omnizip/commands/parity_create_command.rb +114 -0
- data/lib/omnizip/commands/parity_repair_command.rb +120 -0
- data/lib/omnizip/commands/parity_verify_command.rb +122 -0
- data/lib/omnizip/commands/profile_list_command.rb +54 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/commands.rb +21 -0
- data/lib/omnizip/convenience.rb +389 -0
- data/lib/omnizip/converter/conversion_registry.rb +50 -0
- data/lib/omnizip/converter/conversion_strategy.rb +108 -0
- data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
- data/lib/omnizip/converter.rb +124 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/crypto.rb +11 -0
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/error.rb +110 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +68 -0
- data/lib/omnizip/extraction/filter_chain.rb +179 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +247 -0
- data/lib/omnizip/extraction.rb +115 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +117 -0
- data/lib/omnizip/filter.rb +141 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +113 -0
- data/lib/omnizip/filters/bcj.rb +277 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
- data/lib/omnizip/filters/bcj2.rb +93 -0
- data/lib/omnizip/filters/bcj_arm.rb +174 -0
- data/lib/omnizip/filters/bcj_arm64.rb +242 -0
- data/lib/omnizip/filters/bcj_ia64.rb +194 -0
- data/lib/omnizip/filters/bcj_ppc.rb +188 -0
- data/lib/omnizip/filters/bcj_sparc.rb +174 -0
- data/lib/omnizip/filters/bcj_x86.rb +191 -0
- data/lib/omnizip/filters/delta.rb +195 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/filters.rb +20 -0
- data/lib/omnizip/format_detector.rb +166 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +159 -0
- data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +389 -0
- data/lib/omnizip/formats/cpio/reader.rb +194 -0
- data/lib/omnizip/formats/cpio/writer.rb +232 -0
- data/lib/omnizip/formats/cpio.rb +132 -0
- data/lib/omnizip/formats/format_spec_loader.rb +228 -0
- data/lib/omnizip/formats/gzip.rb +236 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
- data/lib/omnizip/formats/iso/directory_record.rb +162 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +194 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +543 -0
- data/lib/omnizip/formats/iso.rb +133 -0
- data/lib/omnizip/formats/lzip.rb +161 -0
- data/lib/omnizip/formats/lzma_alone.rb +149 -0
- data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
- data/lib/omnizip/formats/msi/constants.rb +157 -0
- data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
- data/lib/omnizip/formats/msi/entry.rb +134 -0
- data/lib/omnizip/formats/msi/reader.rb +301 -0
- data/lib/omnizip/formats/msi/string_pool.rb +246 -0
- data/lib/omnizip/formats/msi/table_parser.rb +244 -0
- data/lib/omnizip/formats/msi.rb +73 -0
- data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
- data/lib/omnizip/formats/ole/constants.rb +61 -0
- data/lib/omnizip/formats/ole/dirent.rb +439 -0
- data/lib/omnizip/formats/ole/header.rb +199 -0
- data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
- data/lib/omnizip/formats/ole/storage.rb +482 -0
- data/lib/omnizip/formats/ole/types/variant.rb +338 -0
- data/lib/omnizip/formats/ole.rb +143 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
- data/lib/omnizip/formats/rar/block_parser.rb +282 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
- data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
- data/lib/omnizip/formats/rar/compression.rb +17 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +88 -0
- data/lib/omnizip/formats/rar/decompressor.rb +316 -0
- data/lib/omnizip/formats/rar/external_writer.rb +311 -0
- data/lib/omnizip/formats/rar/header.rb +209 -0
- data/lib/omnizip/formats/rar/license_validator.rb +111 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/models.rb +14 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
- data/lib/omnizip/formats/rar/reader.rb +377 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
- data/lib/omnizip/formats/rar/writer.rb +437 -0
- data/lib/omnizip/formats/rar.rb +193 -0
- data/lib/omnizip/formats/rar3/compressor.rb +71 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar3/reader.rb +107 -0
- data/lib/omnizip/formats/rar3/writer.rb +220 -0
- data/lib/omnizip/formats/rar3.rb +15 -0
- data/lib/omnizip/formats/rar5/compressor.rb +71 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar5/reader.rb +130 -0
- data/lib/omnizip/formats/rar5/writer.rb +65 -0
- data/lib/omnizip/formats/rar5.rb +15 -0
- data/lib/omnizip/formats/rpm/constants.rb +58 -0
- data/lib/omnizip/formats/rpm/entry.rb +106 -0
- data/lib/omnizip/formats/rpm/header.rb +106 -0
- data/lib/omnizip/formats/rpm/lead.rb +132 -0
- data/lib/omnizip/formats/rpm/tag.rb +228 -0
- data/lib/omnizip/formats/rpm/writer.rb +652 -0
- data/lib/omnizip/formats/rpm.rb +458 -0
- data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
- data/lib/omnizip/formats/seven_zip/header.rb +102 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/models.rb +20 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
- data/lib/omnizip/formats/seven_zip.rb +179 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +98 -0
- data/lib/omnizip/formats/tar/header.rb +206 -0
- data/lib/omnizip/formats/tar/reader.rb +119 -0
- data/lib/omnizip/formats/tar/writer.rb +212 -0
- data/lib/omnizip/formats/tar.rb +74 -0
- data/lib/omnizip/formats/xar/constants.rb +119 -0
- data/lib/omnizip/formats/xar/entry.rb +268 -0
- data/lib/omnizip/formats/xar/header.rb +223 -0
- data/lib/omnizip/formats/xar/reader.rb +400 -0
- data/lib/omnizip/formats/xar/toc.rb +570 -0
- data/lib/omnizip/formats/xar/writer.rb +461 -0
- data/lib/omnizip/formats/xar.rb +145 -0
- data/lib/omnizip/formats/xz/reader.rb +121 -0
- data/lib/omnizip/formats/xz/writer.rb +416 -0
- data/lib/omnizip/formats/xz.rb +210 -0
- data/lib/omnizip/formats/xz_const.rb +49 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl.rb +52 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
- data/lib/omnizip/formats/zip/reader.rb +376 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +489 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/formats.rb +29 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/base.rb +19 -0
- data/lib/omnizip/implementations/rust/archive.rb +93 -0
- data/lib/omnizip/implementations/rust/library.rb +221 -0
- data/lib/omnizip/implementations/rust.rb +26 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
- data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
- data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
- data/lib/omnizip/implementations/seven_zip.rb +11 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
- data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
- data/lib/omnizip/implementations/xz_utils.rb +10 -0
- data/lib/omnizip/implementations.rb +25 -0
- data/lib/omnizip/io/buffered_input.rb +147 -0
- data/lib/omnizip/io/buffered_output.rb +106 -0
- data/lib/omnizip/io/source.rb +143 -0
- data/lib/omnizip/io/stream_manager.rb +117 -0
- data/lib/omnizip/io.rb +15 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +129 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +153 -0
- data/lib/omnizip/metadata/metadata_editor.rb +169 -0
- data/lib/omnizip/metadata/metadata_registry.rb +71 -0
- data/lib/omnizip/metadata/metadata_validator.rb +101 -0
- data/lib/omnizip/metadata.rb +58 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +41 -0
- data/lib/omnizip/models/attribute_apply.rb +40 -0
- data/lib/omnizip/models/compression_options.rb +53 -0
- data/lib/omnizip/models/conversion_options.rb +79 -0
- data/lib/omnizip/models/conversion_result.rb +141 -0
- data/lib/omnizip/models/eta_result.rb +45 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +142 -0
- data/lib/omnizip/models/filter_config.rb +148 -0
- data/lib/omnizip/models/match_result.rb +141 -0
- data/lib/omnizip/models/optimization_suggestion.rb +95 -0
- data/lib/omnizip/models/parallel_options.rb +116 -0
- data/lib/omnizip/models/performance_result.rb +85 -0
- data/lib/omnizip/models/profile_report.rb +116 -0
- data/lib/omnizip/models/progress_options.rb +39 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +45 -0
- data/lib/omnizip/parallel/engine.rb +52 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +225 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
- data/lib/omnizip/parallel/thread_pool.rb +60 -0
- data/lib/omnizip/parallel/worker_pool.rb +227 -0
- data/lib/omnizip/parallel.rb +156 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +71 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
- data/lib/omnizip/parity/models/main_packet.rb +126 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +102 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
- data/lib/omnizip/parity/models.rb +27 -0
- data/lib/omnizip/parity/par2_creator.rb +496 -0
- data/lib/omnizip/parity/par2_repairer.rb +409 -0
- data/lib/omnizip/parity/par2_verifier.rb +373 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
- data/lib/omnizip/parity.rb +207 -0
- data/lib/omnizip/password/encryption_registry.rb +26 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
- data/lib/omnizip/password.rb +88 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
- data/lib/omnizip/pipe.rb +120 -0
- data/lib/omnizip/platform/ntfs_streams.rb +200 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +36 -0
- data/lib/omnizip/profile/balanced_profile.rb +31 -0
- data/lib/omnizip/profile/binary_profile.rb +33 -0
- data/lib/omnizip/profile/compression_profile.rb +157 -0
- data/lib/omnizip/profile/custom_profile.rb +155 -0
- data/lib/omnizip/profile/fast_profile.rb +31 -0
- data/lib/omnizip/profile/maximum_profile.rb +31 -0
- data/lib/omnizip/profile/profile_detector.rb +108 -0
- data/lib/omnizip/profile/profile_registry.rb +160 -0
- data/lib/omnizip/profile/text_profile.rb +33 -0
- data/lib/omnizip/profile.rb +261 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +158 -0
- data/lib/omnizip/profiler.rb +192 -0
- data/lib/omnizip/progress/callback_reporter.rb +34 -0
- data/lib/omnizip/progress/console_reporter.rb +59 -0
- data/lib/omnizip/progress/log_reporter.rb +89 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +215 -0
- data/lib/omnizip/progress/silent_reporter.rb +22 -0
- data/lib/omnizip/progress.rb +131 -0
- data/lib/omnizip/registry.rb +111 -0
- data/lib/omnizip/rubyzip_compat.rb +61 -0
- data/lib/omnizip/temp/safe_extract.rb +124 -0
- data/lib/omnizip/temp/temp_file.rb +123 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +184 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +160 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +270 -0
- data/lib/omnizip/zip/output_stream.rb +320 -0
- data/lib/omnizip/zip.rb +23 -0
- data/lib/omnizip.rb +157 -0
- data/lib/tasks/msi_test_files.rake +66 -0
- data/lib/tasks/platform_gems.rake +147 -0
- data/lib/tasks/rust_backend.rake +48 -0
- data/readme-docs/advanced-features.adoc +514 -0
- data/readme-docs/api-usage.adoc +445 -0
- data/readme-docs/architecture.adoc +450 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +446 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +316 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/vendor/libomnizip_ffi.so +0 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +768 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
# to deal in the Software without restriction, including without limitation
|
|
8
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
# DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
module Omnizip
|
|
24
|
+
module Formats
|
|
25
|
+
module Rar
|
|
26
|
+
module Compression
|
|
27
|
+
# Bit-level I/O stream for RAR compression algorithms
|
|
28
|
+
#
|
|
29
|
+
# Provides methods to read and write individual bits from byte streams.
|
|
30
|
+
# This is a shared utility used by PPMd, LZ77+Huffman, and other RAR
|
|
31
|
+
# compression algorithms that need bit-level access.
|
|
32
|
+
#
|
|
33
|
+
# Responsibilities:
|
|
34
|
+
# - ONE responsibility: Bit-level I/O operations
|
|
35
|
+
# - Read bits from byte stream
|
|
36
|
+
# - Write bits to byte stream
|
|
37
|
+
# - Manage bit buffer and byte alignment
|
|
38
|
+
class BitStream
|
|
39
|
+
# Initialize a new bit stream
|
|
40
|
+
#
|
|
41
|
+
# @param io [IO] The underlying byte stream
|
|
42
|
+
# @param mode [Symbol] :read or :write
|
|
43
|
+
def initialize(io, mode = :read)
|
|
44
|
+
@io = io
|
|
45
|
+
@mode = mode
|
|
46
|
+
@buffer = 0
|
|
47
|
+
@bits_in_buffer = 0
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Read specified number of bits
|
|
51
|
+
#
|
|
52
|
+
# @param count [Integer] Number of bits to read (1-32)
|
|
53
|
+
# @return [Integer] The bits read as an integer
|
|
54
|
+
def read_bits(count)
|
|
55
|
+
unless @mode == :read
|
|
56
|
+
raise ArgumentError,
|
|
57
|
+
"Can only read in read mode"
|
|
58
|
+
end
|
|
59
|
+
raise ArgumentError, "Count must be 1-32" unless count.between?(1,
|
|
60
|
+
32)
|
|
61
|
+
|
|
62
|
+
result = 0
|
|
63
|
+
|
|
64
|
+
count.times do
|
|
65
|
+
result = (result << 1) | read_bit
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
result
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Read a single bit
|
|
72
|
+
#
|
|
73
|
+
# @return [Integer] 0 or 1
|
|
74
|
+
def read_bit
|
|
75
|
+
unless @mode == :read
|
|
76
|
+
raise ArgumentError,
|
|
77
|
+
"Can only read in read mode"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if @bits_in_buffer.zero?
|
|
81
|
+
fill_buffer
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
@bits_in_buffer -= 1
|
|
85
|
+
(@buffer >> @bits_in_buffer) & 1
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Write specified number of bits
|
|
89
|
+
#
|
|
90
|
+
# @param value [Integer] The value to write
|
|
91
|
+
# @param count [Integer] Number of bits to write (1-32)
|
|
92
|
+
# @return [void]
|
|
93
|
+
def write_bits(value, count)
|
|
94
|
+
unless @mode == :write
|
|
95
|
+
raise ArgumentError,
|
|
96
|
+
"Can only write in write mode"
|
|
97
|
+
end
|
|
98
|
+
raise ArgumentError, "Count must be 1-32" unless count.between?(1,
|
|
99
|
+
32)
|
|
100
|
+
|
|
101
|
+
count.times do |i|
|
|
102
|
+
bit = (value >> (count - 1 - i)) & 1
|
|
103
|
+
write_bit(bit)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Write a single bit
|
|
108
|
+
#
|
|
109
|
+
# @param bit [Integer] 0 or 1
|
|
110
|
+
# @return [void]
|
|
111
|
+
def write_bit(bit)
|
|
112
|
+
unless @mode == :write
|
|
113
|
+
raise ArgumentError,
|
|
114
|
+
"Can only write in write mode"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
@buffer = (@buffer << 1) | (bit & 1)
|
|
118
|
+
@bits_in_buffer += 1
|
|
119
|
+
|
|
120
|
+
flush_buffer if @bits_in_buffer == 8
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Align to byte boundary (read mode)
|
|
124
|
+
#
|
|
125
|
+
# @return [void]
|
|
126
|
+
def align_to_byte
|
|
127
|
+
return unless @mode == :read
|
|
128
|
+
|
|
129
|
+
@bits_in_buffer = 0
|
|
130
|
+
@buffer = 0
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Flush any remaining bits (write mode)
|
|
134
|
+
#
|
|
135
|
+
# @return [void]
|
|
136
|
+
def flush
|
|
137
|
+
return unless @mode == :write
|
|
138
|
+
return if @bits_in_buffer.zero?
|
|
139
|
+
|
|
140
|
+
# Pad with zeros to complete byte
|
|
141
|
+
padding = 8 - @bits_in_buffer
|
|
142
|
+
@buffer <<= padding
|
|
143
|
+
@io.write([@buffer].pack("C"))
|
|
144
|
+
@buffer = 0
|
|
145
|
+
@bits_in_buffer = 0
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Check if at end of stream
|
|
149
|
+
#
|
|
150
|
+
# @return [Boolean] True if no more data available
|
|
151
|
+
def eof?
|
|
152
|
+
@mode == :read && @bits_in_buffer.zero? && @io.eof?
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
private
|
|
156
|
+
|
|
157
|
+
# Fill buffer with next byte from stream
|
|
158
|
+
#
|
|
159
|
+
# @return [void]
|
|
160
|
+
def fill_buffer
|
|
161
|
+
byte = @io.read(1)
|
|
162
|
+
raise EOFError, "Unexpected end of stream" if byte.nil?
|
|
163
|
+
|
|
164
|
+
@buffer = byte.unpack1("C")
|
|
165
|
+
@bits_in_buffer = 8
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Flush full buffer byte to stream
|
|
169
|
+
#
|
|
170
|
+
# @return [void]
|
|
171
|
+
def flush_buffer
|
|
172
|
+
@io.write([@buffer].pack("C"))
|
|
173
|
+
@buffer = 0
|
|
174
|
+
@bits_in_buffer = 0
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module Rar
|
|
6
|
+
module Compression
|
|
7
|
+
# Algorithm dispatcher for RAR compression
|
|
8
|
+
#
|
|
9
|
+
# Selects appropriate compression algorithm based on RAR method
|
|
10
|
+
# and dispatches to correct encoder/decoder.
|
|
11
|
+
#
|
|
12
|
+
# Responsibilities:
|
|
13
|
+
# - Algorithm selection based on compression method
|
|
14
|
+
# - Dispatch to appropriate decoder/encoder
|
|
15
|
+
# - Error handling for unsupported/unknown methods
|
|
16
|
+
#
|
|
17
|
+
# Note: Does NOT perform actual compression/decompression
|
|
18
|
+
# (delegated to decoder/encoder classes)
|
|
19
|
+
class Dispatcher
|
|
20
|
+
# RAR compression methods
|
|
21
|
+
METHOD_STORE = 0x30 # No compression
|
|
22
|
+
METHOD_FASTEST = 0x31 # LZ77+Huffman (fast)
|
|
23
|
+
METHOD_FAST = 0x32 # LZ77+Huffman
|
|
24
|
+
METHOD_NORMAL = 0x33 # LZ77+Huffman (default)
|
|
25
|
+
METHOD_GOOD = 0x34 # LZ77+Huffman or PPMd
|
|
26
|
+
METHOD_BEST = 0x35 # PPMd
|
|
27
|
+
|
|
28
|
+
# Custom errors
|
|
29
|
+
class UnsupportedMethodError < StandardError; end
|
|
30
|
+
class DecompressionError < StandardError; end
|
|
31
|
+
class CompressionError < StandardError; end
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
# Decompress data using appropriate algorithm
|
|
35
|
+
#
|
|
36
|
+
# @param method [Integer] RAR compression method (0x30-0x35)
|
|
37
|
+
# @param input [IO] Input stream
|
|
38
|
+
# @param output [IO] Output stream
|
|
39
|
+
# @param options [Hash] Decoder options
|
|
40
|
+
# @raise [UnsupportedMethodError] if method unknown
|
|
41
|
+
# @raise [DecompressionError] if decompression fails
|
|
42
|
+
def decompress(method, input, output, options = {})
|
|
43
|
+
case method
|
|
44
|
+
when METHOD_STORE
|
|
45
|
+
decompress_store(input, output)
|
|
46
|
+
when METHOD_FASTEST, METHOD_FAST, METHOD_NORMAL
|
|
47
|
+
decompress_lz77_huffman(input, output, options)
|
|
48
|
+
when METHOD_GOOD
|
|
49
|
+
decompress_good(input, output, options)
|
|
50
|
+
when METHOD_BEST
|
|
51
|
+
decompress_ppmd(input, output, options)
|
|
52
|
+
else
|
|
53
|
+
raise UnsupportedMethodError,
|
|
54
|
+
"Unknown compression method: 0x#{method.to_s(16).upcase}"
|
|
55
|
+
end
|
|
56
|
+
rescue StandardError => e
|
|
57
|
+
unless e.is_a?(UnsupportedMethodError)
|
|
58
|
+
raise DecompressionError,
|
|
59
|
+
"Decompression failed: #{e.message}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
raise
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Compress data using appropriate algorithm
|
|
66
|
+
#
|
|
67
|
+
# @param method [Integer] RAR compression method
|
|
68
|
+
# @param input [IO] Input stream
|
|
69
|
+
# @param output [IO] Output stream
|
|
70
|
+
# @param options [Hash] Encoder options
|
|
71
|
+
# @raise [UnsupportedMethodError] if method unknown
|
|
72
|
+
# @raise [CompressionError] if compression fails
|
|
73
|
+
# @raise [NotImplementedError] for methods not yet implemented
|
|
74
|
+
def compress(method, input, output, options = {})
|
|
75
|
+
case method
|
|
76
|
+
when METHOD_STORE
|
|
77
|
+
compress_store(input, output)
|
|
78
|
+
when METHOD_FASTEST, METHOD_FAST, METHOD_NORMAL
|
|
79
|
+
compress_lz77_huffman(input, output, options)
|
|
80
|
+
when METHOD_GOOD
|
|
81
|
+
compress_good(input, output, options)
|
|
82
|
+
when METHOD_BEST
|
|
83
|
+
compress_ppmd(input, output, options)
|
|
84
|
+
else
|
|
85
|
+
raise UnsupportedMethodError,
|
|
86
|
+
"Unknown compression method: 0x#{method.to_s(16).upcase}"
|
|
87
|
+
end
|
|
88
|
+
rescue StandardError => e
|
|
89
|
+
raise CompressionError, "Compression failed: #{e.message}" unless
|
|
90
|
+
e.is_a?(UnsupportedMethodError) || e.is_a?(NotImplementedError)
|
|
91
|
+
|
|
92
|
+
raise
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
# Decompress METHOD_STORE (no compression)
|
|
98
|
+
#
|
|
99
|
+
# @param input [IO] Input stream
|
|
100
|
+
# @param output [IO] Output stream
|
|
101
|
+
def decompress_store(input, output)
|
|
102
|
+
# Direct copy, no decompression needed
|
|
103
|
+
::IO.copy_stream(input, output)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Decompress using LZ77+Huffman decoder
|
|
107
|
+
#
|
|
108
|
+
# @param input [IO] Input stream
|
|
109
|
+
# @param output [IO] Output stream
|
|
110
|
+
# @param options [Hash] Decoder options
|
|
111
|
+
def decompress_lz77_huffman(input, output, options)
|
|
112
|
+
decoder = LZ77Huffman::Decoder.new(input, options)
|
|
113
|
+
decoded_data = decoder.decode
|
|
114
|
+
output.write(decoded_data)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Decompress METHOD_GOOD (adaptive)
|
|
118
|
+
#
|
|
119
|
+
# For now, default to LZ77+Huffman
|
|
120
|
+
# In future, could analyze content to choose algorithm
|
|
121
|
+
#
|
|
122
|
+
# @param input [IO] Input stream
|
|
123
|
+
# @param output [IO] Output stream
|
|
124
|
+
# @param options [Hash] Decoder options
|
|
125
|
+
def decompress_good(input, output, options)
|
|
126
|
+
# METHOD_GOOD maps to the same LZ77+Huffman pipeline as
|
|
127
|
+
# METHOD_NORMAL; the RAR method byte distinguishes
|
|
128
|
+
# effort levels, not algorithms, and the omnizip-rs
|
|
129
|
+
# reference decodes both identically.
|
|
130
|
+
decompress_lz77_huffman(input, output, options)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Decompress using PPMd decoder
|
|
134
|
+
#
|
|
135
|
+
# @param input [IO] Input stream
|
|
136
|
+
# @param output [IO] Output stream
|
|
137
|
+
# @param options [Hash] Decoder options
|
|
138
|
+
def decompress_ppmd(input, output, options)
|
|
139
|
+
decoder = PPMd::Decoder.new(input, options)
|
|
140
|
+
decoded_data = decoder.decode_stream
|
|
141
|
+
output.write(decoded_data)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Compress METHOD_STORE (no compression)
|
|
145
|
+
#
|
|
146
|
+
# @param input [IO] Input stream
|
|
147
|
+
# @param output [IO] Output stream
|
|
148
|
+
def compress_store(input, output)
|
|
149
|
+
# Direct copy, no compression
|
|
150
|
+
::IO.copy_stream(input, output)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Compress using LZ77+Huffman encoder
|
|
154
|
+
#
|
|
155
|
+
# @param input [IO] Input stream
|
|
156
|
+
# @param output [IO] Output stream
|
|
157
|
+
# @param options [Hash] Encoder options
|
|
158
|
+
def compress_lz77_huffman(input, output, options)
|
|
159
|
+
encoder = LZ77Huffman::Encoder.new(output, options)
|
|
160
|
+
encoder.encode(input)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Compress METHOD_GOOD (adaptive)
|
|
164
|
+
#
|
|
165
|
+
# For now, default to LZ77+Huffman
|
|
166
|
+
# In future, could analyze content to choose algorithm
|
|
167
|
+
#
|
|
168
|
+
# @param input [IO] Input stream
|
|
169
|
+
# @param output [IO] Output stream
|
|
170
|
+
# @param options [Hash] Encoder options
|
|
171
|
+
def compress_good(input, output, options)
|
|
172
|
+
# METHOD_GOOD compresses with the same LZ77+Huffman
|
|
173
|
+
# pipeline as METHOD_NORMAL (see decompress_good); the
|
|
174
|
+
# method byte records the writer's effort level only.
|
|
175
|
+
compress_lz77_huffman(input, output, options)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Compress using PPMd encoder
|
|
179
|
+
#
|
|
180
|
+
# @param input [IO] Input stream
|
|
181
|
+
# @param output [IO] Output stream
|
|
182
|
+
# @param options [Hash] Encoder options
|
|
183
|
+
def compress_ppmd(input, output, options)
|
|
184
|
+
encoder = PPMd::Encoder.new(output, options)
|
|
185
|
+
encoder.encode_stream(input)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Select decoder class for method (for testing)
|
|
189
|
+
#
|
|
190
|
+
# @param method [Integer] Compression method
|
|
191
|
+
# @return [Class, nil] Decoder class or nil for METHOD_STORE
|
|
192
|
+
def select_decoder(method)
|
|
193
|
+
case method
|
|
194
|
+
when METHOD_STORE
|
|
195
|
+
nil
|
|
196
|
+
when METHOD_FASTEST, METHOD_FAST, METHOD_NORMAL, METHOD_GOOD
|
|
197
|
+
LZ77Huffman::Decoder
|
|
198
|
+
when METHOD_BEST
|
|
199
|
+
PPMd::Decoder
|
|
200
|
+
else
|
|
201
|
+
raise UnsupportedMethodError,
|
|
202
|
+
"Unknown compression method: 0x#{method.to_s(16).upcase}"
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
6
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
7
|
+
# to deal in the Software without restriction, including without limitation
|
|
8
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
9
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
10
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
|
13
|
+
# all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
21
|
+
# DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
module Omnizip
|
|
24
|
+
module Formats
|
|
25
|
+
module Rar
|
|
26
|
+
module Compression
|
|
27
|
+
module LZ77Huffman
|
|
28
|
+
# RAR LZ77+Huffman decoder
|
|
29
|
+
#
|
|
30
|
+
# Orchestrates the decoding of RAR METHOD_NORMAL compressed data.
|
|
31
|
+
# Combines Huffman coding with LZ77 sliding window compression.
|
|
32
|
+
#
|
|
33
|
+
# Responsibilities:
|
|
34
|
+
# - ONE responsibility: Orchestrate LZ77+Huffman decoding
|
|
35
|
+
# - Parse Huffman trees from bit stream
|
|
36
|
+
# - Decode symbols using Huffman coder
|
|
37
|
+
# - Process LZ77 matches via sliding window
|
|
38
|
+
# - Manage decoder state and output
|
|
39
|
+
#
|
|
40
|
+
# RAR LZ77+Huffman Format:
|
|
41
|
+
# 1. Block header with Huffman tree definitions
|
|
42
|
+
# 2. Compressed data stream
|
|
43
|
+
# 3. Symbols: literals (0-255), matches (length+distance), end marker
|
|
44
|
+
class Decoder
|
|
45
|
+
# Symbol ranges
|
|
46
|
+
LITERAL_SYMBOLS = (0..255)
|
|
47
|
+
END_OF_BLOCK = 256
|
|
48
|
+
MATCH_SYMBOLS = (257..511)
|
|
49
|
+
|
|
50
|
+
# Match parameters
|
|
51
|
+
MIN_MATCH_LENGTH = 3
|
|
52
|
+
MAX_MATCH_LENGTH = 257
|
|
53
|
+
|
|
54
|
+
# Window size for RAR4
|
|
55
|
+
DEFAULT_WINDOW_SIZE = 64 * 1024
|
|
56
|
+
|
|
57
|
+
# Initialize LZ77+Huffman decoder
|
|
58
|
+
#
|
|
59
|
+
# @param input [IO] Compressed input stream
|
|
60
|
+
# @param options [Hash] Decoding options
|
|
61
|
+
# @option options [Integer] :window_size Window size in bytes
|
|
62
|
+
def initialize(input, options = {})
|
|
63
|
+
@bit_stream = BitStream.new(input, :read)
|
|
64
|
+
@window = SlidingWindow.new(options[:window_size] || DEFAULT_WINDOW_SIZE)
|
|
65
|
+
@huffman = HuffmanCoder.new
|
|
66
|
+
@output = String.new(encoding: Encoding::BINARY)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Decode compressed data
|
|
70
|
+
#
|
|
71
|
+
# Main decoding loop:
|
|
72
|
+
# 1. Parse Huffman tree (simplified for MVP)
|
|
73
|
+
# 2. Decode symbols until end-of-block
|
|
74
|
+
# 3. Process literals and matches
|
|
75
|
+
#
|
|
76
|
+
# @param max_output [Integer, nil] Maximum output bytes
|
|
77
|
+
# @return [String] Decoded data
|
|
78
|
+
def decode(max_output = nil)
|
|
79
|
+
@output.clear
|
|
80
|
+
|
|
81
|
+
# Parse Huffman tree (simplified - real RAR has complex structure)
|
|
82
|
+
parse_huffman_trees
|
|
83
|
+
|
|
84
|
+
# Decode symbols until end-of-block or max output
|
|
85
|
+
loop do
|
|
86
|
+
break if max_output && @output.bytesize >= max_output
|
|
87
|
+
|
|
88
|
+
symbol = @huffman.decode_symbol(@bit_stream)
|
|
89
|
+
break if symbol.nil? || symbol == END_OF_BLOCK
|
|
90
|
+
|
|
91
|
+
process_symbol(symbol)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
@output
|
|
95
|
+
rescue EOFError
|
|
96
|
+
@output
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Get window size
|
|
100
|
+
#
|
|
101
|
+
# @return [Integer] Window size in bytes
|
|
102
|
+
def window_size
|
|
103
|
+
@window.size
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# Parse Huffman trees from bit stream
|
|
109
|
+
#
|
|
110
|
+
# RAR uses multiple Huffman tables for different symbol types.
|
|
111
|
+
# This is a simplified implementation for MVP.
|
|
112
|
+
#
|
|
113
|
+
# Simplified format (written by Encoder):
|
|
114
|
+
# 1. 16-bit number of symbols (always 512 for MVP)
|
|
115
|
+
# 2. Code lengths (4 bits each, 512 × 4 bits = 2048 bits = 256 bytes)
|
|
116
|
+
#
|
|
117
|
+
# Real RAR format:
|
|
118
|
+
# - MC table: Main code (literals + length codes)
|
|
119
|
+
# - LD table: Low distance bits
|
|
120
|
+
# - RC table: Repeat codes
|
|
121
|
+
# - LDD table: Low distance for distance codes
|
|
122
|
+
#
|
|
123
|
+
# @return [void]
|
|
124
|
+
def parse_huffman_trees
|
|
125
|
+
# Read number of symbols from encoder (16-bit header)
|
|
126
|
+
num_symbols = @bit_stream.read_bits(16)
|
|
127
|
+
|
|
128
|
+
# Parse tree structure
|
|
129
|
+
@huffman.parse_tree(@bit_stream, num_symbols)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Process a decoded symbol
|
|
133
|
+
#
|
|
134
|
+
# Symbol types:
|
|
135
|
+
# - 0-255: Literal byte
|
|
136
|
+
# - 256: End of block
|
|
137
|
+
# - 257-511: Match (length+distance)
|
|
138
|
+
#
|
|
139
|
+
# @param symbol [Integer] Decoded symbol
|
|
140
|
+
# @return [void]
|
|
141
|
+
def process_symbol(symbol)
|
|
142
|
+
if LITERAL_SYMBOLS.cover?(symbol)
|
|
143
|
+
process_literal(symbol)
|
|
144
|
+
elsif MATCH_SYMBOLS.cover?(symbol)
|
|
145
|
+
process_match(symbol)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Process literal byte
|
|
150
|
+
#
|
|
151
|
+
# @param byte [Integer] Literal byte value (0-255)
|
|
152
|
+
# @return [void]
|
|
153
|
+
def process_literal(byte)
|
|
154
|
+
@output << byte.chr
|
|
155
|
+
@window.add_byte(byte)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Process LZ77 match
|
|
159
|
+
#
|
|
160
|
+
# Match symbol encodes both length and distance information.
|
|
161
|
+
# Additional bits may be read for exact values.
|
|
162
|
+
#
|
|
163
|
+
# @param symbol [Integer] Match symbol (257-511)
|
|
164
|
+
# @return [void]
|
|
165
|
+
def process_match(symbol)
|
|
166
|
+
length = decode_match_length(symbol)
|
|
167
|
+
distance = decode_match_distance
|
|
168
|
+
|
|
169
|
+
# Copy match from window
|
|
170
|
+
match_bytes = @window.copy_match(distance, length)
|
|
171
|
+
match_bytes.each { |byte| @output << byte.chr }
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Decode match length from symbol
|
|
175
|
+
#
|
|
176
|
+
# RAR encodes length in the symbol itself plus extra bits.
|
|
177
|
+
# This is simplified for MVP.
|
|
178
|
+
#
|
|
179
|
+
# @param symbol [Integer] Match symbol
|
|
180
|
+
# @return [Integer] Match length
|
|
181
|
+
def decode_match_length(symbol)
|
|
182
|
+
# Simplified length decoding
|
|
183
|
+
# Real RAR uses complex length encoding with extra bits
|
|
184
|
+
|
|
185
|
+
base_length = symbol - 257 + MIN_MATCH_LENGTH
|
|
186
|
+
|
|
187
|
+
# Could read extra bits here for longer lengths
|
|
188
|
+
# For now, use base length
|
|
189
|
+
[base_length, MAX_MATCH_LENGTH].min
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Decode match distance
|
|
193
|
+
#
|
|
194
|
+
# Distance is encoded separately, often with additional
|
|
195
|
+
# Huffman tables and extra bits.
|
|
196
|
+
#
|
|
197
|
+
# @return [Integer] Match distance
|
|
198
|
+
def decode_match_distance
|
|
199
|
+
# Simplified distance decoding
|
|
200
|
+
# Real RAR uses separate Huffman table for distance
|
|
201
|
+
|
|
202
|
+
# Read distance as direct bits (simplified)
|
|
203
|
+
# Real implementation would use distance Huffman table
|
|
204
|
+
distance_bits = 16 # Changed from 8 to 16 bits for 64KB window
|
|
205
|
+
@bit_stream.read_bits(distance_bits)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|