omnizip 0.4.7-arm-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,159 @@
|
|
|
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 Algorithms
|
|
25
|
+
class Zstandard
|
|
26
|
+
# XXHash64 (https://github.com/Cyan4973/xxHash), single-shot.
|
|
27
|
+
#
|
|
28
|
+
# Zstandard frame checksums are the low 32 bits of XXHash64 of the
|
|
29
|
+
# decoded content with seed 0 (the zstd C reference truncates
|
|
30
|
+
# XXH64_digest to a U32; RFC 8878's "xxh64" wording agrees).
|
|
31
|
+
module XXHash64
|
|
32
|
+
MASK64 = 0xFFFFFFFFFFFFFFFF
|
|
33
|
+
MASK32 = 0xFFFFFFFF
|
|
34
|
+
|
|
35
|
+
PRIME64_1 = 0x9E3779B185EBCA87
|
|
36
|
+
PRIME64_2 = 0xC2B2AE3D27D4EB4F
|
|
37
|
+
PRIME64_3 = 0x165667B19E3779F9
|
|
38
|
+
PRIME64_4 = 0x85EBCA77C2B2AE63
|
|
39
|
+
PRIME64_5 = 0x27D4EB2F165667C5
|
|
40
|
+
|
|
41
|
+
module_function
|
|
42
|
+
|
|
43
|
+
# Digest `data` with seed 0.
|
|
44
|
+
#
|
|
45
|
+
# @param data [String] binary string
|
|
46
|
+
# @return [Integer] 64-bit digest
|
|
47
|
+
def digest(data)
|
|
48
|
+
digest_seeded(data, 0)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def digest_seeded(data, seed)
|
|
52
|
+
len = data.bytesize
|
|
53
|
+
hash = 0
|
|
54
|
+
tail_start = 0
|
|
55
|
+
|
|
56
|
+
if len >= 32
|
|
57
|
+
v1 = (seed + PRIME64_1 + PRIME64_2) & MASK64
|
|
58
|
+
v2 = (seed + PRIME64_2) & MASK64
|
|
59
|
+
v3 = seed & MASK64
|
|
60
|
+
v4 = (seed - PRIME64_1) & MASK64
|
|
61
|
+
|
|
62
|
+
i = 0
|
|
63
|
+
while i + 32 <= len
|
|
64
|
+
v1 = round64(v1, read_u64(data, i))
|
|
65
|
+
v2 = round64(v2, read_u64(data, i + 8))
|
|
66
|
+
v3 = round64(v3, read_u64(data, i + 16))
|
|
67
|
+
v4 = round64(v4, read_u64(data, i + 24))
|
|
68
|
+
i += 32
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
hash = rotl64(v1, 1)
|
|
72
|
+
hash = (hash + rotl64(v2, 7)) & MASK64
|
|
73
|
+
hash = (hash + rotl64(v3, 12)) & MASK64
|
|
74
|
+
hash = (hash + rotl64(v4, 18)) & MASK64
|
|
75
|
+
|
|
76
|
+
hash = merge_round64(hash, v1)
|
|
77
|
+
hash = merge_round64(hash, v2)
|
|
78
|
+
hash = merge_round64(hash, v3)
|
|
79
|
+
hash = merge_round64(hash, v4)
|
|
80
|
+
|
|
81
|
+
tail_start = len - (len % 32)
|
|
82
|
+
else
|
|
83
|
+
hash = (seed + PRIME64_5) & MASK64
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
hash = (hash + len) & MASK64
|
|
87
|
+
|
|
88
|
+
i = tail_start
|
|
89
|
+
while i + 8 <= len
|
|
90
|
+
k1 = round64(0, read_u64(data, i))
|
|
91
|
+
hash ^= k1
|
|
92
|
+
hash = ((rotl64(hash, 27) * PRIME64_1) & MASK64) + PRIME64_4
|
|
93
|
+
hash &= MASK64
|
|
94
|
+
i += 8
|
|
95
|
+
end
|
|
96
|
+
if i + 4 <= len
|
|
97
|
+
hash ^= (read_u32(data, i) * PRIME64_1) & MASK64
|
|
98
|
+
hash = ((rotl64(hash, 23) * PRIME64_2) & MASK64) + PRIME64_3
|
|
99
|
+
hash &= MASK64
|
|
100
|
+
i += 4
|
|
101
|
+
end
|
|
102
|
+
while i < len
|
|
103
|
+
hash ^= (data.getbyte(i) * PRIME64_5) & MASK64
|
|
104
|
+
hash = (rotl64(hash, 11) * PRIME64_1) & MASK64
|
|
105
|
+
i += 1
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
hash ^= hash >> 33
|
|
109
|
+
hash = (hash * PRIME64_2) & MASK64
|
|
110
|
+
hash ^= hash >> 29
|
|
111
|
+
hash = (hash * PRIME64_3) & MASK64
|
|
112
|
+
hash ^= hash >> 32
|
|
113
|
+
hash
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Zstandard frame checksum: low 32 bits of XXHash64.
|
|
117
|
+
#
|
|
118
|
+
# @return [Integer] 32-bit checksum
|
|
119
|
+
def frame_checksum(data)
|
|
120
|
+
digest(data) & MASK32
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def read_u64(data, offset)
|
|
124
|
+
data.getbyte(offset) |
|
|
125
|
+
(data.getbyte(offset + 1) << 8) |
|
|
126
|
+
(data.getbyte(offset + 2) << 16) |
|
|
127
|
+
(data.getbyte(offset + 3) << 24) |
|
|
128
|
+
(data.getbyte(offset + 4) << 32) |
|
|
129
|
+
(data.getbyte(offset + 5) << 40) |
|
|
130
|
+
(data.getbyte(offset + 6) << 48) |
|
|
131
|
+
(data.getbyte(offset + 7) << 56)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def read_u32(data, offset)
|
|
135
|
+
data.getbyte(offset) |
|
|
136
|
+
(data.getbyte(offset + 1) << 8) |
|
|
137
|
+
(data.getbyte(offset + 2) << 16) |
|
|
138
|
+
(data.getbyte(offset + 3) << 24)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def rotl64(value, count)
|
|
142
|
+
((value << count) | (value >> (64 - count))) & MASK64
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def round64(acc, input)
|
|
146
|
+
acc = ((acc + (input * PRIME64_2)) & MASK64) & MASK64
|
|
147
|
+
acc = rotl64(acc, 31)
|
|
148
|
+
(acc * PRIME64_1) & MASK64
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def merge_round64(acc, value)
|
|
152
|
+
value = round64(0, value)
|
|
153
|
+
acc ^= value
|
|
154
|
+
(((acc * PRIME64_1) & MASK64) + PRIME64_4) & MASK64
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
8
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
9
|
+
# to deal in the Software without restriction, including without limitation
|
|
10
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
11
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
12
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
|
15
|
+
# all copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
23
|
+
# DEALINGS IN THE SOFTWARE.
|
|
24
|
+
|
|
25
|
+
module Omnizip
|
|
26
|
+
module Algorithms
|
|
27
|
+
# Zstandard compression algorithm
|
|
28
|
+
#
|
|
29
|
+
# Zstandard (or Zstd) is a fast lossless compression algorithm developed
|
|
30
|
+
# by Facebook (now Meta). It provides:
|
|
31
|
+
# - Excellent compression ratios comparable to zlib/deflate
|
|
32
|
+
# - Very fast compression and decompression speeds
|
|
33
|
+
# - Wide range of compression levels (1-22)
|
|
34
|
+
# - Dictionary support for small data compression
|
|
35
|
+
# - Streaming and frame modes
|
|
36
|
+
#
|
|
37
|
+
# Pure Ruby implementation of the Zstandard format, interoperable
|
|
38
|
+
# with the reference zstd CLI in both directions.
|
|
39
|
+
#
|
|
40
|
+
# Zstandard is particularly effective for:
|
|
41
|
+
# - Real-time compression needs
|
|
42
|
+
# - Network protocol compression
|
|
43
|
+
# - Database compression
|
|
44
|
+
# - Log file compression
|
|
45
|
+
# - General-purpose compression with speed priority
|
|
46
|
+
class Zstandard < Algorithm
|
|
47
|
+
# Nested classes - autoloaded
|
|
48
|
+
autoload :Constants, "omnizip/algorithms/zstandard/constants"
|
|
49
|
+
autoload :Encoder, "omnizip/algorithms/zstandard/encoder"
|
|
50
|
+
autoload :Decoder, "omnizip/algorithms/zstandard/decoder"
|
|
51
|
+
autoload :Huffman, "omnizip/algorithms/zstandard/huffman"
|
|
52
|
+
autoload :HuffmanTableReader, "omnizip/algorithms/zstandard/huffman"
|
|
53
|
+
autoload :HuffmanEncoder, "omnizip/algorithms/zstandard/huffman_encoder"
|
|
54
|
+
autoload :LiteralsDecoder, "omnizip/algorithms/zstandard/literals"
|
|
55
|
+
autoload :LiteralsEncoder, "omnizip/algorithms/zstandard/literals_encoder"
|
|
56
|
+
autoload :SequencesDecoder, "omnizip/algorithms/zstandard/sequences"
|
|
57
|
+
autoload :SequenceExecutor, "omnizip/algorithms/zstandard/sequences"
|
|
58
|
+
autoload :SequencesEncoder,
|
|
59
|
+
"omnizip/algorithms/zstandard/sequences_encoder"
|
|
60
|
+
autoload :MatchFinder, "omnizip/algorithms/zstandard/match_finder"
|
|
61
|
+
autoload :LdmHashTable, "omnizip/algorithms/zstandard/ldm"
|
|
62
|
+
autoload :Dictionary, "omnizip/algorithms/zstandard/dictionary"
|
|
63
|
+
autoload :XXHash64, "omnizip/algorithms/zstandard/xxhash"
|
|
64
|
+
|
|
65
|
+
# Frame and FSE modules
|
|
66
|
+
autoload :Frame, "omnizip/algorithms/zstandard/frame"
|
|
67
|
+
autoload :FSE, "omnizip/algorithms/zstandard/fse"
|
|
68
|
+
|
|
69
|
+
# Get algorithm metadata
|
|
70
|
+
#
|
|
71
|
+
# @return [AlgorithmMetadata] Algorithm information
|
|
72
|
+
def self.metadata
|
|
73
|
+
Models::AlgorithmMetadata.new.tap do |meta|
|
|
74
|
+
meta.name = "zstandard"
|
|
75
|
+
meta.description = "Zstandard fast compression with " \
|
|
76
|
+
"excellent ratios"
|
|
77
|
+
meta.version = "1.0.0"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Compress data using Zstandard algorithm
|
|
82
|
+
#
|
|
83
|
+
# @param input_stream [IO] Input stream to compress
|
|
84
|
+
# @param output_stream [IO] Output stream for compressed data
|
|
85
|
+
# @param options [Models::CompressionOptions] Compression options
|
|
86
|
+
# @return [void]
|
|
87
|
+
def compress(input_stream, output_stream, options = nil)
|
|
88
|
+
input_data = input_stream.read
|
|
89
|
+
level = build_encoder_options(options)[:level] || 3
|
|
90
|
+
output_stream.write(
|
|
91
|
+
Backends.compress("zstd", input_data, level) do
|
|
92
|
+
encoder = Encoder.new(output_stream, build_encoder_options(options))
|
|
93
|
+
encoder.encode_stream(input_data)
|
|
94
|
+
end,
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Decompress Zstandard-compressed data
|
|
99
|
+
#
|
|
100
|
+
# @param input_stream [IO] Input stream of compressed data
|
|
101
|
+
# @param output_stream [IO] Output stream for decompressed data
|
|
102
|
+
# @param options [Models::CompressionOptions] Decompression options
|
|
103
|
+
# @return [void]
|
|
104
|
+
def decompress(input_stream, output_stream, _options = nil)
|
|
105
|
+
output_stream.set_encoding(Encoding::BINARY)
|
|
106
|
+
compressed = input_stream.read
|
|
107
|
+
decompressed = Backends.decompress("zstd", compressed, Backends::UNKNOWN_LENGTH) do
|
|
108
|
+
Decoder.new(StringIO.new(compressed)).decode_stream
|
|
109
|
+
end
|
|
110
|
+
output_stream.write(decompressed)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Compress data primed with a dictionary prefix: the dictionary
|
|
114
|
+
# content acts as shared history the match finder can reference,
|
|
115
|
+
# dramatically improving ratios on small inputs. The resulting
|
|
116
|
+
# frame carries the dictionary's ID and requires
|
|
117
|
+
# decompress_with_dict to decode.
|
|
118
|
+
#
|
|
119
|
+
# @param input_stream [IO] plaintext
|
|
120
|
+
# @param output_stream [IO] compressed frame
|
|
121
|
+
# @param dict [Dictionary]
|
|
122
|
+
# @param options [Hash] :level, :checksum
|
|
123
|
+
# @return [void]
|
|
124
|
+
def compress_with_dict(input_stream, output_stream, dict, options = {})
|
|
125
|
+
encoder = Encoder.new(output_stream, build_encoder_options(options))
|
|
126
|
+
encoder.encode_stream_with_dict(input_stream.read, dict)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Decompress a frame produced by compress_with_dict. The frame's
|
|
130
|
+
# dictionary ID is verified against `dict` before decoding.
|
|
131
|
+
#
|
|
132
|
+
# @param input_stream [IO] compressed frame
|
|
133
|
+
# @param output_stream [IO] plaintext
|
|
134
|
+
# @param dict [Dictionary]
|
|
135
|
+
# @return [void]
|
|
136
|
+
def decompress_with_dict(input_stream, output_stream, dict)
|
|
137
|
+
output_stream.set_encoding(Encoding::BINARY)
|
|
138
|
+
decoder = Decoder.new(input_stream)
|
|
139
|
+
output_stream.write(decoder.decode_stream_with_dict(dict))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Class-level convenience mirrors of the dictionary API.
|
|
143
|
+
#
|
|
144
|
+
# @return [String] compressed frame / decompressed plaintext
|
|
145
|
+
def self.compress_with_dict(data, dict, **options)
|
|
146
|
+
output = StringIO.new
|
|
147
|
+
output.set_encoding(Encoding::BINARY)
|
|
148
|
+
new(options).compress_with_dict(
|
|
149
|
+
StringIO.new(data.to_s.b), output, dict, options
|
|
150
|
+
)
|
|
151
|
+
output.string
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def self.decompress_with_dict(data, dict)
|
|
155
|
+
output = StringIO.new
|
|
156
|
+
output.set_encoding(Encoding::BINARY)
|
|
157
|
+
new.decompress_with_dict(StringIO.new(data.to_s.b), output, dict)
|
|
158
|
+
output.string
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
private
|
|
162
|
+
|
|
163
|
+
# Build encoder options from compression options
|
|
164
|
+
#
|
|
165
|
+
# Always sets :level, defaulting to the zstd default (3) so that
|
|
166
|
+
# `compress(data)` never silently degrades to stored frames
|
|
167
|
+
# (issue #27). Accepts a Hash (as forwarded by Algorithm.compress)
|
|
168
|
+
# or a Models::CompressionOptions.
|
|
169
|
+
#
|
|
170
|
+
# @param options [Models::CompressionOptions, Hash, nil]
|
|
171
|
+
# @return [Hash] Encoder options
|
|
172
|
+
def build_encoder_options(options)
|
|
173
|
+
level = case options
|
|
174
|
+
when nil then nil
|
|
175
|
+
when Hash then options[:level]
|
|
176
|
+
# allowed: options is a public parameter; any object with #level is honored
|
|
177
|
+
else options.level if options.respond_to?(:level)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
{ level: map_compression_level(level) }
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Map generic compression level (0-9) to Zstd level (1-22)
|
|
184
|
+
#
|
|
185
|
+
# @param level [Integer] Compression level (0-9)
|
|
186
|
+
# @return [Integer] Zstd compression level (1-22)
|
|
187
|
+
def map_compression_level(level)
|
|
188
|
+
return 3 if level.nil? # Zstd default
|
|
189
|
+
|
|
190
|
+
case level
|
|
191
|
+
when 0 then 1 # Fastest
|
|
192
|
+
when 1 then 2
|
|
193
|
+
when 2 then 3
|
|
194
|
+
when 3 then 5
|
|
195
|
+
when 4 then 7
|
|
196
|
+
when 5 then 10
|
|
197
|
+
when 6 then 13
|
|
198
|
+
when 7 then 16
|
|
199
|
+
when 8 then 19
|
|
200
|
+
when 9 then 22 # Maximum
|
|
201
|
+
else level
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Register the Zstandard algorithm
|
|
209
|
+
Omnizip::AlgorithmRegistry.register(:zstandard,
|
|
210
|
+
Omnizip::Algorithms::Zstandard)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
# High-level compression algorithm facades.
|
|
5
|
+
#
|
|
6
|
+
# Each top-level constant in this namespace (Deflate, BZip2, LZMA,
|
|
7
|
+
# LZMA2, Zstandard, PPMd7, PPMd8) is a facade that exposes the
|
|
8
|
+
# streaming +.compress+/+.decompress+ contract from +Omnizip::Algorithm+.
|
|
9
|
+
# Format-specific readers/writers call these facades for the actual
|
|
10
|
+
# compression work; the facades themselves do not know about archive
|
|
11
|
+
# container structure.
|
|
12
|
+
#
|
|
13
|
+
# Bit-level SDK ports (state machines, range coders, match finders)
|
|
14
|
+
# live under +Omnizip::Implementations+, not here. This namespace
|
|
15
|
+
# owns the *streaming contract*; that namespace owns the *primitives*.
|
|
16
|
+
# The boundary is: +Algorithms+ calls +Implementations+, never the
|
|
17
|
+
# reverse.
|
|
18
|
+
module Algorithms
|
|
19
|
+
autoload :PPMdBase, "omnizip/algorithms/ppmd_base"
|
|
20
|
+
autoload :LZMA2Const, "omnizip/algorithms/lzma2/constants"
|
|
21
|
+
autoload :LZMA, "omnizip/algorithms/lzma"
|
|
22
|
+
autoload :LZMA2, "omnizip/algorithms/lzma2"
|
|
23
|
+
autoload :LZMA2XzEncoderAdapter,
|
|
24
|
+
"omnizip/algorithms/lzma2/xz_encoder_adapter"
|
|
25
|
+
autoload :LZMA2Chunk, "omnizip/algorithms/lzma2/lzma2_chunk"
|
|
26
|
+
autoload :LZMA2Encoder, "omnizip/algorithms/lzma2/encoder"
|
|
27
|
+
autoload :XzUtilsDecoder, "omnizip/algorithms/lzma/xz_utils_decoder"
|
|
28
|
+
autoload :PPMd7, "omnizip/algorithms/ppmd7"
|
|
29
|
+
autoload :PPMd8, "omnizip/algorithms/ppmd8"
|
|
30
|
+
autoload :BZip2, "omnizip/algorithms/bzip2"
|
|
31
|
+
autoload :Deflate, "omnizip/algorithms/deflate"
|
|
32
|
+
autoload :Deflate64, "omnizip/algorithms/deflate64"
|
|
33
|
+
autoload :Zstandard, "omnizip/algorithms/zstandard"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Archive
|
|
5
|
+
# Block argument of +Archive.create+. Translates the documented
|
|
6
|
+
# +add_file+/+add_directory+/+add_data+ vocabulary onto the
|
|
7
|
+
# handler proxy's +add(name, source_path)+ / +add_data+ calls.
|
|
8
|
+
class Builder
|
|
9
|
+
def initialize(proxy)
|
|
10
|
+
@proxy = proxy
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Add a file from disk, optionally under a different archive
|
|
14
|
+
# path: +add_file('report.pdf', 'reports/report.pdf')+.
|
|
15
|
+
def add_file(file_path, archive_path = nil)
|
|
16
|
+
@proxy.add(archive_path || ::File.basename(file_path), file_path)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Add a directory tree under its own name:
|
|
20
|
+
# +add_directory('photos/')+ stores +photos/x.jpg+.
|
|
21
|
+
def add_directory(dir_path)
|
|
22
|
+
prefix = ::File.basename(::File.expand_path(dir_path))
|
|
23
|
+
@proxy.add("#{prefix}/")
|
|
24
|
+
walk(dir_path, prefix)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Add in-memory content at +archive_path+.
|
|
28
|
+
def add_data(archive_path, data)
|
|
29
|
+
@proxy.add_data(archive_path, data)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def walk(dir, prefix)
|
|
35
|
+
::Dir.children(dir).sort.each do |child|
|
|
36
|
+
full = ::File.join(dir, child)
|
|
37
|
+
name = "#{prefix}/#{child}"
|
|
38
|
+
if ::File.directory?(full)
|
|
39
|
+
@proxy.add("#{name}/")
|
|
40
|
+
walk(full, name)
|
|
41
|
+
else
|
|
42
|
+
@proxy.add(name, full)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Archive
|
|
7
|
+
# Block argument (and return value) of +Archive.open+. Delegates
|
|
8
|
+
# per operation to the resolved ArchiveHandler, which opens and
|
|
9
|
+
# closes the underlying reader on every call — the session itself
|
|
10
|
+
# holds no resources.
|
|
11
|
+
class ReaderSession
|
|
12
|
+
def initialize(handler, path, options = {})
|
|
13
|
+
@handler = handler
|
|
14
|
+
@path = path
|
|
15
|
+
@options = options
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Archive metadata records (see Archive::Entry).
|
|
19
|
+
def entries
|
|
20
|
+
@handler.list(@path, details: true, **@options).map do |h|
|
|
21
|
+
Entry.new(name: h[:name], size: h[:size], directory: h[:directory],
|
|
22
|
+
mtime: h[:mtime] || h[:time])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def each_entry(&block)
|
|
27
|
+
entries.each(&block)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Contents of a single entry, without extraction.
|
|
31
|
+
def read(entry_name)
|
|
32
|
+
@handler.read_entry(@path, entry_name, **@options)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Extract one entry to an explicit destination path.
|
|
36
|
+
def extract(entry_name, dest_path)
|
|
37
|
+
entry = entries.find { |e| e.name == entry_name }
|
|
38
|
+
unless entry
|
|
39
|
+
raise Errno::ENOENT, "Entry not found: #{entry_name}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
if entry.directory?
|
|
43
|
+
::FileUtils.mkdir_p(dest_path)
|
|
44
|
+
return dest_path
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
::FileUtils.mkdir_p(::File.dirname(dest_path))
|
|
48
|
+
::File.binwrite(dest_path, read(entry_name))
|
|
49
|
+
dest_path
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def extract_all(output_dir)
|
|
53
|
+
@handler.extract_to(@path, output_dir, **@options)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Extract every entry whose name matches +pattern+ under
|
|
57
|
+
# +output_dir+, preserving archive-relative paths.
|
|
58
|
+
def extract_matching(pattern, output_dir)
|
|
59
|
+
::FileUtils.mkdir_p(output_dir)
|
|
60
|
+
entries.select do |e|
|
|
61
|
+
!e.directory? && ::File.fnmatch?(pattern, e.name,
|
|
62
|
+
::File::FNM_PATHNAME)
|
|
63
|
+
end.map { |e| extract(e.name, ::File.join(output_dir, e.name)) }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
# High-level block-style archive facade over the registered
|
|
5
|
+
# ArchiveHandlers. This is the API the guides document:
|
|
6
|
+
#
|
|
7
|
+
# Omnizip::Archive.create('backup.7z', format: :seven_zip,
|
|
8
|
+
# level: 9) do |archive|
|
|
9
|
+
# archive.add_file('report.pdf', 'reports/report.pdf')
|
|
10
|
+
# archive.add_directory('photos/')
|
|
11
|
+
# archive.add_data('notes/readme.txt', "generated\n")
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# Omnizip::Archive.open('backup.7z') do |archive|
|
|
15
|
+
# archive.entries.each { |e| puts "#{e.name} (#{e.size})" }
|
|
16
|
+
# archive.read('notes/readme.txt')
|
|
17
|
+
# archive.extract_all('output/')
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# The format is resolved from the output path's extension when
|
|
21
|
+
# +format:+ is not given explicitly, exactly like the convenience
|
|
22
|
+
# methods. Passwords are supported for 7z only (ZIP writing and
|
|
23
|
+
# reading have no encryption support); asking for one elsewhere
|
|
24
|
+
# raises rather than silently producing an unprotected archive.
|
|
25
|
+
module Archive
|
|
26
|
+
autoload :Builder, "omnizip/archive/builder"
|
|
27
|
+
autoload :ReaderSession, "omnizip/archive/reader_session"
|
|
28
|
+
|
|
29
|
+
# Metadata record yielded by ReaderSession#entries. The +size+
|
|
30
|
+
# member intentionally shadows Struct#size: the documented
|
|
31
|
+
# contract is entry size in bytes, not the member count.
|
|
32
|
+
# rubocop:disable-next Lint/StructNewOverride -- documented byte size
|
|
33
|
+
Entry = Struct.new(:name, :size, :directory, :mtime, keyword_init: true) do
|
|
34
|
+
def directory?
|
|
35
|
+
directory
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
PASSWORD_FORMATS = %i[seven_zip rar].freeze
|
|
40
|
+
private_constant :PASSWORD_FORMATS
|
|
41
|
+
|
|
42
|
+
class << self
|
|
43
|
+
# Create an archive, yielding a Builder that translates the
|
|
44
|
+
# documented +add_file+/+add_directory+/+add_data+ calls onto
|
|
45
|
+
# the resolved handler. Returns the archive path.
|
|
46
|
+
def create(path, format: Convenience::DEFAULT_FORMAT, **options, &block)
|
|
47
|
+
resolved = Omnizip.resolve_archive_format(path, format)
|
|
48
|
+
check_password_support!(resolved, options[:password])
|
|
49
|
+
|
|
50
|
+
Omnizip::ArchiveHandler.for(resolved).create(path, **options) do |proxy|
|
|
51
|
+
block&.call(Builder.new(proxy))
|
|
52
|
+
end
|
|
53
|
+
path
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Open an archive for reading, yielding a ReaderSession. Without
|
|
57
|
+
# a block, returns the session. An explicit +password:+ wins
|
|
58
|
+
# over ENV['OMNIZIP_PASSWORD'].
|
|
59
|
+
def open(path, password: nil, **options, &block)
|
|
60
|
+
resolved = Omnizip.resolve_archive_format(
|
|
61
|
+
path, Convenience::DEFAULT_FORMAT, writing: false
|
|
62
|
+
)
|
|
63
|
+
pw = password || ENV.fetch("OMNIZIP_PASSWORD", nil)
|
|
64
|
+
check_password_support!(resolved, pw)
|
|
65
|
+
|
|
66
|
+
options[:password] = pw if pw
|
|
67
|
+
session = ReaderSession.new(
|
|
68
|
+
Omnizip::ArchiveHandler.for(resolved), path, options
|
|
69
|
+
)
|
|
70
|
+
return session unless block
|
|
71
|
+
|
|
72
|
+
yield session
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def check_password_support!(resolved, password)
|
|
78
|
+
return unless password && !PASSWORD_FORMATS.include?(resolved)
|
|
79
|
+
|
|
80
|
+
raise Omnizip::UnsupportedFormatError,
|
|
81
|
+
"password is only supported for #{PASSWORD_FORMATS.join(', ')}; " \
|
|
82
|
+
"#{resolved.inspect} has no encryption support"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
# Unified archive handler interface for the Convenience module.
|
|
5
|
+
#
|
|
6
|
+
# Each format that wants to participate in Omnizip.compress_file /
|
|
7
|
+
# extract_archive / etc. registers a Handler here. The Handler exposes
|
|
8
|
+
# a small canonical API (+create+, +open+, +extract_to+, +list+) that
|
|
9
|
+
# the Convenience module calls; the Handler then delegates to the
|
|
10
|
+
# format-specific reader/writer.
|
|
11
|
+
#
|
|
12
|
+
# @example Register a format
|
|
13
|
+
# Omnizip::ArchiveHandler.register(:tar, TarHandler.new)
|
|
14
|
+
#
|
|
15
|
+
# @example Use from a caller
|
|
16
|
+
# Omnizip::ArchiveHandler.for(:tar).create(path) { |w| w.add_file(...) }
|
|
17
|
+
module ArchiveHandler
|
|
18
|
+
@handlers = {}
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
# Register a handler for a format symbol.
|
|
22
|
+
#
|
|
23
|
+
# @param format [Symbol] e.g. +:zip+, +:tar+
|
|
24
|
+
# @param handler [Object] responding to the Handler interface
|
|
25
|
+
# @return [void]
|
|
26
|
+
def register(format, handler)
|
|
27
|
+
@handlers[format.to_sym] = handler
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Look up the handler for +format+. Triggers the registered lazy
|
|
31
|
+
# load constant if the format is one of the built-ins.
|
|
32
|
+
#
|
|
33
|
+
# @param format [Symbol]
|
|
34
|
+
# @return [Object]
|
|
35
|
+
# @raise [Omnizip::UnsupportedFormatError] if +format+ is unknown
|
|
36
|
+
def for(format)
|
|
37
|
+
handler = @handlers[format.to_sym]
|
|
38
|
+
return handler if handler
|
|
39
|
+
|
|
40
|
+
trigger = LAZY_LOAD_TRIGGERS[format.to_sym]
|
|
41
|
+
if trigger
|
|
42
|
+
trigger.call
|
|
43
|
+
handler = @handlers[format.to_sym]
|
|
44
|
+
return handler if handler
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
raise Omnizip::UnsupportedFormatError,
|
|
48
|
+
"No archive handler registered for #{format.inspect}. " \
|
|
49
|
+
"Registered: #{@handlers.keys.join(', ')}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# List of registered format names.
|
|
53
|
+
#
|
|
54
|
+
# @return [Array<Symbol>]
|
|
55
|
+
def available
|
|
56
|
+
@handlers.keys
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Remove a handler (primarily for testing).
|
|
60
|
+
#
|
|
61
|
+
# @return [void]
|
|
62
|
+
def unregister(format)
|
|
63
|
+
@handlers.delete(format.to_sym)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Lazy triggers — referencing the constant autoloads the handler's
|
|
68
|
+
# file, which then self-registers at the bottom of the file.
|
|
69
|
+
LAZY_LOAD_TRIGGERS = {
|
|
70
|
+
zip: -> { Omnizip::ArchiveHandlers::ZipHandler },
|
|
71
|
+
rpm: -> { Omnizip::ArchiveHandlers::RpmHandler },
|
|
72
|
+
xar: -> { Omnizip::ArchiveHandlers::XarHandler },
|
|
73
|
+
ole: -> { Omnizip::ArchiveHandlers::OleHandler },
|
|
74
|
+
tar: -> { Omnizip::ArchiveHandlers::TarHandler },
|
|
75
|
+
seven_zip: -> { Omnizip::ArchiveHandlers::SevenZipHandler },
|
|
76
|
+
rar: -> { Omnizip::ArchiveHandlers::RarHandler },
|
|
77
|
+
cpio: -> { Omnizip::ArchiveHandlers::CpioHandler },
|
|
78
|
+
iso: -> { Omnizip::ArchiveHandlers::IsoHandler },
|
|
79
|
+
}.freeze
|
|
80
|
+
private_constant :LAZY_LOAD_TRIGGERS
|
|
81
|
+
end
|
|
82
|
+
end
|