omnizip 0.3.1
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 +754 -0
- data/COPYING +502 -0
- data/Gemfile +17 -0
- data/LICENSE +12 -0
- data/README.adoc +1045 -0
- data/Rakefile +12 -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 +91 -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 +271 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +185 -0
- data/docs/getting-started/your-first-archive.adoc +218 -0
- data/docs/guides/advanced-features/encryption.adoc +300 -0
- data/docs/guides/advanced-features/index.adoc +49 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
- data/docs/guides/advanced-features/streaming.adoc +212 -0
- data/docs/guides/archive-formats/gzip-format.adoc +107 -0
- data/docs/guides/archive-formats/index.adoc +130 -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/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 +113 -0
- data/docs/guides/compression-algorithms/deflate.adoc +319 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +398 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
- data/docs/guides/creating-archives.adoc +354 -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 +218 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +188 -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/troubleshooting/index.adoc +208 -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 +130 -0
- data/lib/omnizip/algorithm_registry.rb +86 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
- data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
- data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
- data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
- data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
- data/lib/omnizip/algorithms/bzip2.rb +130 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
- data/lib/omnizip/algorithms/deflate.rb +128 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
- data/lib/omnizip/algorithms/deflate64.rb +109 -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 +148 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -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 +205 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
- data/lib/omnizip/algorithms/lzma.rb +238 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +141 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +116 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +82 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
- data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
- data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
- data/lib/omnizip/algorithms/zstandard.rb +138 -0
- data/lib/omnizip/buffer/memory_archive.rb +251 -0
- data/lib/omnizip/buffer/memory_extractor.rb +224 -0
- data/lib/omnizip/buffer.rb +176 -0
- data/lib/omnizip/checksum_registry.rb +114 -0
- data/lib/omnizip/checksums/crc32.rb +100 -0
- data/lib/omnizip/checksums/crc64.rb +101 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/verifier.rb +131 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +120 -0
- data/lib/omnizip/chunked.rb +129 -0
- data/lib/omnizip/cli/output_formatter.rb +104 -0
- data/lib/omnizip/cli.rb +572 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +427 -0
- data/lib/omnizip/commands/archive_extract_command.rb +272 -0
- data/lib/omnizip/commands/archive_list_command.rb +218 -0
- data/lib/omnizip/commands/archive_repair_command.rb +131 -0
- data/lib/omnizip/commands/archive_verify_command.rb +117 -0
- data/lib/omnizip/commands/compress_command.rb +117 -0
- data/lib/omnizip/commands/decompress_command.rb +120 -0
- data/lib/omnizip/commands/list_command.rb +53 -0
- data/lib/omnizip/commands/metadata_command.rb +153 -0
- data/lib/omnizip/commands/parity_create_command.rb +122 -0
- data/lib/omnizip/commands/parity_repair_command.rb +122 -0
- data/lib/omnizip/commands/parity_verify_command.rb +124 -0
- data/lib/omnizip/commands/profile_list_command.rb +56 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/convenience.rb +359 -0
- data/lib/omnizip/converter/conversion_registry.rb +49 -0
- data/lib/omnizip/converter/conversion_strategy.rb +121 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
- data/lib/omnizip/converter.rb +105 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/error.rb +106 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +99 -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 +63 -0
- data/lib/omnizip/extraction/filter_chain.rb +177 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +70 -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 +240 -0
- data/lib/omnizip/extraction.rb +111 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +113 -0
- data/lib/omnizip/filter.rb +139 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +166 -0
- data/lib/omnizip/filters/bcj.rb +279 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
- data/lib/omnizip/filters/bcj2.rb +99 -0
- data/lib/omnizip/filters/bcj_arm.rb +176 -0
- data/lib/omnizip/filters/bcj_arm64.rb +244 -0
- data/lib/omnizip/filters/bcj_ia64.rb +196 -0
- data/lib/omnizip/filters/bcj_ppc.rb +190 -0
- data/lib/omnizip/filters/bcj_sparc.rb +176 -0
- data/lib/omnizip/filters/bcj_x86.rb +193 -0
- data/lib/omnizip/filters/delta.rb +196 -0
- data/lib/omnizip/filters/filter_base.rb +72 -0
- data/lib/omnizip/filters/registry.rb +123 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/format_detector.rb +162 -0
- data/lib/omnizip/format_registry.rb +59 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +172 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +385 -0
- data/lib/omnizip/formats/cpio/reader.rb +196 -0
- data/lib/omnizip/formats/cpio/writer.rb +234 -0
- data/lib/omnizip/formats/cpio.rb +140 -0
- data/lib/omnizip/formats/format_spec_loader.rb +230 -0
- data/lib/omnizip/formats/gzip.rb +238 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
- data/lib/omnizip/formats/iso/directory_record.rb +152 -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 +197 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +530 -0
- data/lib/omnizip/formats/iso.rb +140 -0
- data/lib/omnizip/formats/lzip.rb +175 -0
- data/lib/omnizip/formats/lzma_alone.rb +171 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
- data/lib/omnizip/formats/rar/block_parser.rb +243 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -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/ppmd/context.rb +105 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +82 -0
- data/lib/omnizip/formats/rar/decompressor.rb +238 -0
- data/lib/omnizip/formats/rar/external_writer.rb +312 -0
- data/lib/omnizip/formats/rar/header.rb +192 -0
- data/lib/omnizip/formats/rar/license_validator.rb +109 -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/parity_handler.rb +292 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -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 +97 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +187 -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 +264 -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 +194 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
- data/lib/omnizip/formats/rar/reader.rb +366 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
- data/lib/omnizip/formats/rar/writer.rb +431 -0
- data/lib/omnizip/formats/rar.rb +205 -0
- data/lib/omnizip/formats/rar3/compressor.rb +73 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar3/reader.rb +386 -0
- data/lib/omnizip/formats/rar3/writer.rb +219 -0
- data/lib/omnizip/formats/rar5/compressor.rb +73 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar5/reader.rb +342 -0
- data/lib/omnizip/formats/rar5/writer.rb +214 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
- data/lib/omnizip/formats/seven_zip/header.rb +106 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
- data/lib/omnizip/formats/seven_zip.rb +93 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +94 -0
- data/lib/omnizip/formats/tar/header.rb +168 -0
- data/lib/omnizip/formats/tar/reader.rb +121 -0
- data/lib/omnizip/formats/tar/writer.rb +216 -0
- data/lib/omnizip/formats/tar.rb +84 -0
- data/lib/omnizip/formats/xz/reader.rb +116 -0
- data/lib/omnizip/formats/xz.rb +237 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
- data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
- data/lib/omnizip/formats/zip/reader.rb +250 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +375 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
- data/lib/omnizip/formats/zip.rb +50 -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/seven_zip/lzma/decoder.rb +421 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
- data/lib/omnizip/io/buffered_input.rb +146 -0
- data/lib/omnizip/io/buffered_output.rb +105 -0
- data/lib/omnizip/io/stream_manager.rb +115 -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 +124 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +146 -0
- data/lib/omnizip/metadata/metadata_editor.rb +171 -0
- data/lib/omnizip/metadata/metadata_registry.rb +64 -0
- data/lib/omnizip/metadata/metadata_validator.rb +99 -0
- data/lib/omnizip/metadata.rb +57 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +73 -0
- data/lib/omnizip/models/compression_options.rb +71 -0
- data/lib/omnizip/models/conversion_options.rb +87 -0
- data/lib/omnizip/models/conversion_result.rb +135 -0
- data/lib/omnizip/models/eta_result.rb +46 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +144 -0
- data/lib/omnizip/models/filter_config.rb +183 -0
- data/lib/omnizip/models/match_result.rb +124 -0
- data/lib/omnizip/models/optimization_suggestion.rb +91 -0
- data/lib/omnizip/models/parallel_options.rb +104 -0
- data/lib/omnizip/models/performance_result.rb +79 -0
- data/lib/omnizip/models/profile_report.rb +82 -0
- data/lib/omnizip/models/progress_options.rb +38 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +81 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +203 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
- data/lib/omnizip/parallel/worker_pool.rb +223 -0
- data/lib/omnizip/parallel.rb +149 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +73 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
- data/lib/omnizip/parity/models/main_packet.rb +128 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +109 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
- data/lib/omnizip/parity/par2_creator.rb +531 -0
- data/lib/omnizip/parity/par2_repairer.rb +407 -0
- data/lib/omnizip/parity/par2_verifier.rb +364 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
- data/lib/omnizip/parity.rb +186 -0
- data/lib/omnizip/password/encryption_registry.rb +65 -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 +192 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
- data/lib/omnizip/password.rb +87 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
- data/lib/omnizip/pipe.rb +121 -0
- data/lib/omnizip/platform/ntfs_streams.rb +201 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +39 -0
- data/lib/omnizip/profile/balanced_profile.rb +33 -0
- data/lib/omnizip/profile/binary_profile.rb +36 -0
- data/lib/omnizip/profile/compression_profile.rb +158 -0
- data/lib/omnizip/profile/custom_profile.rb +157 -0
- data/lib/omnizip/profile/fast_profile.rb +33 -0
- data/lib/omnizip/profile/maximum_profile.rb +33 -0
- data/lib/omnizip/profile/profile_detector.rb +110 -0
- data/lib/omnizip/profile/profile_registry.rb +161 -0
- data/lib/omnizip/profile/text_profile.rb +36 -0
- data/lib/omnizip/profile.rb +190 -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 +169 -0
- data/lib/omnizip/profiler.rb +204 -0
- data/lib/omnizip/progress/callback_reporter.rb +36 -0
- data/lib/omnizip/progress/console_reporter.rb +62 -0
- data/lib/omnizip/progress/log_reporter.rb +91 -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 +190 -0
- data/lib/omnizip/progress/silent_reporter.rb +24 -0
- data/lib/omnizip/progress.rb +127 -0
- data/lib/omnizip/rubyzip_compat.rb +63 -0
- data/lib/omnizip/temp/safe_extract.rb +168 -0
- data/lib/omnizip/temp/temp_file.rb +124 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +181 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +156 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +273 -0
- data/lib/omnizip/zip/output_stream.rb +324 -0
- data/lib/omnizip.rb +156 -0
- data/readme-docs/advanced-features.adoc +515 -0
- data/readme-docs/api-usage.adoc +444 -0
- data/readme-docs/architecture.adoc +449 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +442 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +325 -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/xz-file-format-1.2.1.txt +1174 -0
- metadata +617 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "compression_profile"
|
|
4
|
+
require_relative "../file_type/mime_classifier"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Profile
|
|
8
|
+
# Archive compression profile
|
|
9
|
+
#
|
|
10
|
+
# For files that are already compressed.
|
|
11
|
+
# Uses Store (no compression) to avoid wasting CPU time on files
|
|
12
|
+
# that cannot be compressed further.
|
|
13
|
+
class ArchiveProfile < CompressionProfile
|
|
14
|
+
# Initialize archive profile
|
|
15
|
+
def initialize
|
|
16
|
+
super(
|
|
17
|
+
name: :archive,
|
|
18
|
+
algorithm: :store,
|
|
19
|
+
level: 0,
|
|
20
|
+
filter: nil,
|
|
21
|
+
solid: false,
|
|
22
|
+
description: "No compression (already compressed files)"
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Check if this profile is suitable for a MIME type
|
|
27
|
+
#
|
|
28
|
+
# @param mime_type [String] MIME type string
|
|
29
|
+
# @return [Boolean] true if MIME type is already compressed
|
|
30
|
+
def suitable_for?(mime_type)
|
|
31
|
+
return true unless mime_type
|
|
32
|
+
|
|
33
|
+
# Suitable for archives and media files (already compressed)
|
|
34
|
+
FileType::MimeClassifier.archive?(mime_type) ||
|
|
35
|
+
FileType::MimeClassifier.media?(mime_type)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "compression_profile"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Profile
|
|
7
|
+
# Balanced compression profile
|
|
8
|
+
#
|
|
9
|
+
# Provides a good balance between compression speed and ratio.
|
|
10
|
+
# Uses Deflate with level 6 (the default for most use cases).
|
|
11
|
+
class BalancedProfile < CompressionProfile
|
|
12
|
+
# Initialize balanced profile
|
|
13
|
+
def initialize
|
|
14
|
+
super(
|
|
15
|
+
name: :balanced,
|
|
16
|
+
algorithm: :deflate,
|
|
17
|
+
level: 6,
|
|
18
|
+
filter: nil,
|
|
19
|
+
solid: false,
|
|
20
|
+
description: "Balanced speed/compression (default)"
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Balanced profile is suitable for all MIME types
|
|
25
|
+
#
|
|
26
|
+
# @param _mime_type [String] MIME type string
|
|
27
|
+
# @return [Boolean] Always true
|
|
28
|
+
def suitable_for?(_mime_type)
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "compression_profile"
|
|
4
|
+
require_relative "../file_type/mime_classifier"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Profile
|
|
8
|
+
# Binary compression profile
|
|
9
|
+
#
|
|
10
|
+
# Optimized for compressing executable files.
|
|
11
|
+
# Uses LZMA2 with BCJ filters to improve compression of executables.
|
|
12
|
+
class BinaryProfile < CompressionProfile
|
|
13
|
+
# Initialize binary profile
|
|
14
|
+
def initialize
|
|
15
|
+
super(
|
|
16
|
+
name: :binary,
|
|
17
|
+
algorithm: :lzma2,
|
|
18
|
+
level: 6,
|
|
19
|
+
filter: :bcj_x86,
|
|
20
|
+
solid: false,
|
|
21
|
+
description: "Optimized for executables"
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Check if this profile is suitable for a MIME type
|
|
26
|
+
#
|
|
27
|
+
# @param mime_type [String] MIME type string
|
|
28
|
+
# @return [Boolean] true if MIME type is executable
|
|
29
|
+
def suitable_for?(mime_type)
|
|
30
|
+
return true unless mime_type
|
|
31
|
+
|
|
32
|
+
FileType::MimeClassifier.executable?(mime_type)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Profile
|
|
5
|
+
# Base class for compression profiles
|
|
6
|
+
#
|
|
7
|
+
# A compression profile encapsulates a set of compression settings that
|
|
8
|
+
# define how files should be compressed. This includes the algorithm,
|
|
9
|
+
# compression level, filters, and other options.
|
|
10
|
+
#
|
|
11
|
+
# @abstract Subclass and override {#suitable_for?} to implement a custom
|
|
12
|
+
# profile
|
|
13
|
+
class CompressionProfile
|
|
14
|
+
attr_reader :name, :algorithm, :level, :filter, :solid, :description
|
|
15
|
+
|
|
16
|
+
# Initialize a new compression profile
|
|
17
|
+
#
|
|
18
|
+
# @param name [Symbol] Profile name
|
|
19
|
+
# @param algorithm [Symbol] Compression algorithm (:deflate, :lzma2,
|
|
20
|
+
# :ppmd7, etc.)
|
|
21
|
+
# @param level [Integer] Compression level (0-9)
|
|
22
|
+
# @param filter [Symbol, nil] Filter to apply (:bcj_x86, :bcj_arm, etc.)
|
|
23
|
+
# @param solid [Boolean] Whether to use solid compression
|
|
24
|
+
# @param description [String] Human-readable description
|
|
25
|
+
def initialize(
|
|
26
|
+
name:,
|
|
27
|
+
algorithm:,
|
|
28
|
+
level:,
|
|
29
|
+
filter: nil,
|
|
30
|
+
solid: false,
|
|
31
|
+
description: ""
|
|
32
|
+
)
|
|
33
|
+
@name = name
|
|
34
|
+
@algorithm = algorithm
|
|
35
|
+
@level = level
|
|
36
|
+
@filter = filter
|
|
37
|
+
@solid = solid
|
|
38
|
+
@description = description
|
|
39
|
+
|
|
40
|
+
validate!
|
|
41
|
+
freeze
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Apply this profile to compression options
|
|
45
|
+
#
|
|
46
|
+
# @param options [Hash] Existing compression options
|
|
47
|
+
# @return [Hash] Updated compression options
|
|
48
|
+
def apply_to(options)
|
|
49
|
+
options = options.dup
|
|
50
|
+
|
|
51
|
+
options[:algorithm] = algorithm
|
|
52
|
+
options[:level] = level
|
|
53
|
+
options[:filter] = resolve_filter(options[:file_type]) if filter
|
|
54
|
+
options[:solid] = solid
|
|
55
|
+
|
|
56
|
+
options
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Check if this profile is suitable for a given MIME type
|
|
60
|
+
#
|
|
61
|
+
# @param mime_type [String] MIME type string to check
|
|
62
|
+
# @return [Boolean] true if this profile is suitable
|
|
63
|
+
def suitable_for?(_mime_type)
|
|
64
|
+
# Default implementation - subclasses should override
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Get profile information as a hash
|
|
69
|
+
#
|
|
70
|
+
# @return [Hash] Profile properties
|
|
71
|
+
def to_h
|
|
72
|
+
{
|
|
73
|
+
name: name,
|
|
74
|
+
algorithm: algorithm,
|
|
75
|
+
level: level,
|
|
76
|
+
filter: filter,
|
|
77
|
+
solid: solid,
|
|
78
|
+
description: description,
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# String representation of the profile
|
|
83
|
+
#
|
|
84
|
+
# @return [String]
|
|
85
|
+
def to_s
|
|
86
|
+
"#{name} - #{description}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Inspect representation
|
|
90
|
+
#
|
|
91
|
+
# @return [String]
|
|
92
|
+
def inspect
|
|
93
|
+
"#<#{self.class.name} name=#{name} " \
|
|
94
|
+
"algorithm=#{algorithm} level=#{level}>"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
# Validate profile settings
|
|
100
|
+
#
|
|
101
|
+
# @raise [ArgumentError] if settings are invalid
|
|
102
|
+
def validate!
|
|
103
|
+
validate_name!
|
|
104
|
+
validate_algorithm!
|
|
105
|
+
validate_level!
|
|
106
|
+
validate_filter!
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Validate profile name
|
|
110
|
+
def validate_name!
|
|
111
|
+
raise ArgumentError, "Profile name is required" if name.nil?
|
|
112
|
+
return if name.is_a?(Symbol)
|
|
113
|
+
|
|
114
|
+
raise ArgumentError, "Profile name must be a Symbol"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Validate algorithm
|
|
118
|
+
def validate_algorithm!
|
|
119
|
+
return if algorithm.nil?
|
|
120
|
+
return if algorithm.is_a?(Symbol)
|
|
121
|
+
|
|
122
|
+
raise ArgumentError, "Algorithm must be a Symbol"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Validate compression level
|
|
126
|
+
def validate_level!
|
|
127
|
+
return if level.nil?
|
|
128
|
+
return if level.is_a?(Integer) && level >= 0 && level <= 9
|
|
129
|
+
|
|
130
|
+
raise ArgumentError, "Level must be an Integer between 0 and 9"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Validate filter
|
|
134
|
+
def validate_filter!
|
|
135
|
+
return if filter.nil?
|
|
136
|
+
return if filter.is_a?(Symbol)
|
|
137
|
+
|
|
138
|
+
raise ArgumentError, "Filter must be a Symbol or nil"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Resolve filter based on MIME type
|
|
142
|
+
#
|
|
143
|
+
# @param mime_type [String, nil] MIME type string
|
|
144
|
+
# @return [Symbol, nil] Resolved filter
|
|
145
|
+
def resolve_filter(mime_type)
|
|
146
|
+
return filter unless filter == :auto
|
|
147
|
+
return nil unless mime_type
|
|
148
|
+
|
|
149
|
+
# Auto-select BCJ filter based on MIME type
|
|
150
|
+
# For executables, default to x86 architecture
|
|
151
|
+
require_relative "../file_type/mime_classifier"
|
|
152
|
+
if FileType::MimeClassifier.executable?(mime_type)
|
|
153
|
+
:bcj_x86
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "compression_profile"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Profile
|
|
7
|
+
# Custom user-defined compression profile
|
|
8
|
+
#
|
|
9
|
+
# Allows users to create custom profiles with specific settings.
|
|
10
|
+
# Supports builder pattern for fluent API and profile inheritance.
|
|
11
|
+
class CustomProfile < CompressionProfile
|
|
12
|
+
# Builder for creating custom profiles
|
|
13
|
+
class Builder
|
|
14
|
+
attr_accessor :name, :algorithm, :level, :filter, :solid, :description,
|
|
15
|
+
:base_profile
|
|
16
|
+
|
|
17
|
+
# Initialize a new builder
|
|
18
|
+
#
|
|
19
|
+
# @param name [Symbol] Profile name
|
|
20
|
+
# @param base_profile [CompressionProfile, nil] Base profile to extend
|
|
21
|
+
def initialize(name, base_profile = nil)
|
|
22
|
+
@name = name
|
|
23
|
+
|
|
24
|
+
if base_profile
|
|
25
|
+
# Inherit settings from base profile
|
|
26
|
+
@algorithm = base_profile.algorithm
|
|
27
|
+
@level = base_profile.level
|
|
28
|
+
@filter = base_profile.filter
|
|
29
|
+
@solid = base_profile.solid
|
|
30
|
+
@description = base_profile.description
|
|
31
|
+
@base_profile = base_profile
|
|
32
|
+
else
|
|
33
|
+
# Default settings
|
|
34
|
+
@algorithm = :deflate
|
|
35
|
+
@level = 6
|
|
36
|
+
@filter = nil
|
|
37
|
+
@solid = false
|
|
38
|
+
@description = ""
|
|
39
|
+
@base_profile = nil
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Build the custom profile
|
|
44
|
+
#
|
|
45
|
+
# @return [CustomProfile] The built profile
|
|
46
|
+
def build
|
|
47
|
+
CustomProfile.new(
|
|
48
|
+
name: name,
|
|
49
|
+
algorithm: algorithm,
|
|
50
|
+
level: level,
|
|
51
|
+
filter: filter,
|
|
52
|
+
solid: solid,
|
|
53
|
+
description: description,
|
|
54
|
+
base_profile: base_profile,
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Validate builder settings
|
|
59
|
+
#
|
|
60
|
+
# @raise [ArgumentError] if settings are invalid
|
|
61
|
+
# @return [Boolean] true if valid
|
|
62
|
+
def valid?
|
|
63
|
+
validate_name!
|
|
64
|
+
validate_algorithm!
|
|
65
|
+
validate_level!
|
|
66
|
+
validate_filter!
|
|
67
|
+
true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
# Validate profile name
|
|
73
|
+
def validate_name!
|
|
74
|
+
raise ArgumentError, "Profile name is required" if name.nil?
|
|
75
|
+
return if name.is_a?(Symbol)
|
|
76
|
+
|
|
77
|
+
raise ArgumentError, "Profile name must be a Symbol"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Validate algorithm
|
|
81
|
+
def validate_algorithm!
|
|
82
|
+
return if algorithm.nil?
|
|
83
|
+
return if algorithm.is_a?(Symbol)
|
|
84
|
+
|
|
85
|
+
raise ArgumentError, "Algorithm must be a Symbol"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Validate compression level
|
|
89
|
+
def validate_level!
|
|
90
|
+
return if level.nil?
|
|
91
|
+
return if level.is_a?(Integer) && level >= 0 && level <= 9
|
|
92
|
+
|
|
93
|
+
raise ArgumentError, "Level must be an Integer between 0 and 9"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Validate filter
|
|
97
|
+
def validate_filter!
|
|
98
|
+
return if filter.nil?
|
|
99
|
+
return if filter.is_a?(Symbol)
|
|
100
|
+
|
|
101
|
+
raise ArgumentError, "Filter must be a Symbol or nil"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
attr_reader :base_profile
|
|
106
|
+
|
|
107
|
+
# Initialize a custom profile
|
|
108
|
+
#
|
|
109
|
+
# @param name [Symbol] Profile name
|
|
110
|
+
# @param algorithm [Symbol] Compression algorithm
|
|
111
|
+
# @param level [Integer] Compression level (0-9)
|
|
112
|
+
# @param filter [Symbol, nil] Filter to apply
|
|
113
|
+
# @param solid [Boolean] Whether to use solid compression
|
|
114
|
+
# @param description [String] Human-readable description
|
|
115
|
+
# @param base_profile [CompressionProfile, nil] Base profile extended
|
|
116
|
+
def initialize(
|
|
117
|
+
name:,
|
|
118
|
+
algorithm:,
|
|
119
|
+
level:,
|
|
120
|
+
filter: nil,
|
|
121
|
+
solid: false,
|
|
122
|
+
description: "",
|
|
123
|
+
base_profile: nil
|
|
124
|
+
)
|
|
125
|
+
@base_profile = base_profile
|
|
126
|
+
super(
|
|
127
|
+
name: name,
|
|
128
|
+
algorithm: algorithm,
|
|
129
|
+
level: level,
|
|
130
|
+
filter: filter,
|
|
131
|
+
solid: solid,
|
|
132
|
+
description: description
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Check if this profile is suitable for a file type
|
|
137
|
+
#
|
|
138
|
+
# @param file_type [Omnizip::FileType::DetectionResult] File type
|
|
139
|
+
# @return [Boolean] Delegates to base profile if available
|
|
140
|
+
def suitable_for?(file_type)
|
|
141
|
+
return base_profile.suitable_for?(file_type) if base_profile
|
|
142
|
+
|
|
143
|
+
# Custom profiles are suitable for all file types by default
|
|
144
|
+
true
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Convert to hash with base profile information
|
|
148
|
+
#
|
|
149
|
+
# @return [Hash] Profile properties including base
|
|
150
|
+
def to_h
|
|
151
|
+
hash = super
|
|
152
|
+
hash[:base_profile] = base_profile.name if base_profile
|
|
153
|
+
hash
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "compression_profile"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Profile
|
|
7
|
+
# Fast compression profile
|
|
8
|
+
#
|
|
9
|
+
# Optimizes for compression speed over compression ratio.
|
|
10
|
+
# Uses Deflate with level 1 for minimal CPU usage.
|
|
11
|
+
class FastProfile < CompressionProfile
|
|
12
|
+
# Initialize fast profile
|
|
13
|
+
def initialize
|
|
14
|
+
super(
|
|
15
|
+
name: :fast,
|
|
16
|
+
algorithm: :deflate,
|
|
17
|
+
level: 1,
|
|
18
|
+
filter: nil,
|
|
19
|
+
solid: false,
|
|
20
|
+
description: "Fast compression, lower ratio"
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Fast profile is suitable for all MIME types
|
|
25
|
+
#
|
|
26
|
+
# @param _mime_type [String] MIME type string
|
|
27
|
+
# @return [Boolean] Always true
|
|
28
|
+
def suitable_for?(_mime_type)
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "compression_profile"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Profile
|
|
7
|
+
# Maximum compression profile
|
|
8
|
+
#
|
|
9
|
+
# Optimizes for the best compression ratio regardless of time.
|
|
10
|
+
# Uses LZMA2 with level 9 and solid compression for maximum compression.
|
|
11
|
+
class MaximumProfile < CompressionProfile
|
|
12
|
+
# Initialize maximum profile
|
|
13
|
+
def initialize
|
|
14
|
+
super(
|
|
15
|
+
name: :maximum,
|
|
16
|
+
algorithm: :lzma2,
|
|
17
|
+
level: 9,
|
|
18
|
+
filter: :auto,
|
|
19
|
+
solid: true,
|
|
20
|
+
description: "Maximum compression, slower"
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Maximum profile is suitable for all MIME types
|
|
25
|
+
#
|
|
26
|
+
# @param _mime_type [String] MIME type string
|
|
27
|
+
# @return [Boolean] Always true
|
|
28
|
+
def suitable_for?(_mime_type)
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../file_type/mime_classifier"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Profile
|
|
7
|
+
# Automatic profile detection based on file analysis
|
|
8
|
+
#
|
|
9
|
+
# This class analyzes files and recommends optimal compression profiles
|
|
10
|
+
# based on MIME type detection and user preferences.
|
|
11
|
+
class ProfileDetector
|
|
12
|
+
# Initialize a new profile detector
|
|
13
|
+
#
|
|
14
|
+
# @param registry [ProfileRegistry] Profile registry to use
|
|
15
|
+
def initialize(registry = nil)
|
|
16
|
+
@registry = registry || Profile.registry
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Detect the optimal profile for a file
|
|
20
|
+
#
|
|
21
|
+
# @param file_path [String] Path to the file
|
|
22
|
+
# @param options [Hash] Detection options
|
|
23
|
+
# @option options [Symbol] :fallback Fallback profile if detection fails
|
|
24
|
+
# (default: :balanced)
|
|
25
|
+
# @return [CompressionProfile] Recommended profile
|
|
26
|
+
def detect(file_path, options = {})
|
|
27
|
+
fallback = options[:fallback] || :balanced
|
|
28
|
+
|
|
29
|
+
# Detect MIME type
|
|
30
|
+
mime_type = detect_mime_type(file_path)
|
|
31
|
+
|
|
32
|
+
# Find suitable profiles
|
|
33
|
+
suitable = find_suitable_profiles(mime_type)
|
|
34
|
+
|
|
35
|
+
# Return most appropriate profile or fallback to balanced
|
|
36
|
+
select_best_profile(suitable, mime_type) ||
|
|
37
|
+
@registry.get(fallback) ||
|
|
38
|
+
@registry.get(:balanced)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Detect MIME type using FileType detector
|
|
42
|
+
#
|
|
43
|
+
# @param file_path [String] Path to the file
|
|
44
|
+
# @return [String, nil] MIME type string or nil
|
|
45
|
+
def detect_mime_type(file_path)
|
|
46
|
+
return nil unless File.exist?(file_path)
|
|
47
|
+
|
|
48
|
+
Omnizip::FileType.detect(file_path)
|
|
49
|
+
rescue StandardError
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Find profiles suitable for a MIME type
|
|
54
|
+
#
|
|
55
|
+
# @param mime_type [String, nil] MIME type string
|
|
56
|
+
# @return [Array<CompressionProfile>] Suitable profiles
|
|
57
|
+
def find_suitable_profiles(mime_type)
|
|
58
|
+
return [] unless mime_type
|
|
59
|
+
|
|
60
|
+
@registry.suitable_for(mime_type)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Select the best profile from suitable candidates
|
|
64
|
+
#
|
|
65
|
+
# @param profiles [Array<CompressionProfile>] Suitable profiles
|
|
66
|
+
# @param mime_type [String, nil] MIME type string
|
|
67
|
+
# @return [CompressionProfile, nil] Best profile or nil
|
|
68
|
+
def select_best_profile(profiles, mime_type)
|
|
69
|
+
return nil if profiles.empty?
|
|
70
|
+
return profiles.first if profiles.size == 1
|
|
71
|
+
|
|
72
|
+
# Priority order for specific MIME types
|
|
73
|
+
priority = profile_priority(mime_type)
|
|
74
|
+
|
|
75
|
+
# Find first profile in priority order
|
|
76
|
+
priority.each do |name|
|
|
77
|
+
profile = profiles.find { |p| p.name == name }
|
|
78
|
+
return profile if profile
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Return first suitable profile if none matched priority
|
|
82
|
+
profiles.first
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
# Get profile priority based on MIME type
|
|
88
|
+
#
|
|
89
|
+
# @param mime_type [String, nil] MIME type string
|
|
90
|
+
# @return [Array<Symbol>] Priority-ordered profile names
|
|
91
|
+
def profile_priority(mime_type)
|
|
92
|
+
return [:balanced] unless mime_type
|
|
93
|
+
|
|
94
|
+
# Use MimeClassifier to determine category
|
|
95
|
+
category = FileType::MimeClassifier.profile_category(mime_type)
|
|
96
|
+
|
|
97
|
+
case category
|
|
98
|
+
when :text
|
|
99
|
+
%i[text balanced]
|
|
100
|
+
when :binary
|
|
101
|
+
%i[binary maximum balanced]
|
|
102
|
+
when :archive
|
|
103
|
+
%i[archive fast balanced]
|
|
104
|
+
else
|
|
105
|
+
[:balanced]
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|