omnizip 0.4.7-aarch64-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,294 @@
|
|
|
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
|
+
# Pure Ruby Zstandard encoder (RFC 8878).
|
|
27
|
+
#
|
|
28
|
+
# Emits a single-segment frame. Each 128 KiB chunk becomes one
|
|
29
|
+
# block, choosing whichever is smallest: RLE, a Compressed_Block
|
|
30
|
+
# (LZ77 match finding + Huffman literals + FSE-coded sequences),
|
|
31
|
+
# or a Raw_Block fallback for incompressible data. The match
|
|
32
|
+
# finder works over absolute positions, so blocks can reference
|
|
33
|
+
# earlier blocks; repeat-offset state is carried between blocks
|
|
34
|
+
# exactly as the decoder tracks it.
|
|
35
|
+
class Encoder
|
|
36
|
+
include Constants
|
|
37
|
+
|
|
38
|
+
attr_reader :output_stream, :options
|
|
39
|
+
|
|
40
|
+
# Initialize encoder
|
|
41
|
+
#
|
|
42
|
+
# @param output_stream [IO] output for compressed data
|
|
43
|
+
# @param options [Hash]
|
|
44
|
+
# @option options [Integer] :level compression level (1-22)
|
|
45
|
+
# @option options [Boolean] :checksum write the frame checksum
|
|
46
|
+
def initialize(output_stream, options = {})
|
|
47
|
+
@output_stream = output_stream
|
|
48
|
+
@options = options
|
|
49
|
+
@level = options[:level] || DEFAULT_LEVEL
|
|
50
|
+
@checksum = options.fetch(:checksum, false)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Encode a data stream
|
|
54
|
+
#
|
|
55
|
+
# @param data [String]
|
|
56
|
+
def encode_stream(data)
|
|
57
|
+
data = data.dup.force_encoding(Encoding::BINARY)
|
|
58
|
+
write_frame(data)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Encode a data stream primed with a dictionary prefix (port
|
|
62
|
+
# of the Rust encode_frame_with_dict): the dictionary content
|
|
63
|
+
# is prepended as virtual history, the match finder is seeded
|
|
64
|
+
# with its positions, and only the plaintext is emitted.
|
|
65
|
+
# Frame_Content_Size and the checksum cover the plaintext
|
|
66
|
+
# only; the frame header carries the dictionary's ID and
|
|
67
|
+
# requires the dict-aware decoder.
|
|
68
|
+
#
|
|
69
|
+
# @param data [String]
|
|
70
|
+
# @param dict [Dictionary]
|
|
71
|
+
def encode_stream_with_dict(data, dict)
|
|
72
|
+
data = data.dup.force_encoding(Encoding::BINARY)
|
|
73
|
+
virtual = dict.content + data
|
|
74
|
+
prefix_len = dict.content.bytesize
|
|
75
|
+
|
|
76
|
+
write_u32le(MAGIC_NUMBER)
|
|
77
|
+
write_frame_header(data, dict.id)
|
|
78
|
+
write_blocks(virtual, prefix_len)
|
|
79
|
+
write_u32le(XXHash64.frame_checksum(data)) if @checksum
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def write_frame(data, dict = nil)
|
|
85
|
+
write_u32le(MAGIC_NUMBER)
|
|
86
|
+
write_frame_header(data, dict && dict.id)
|
|
87
|
+
write_blocks(data)
|
|
88
|
+
write_u32le(XXHash64.frame_checksum(data)) if @checksum
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Single-segment frame header: no window descriptor;
|
|
92
|
+
# optional Dictionary_ID, then Frame_Content_Size in 1, 2, 4
|
|
93
|
+
# or 8 bytes.
|
|
94
|
+
def write_frame_header(data, dict_id = nil)
|
|
95
|
+
did_flag, did_bytes = dict_id_encoding(dict_id)
|
|
96
|
+
|
|
97
|
+
size = data.bytesize
|
|
98
|
+
if size < 256
|
|
99
|
+
@output_stream.putc(0x20 | did_flag) # single segment, FCS 1 byte
|
|
100
|
+
write_dict_id_bytes(did_bytes)
|
|
101
|
+
@output_stream.putc(size)
|
|
102
|
+
elsif size <= 65_791
|
|
103
|
+
@output_stream.putc(0x60 | did_flag) # single segment, FCS 2 bytes
|
|
104
|
+
write_dict_id_bytes(did_bytes)
|
|
105
|
+
write_u16le(size - 256)
|
|
106
|
+
elsif size <= 0xFFFFFFFF
|
|
107
|
+
@output_stream.putc(0xA0 | did_flag) # single segment, FCS 4 bytes
|
|
108
|
+
write_dict_id_bytes(did_bytes)
|
|
109
|
+
write_u32le(size)
|
|
110
|
+
else
|
|
111
|
+
@output_stream.putc(0xE0 | did_flag) # single segment, FCS 8 bytes
|
|
112
|
+
write_dict_id_bytes(did_bytes)
|
|
113
|
+
write_u64le(size)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def dict_id_encoding(dict_id)
|
|
118
|
+
return [0, "".b] if dict_id.nil? || dict_id.zero?
|
|
119
|
+
return [1, [dict_id].pack("C")] if dict_id <= 0xFF
|
|
120
|
+
return [2, [dict_id].pack("v")] if dict_id <= 0xFFFF
|
|
121
|
+
|
|
122
|
+
[3, [dict_id].pack("V")]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def write_dict_id_bytes(bytes)
|
|
126
|
+
@output_stream.write(bytes)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# rubocop:disable Metrics/MethodLength
|
|
130
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
131
|
+
def write_blocks(data, start = 0)
|
|
132
|
+
return write_empty_last_block if data.bytesize <= start
|
|
133
|
+
|
|
134
|
+
params = MatchFinder.params_for_level(@level, data.bytesize)
|
|
135
|
+
ms = MatchFinder::MatchState.new(params[:hash_log])
|
|
136
|
+
ms.enable_chain(params[:chain]) if params[:chain].positive?
|
|
137
|
+
ms.seed_prefix(data, start) if start.positive?
|
|
138
|
+
|
|
139
|
+
# LDM (long-distance matching) at high levels on multi-block
|
|
140
|
+
# inputs: a sparse table over the whole frame finds matches
|
|
141
|
+
# beyond the 128 KiB block window. Chains are disabled —
|
|
142
|
+
# the chain table is block-sized and LDM provides the
|
|
143
|
+
# long-distance coverage instead (Rust reference behavior).
|
|
144
|
+
ldm = nil
|
|
145
|
+
max_distance = BLOCK_MAX_SIZE
|
|
146
|
+
if @level >= LDM_MIN_LEVEL && data.bytesize > BLOCK_MAX_SIZE
|
|
147
|
+
window_log = data.bytesize.bit_length.clamp(10, 31)
|
|
148
|
+
ldm = LdmHashTable.new(data.bytesize, window_log)
|
|
149
|
+
(0...data.bytesize).each { |pos| ldm.insert(data, pos) }
|
|
150
|
+
ms.disable_chain
|
|
151
|
+
max_distance = data.bytesize
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Wire repeat-offset state carried across blocks; matches the
|
|
155
|
+
# decoder's executor state. Raw and RLE blocks leave it
|
|
156
|
+
# untouched.
|
|
157
|
+
reps = [1, 4, 8]
|
|
158
|
+
|
|
159
|
+
offset = start
|
|
160
|
+
while offset < data.bytesize
|
|
161
|
+
block_end = [offset + BLOCK_MAX_SIZE, data.bytesize].min
|
|
162
|
+
is_last = block_end == data.bytesize
|
|
163
|
+
chunk = data.byteslice(offset, block_end - offset)
|
|
164
|
+
|
|
165
|
+
# Adaptive splitting (port of the Rust reference): a
|
|
166
|
+
# heterogeneous chunk — first and second halves' byte
|
|
167
|
+
# distributions diverge — is split into 16 KiB sub-blocks
|
|
168
|
+
# so each Huffman/FSE table fits its region; homogeneous
|
|
169
|
+
# chunks keep the single block and its minimal header
|
|
170
|
+
# overhead.
|
|
171
|
+
step = if chunk.bytesize >= 32 * 1024 &&
|
|
172
|
+
halves_diverge(chunk)
|
|
173
|
+
16 * 1024
|
|
174
|
+
else
|
|
175
|
+
chunk.bytesize
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
sub = offset
|
|
179
|
+
while sub < block_end
|
|
180
|
+
sub_end = [sub + step, block_end].min
|
|
181
|
+
sub_last = is_last && sub_end == block_end
|
|
182
|
+
sub_chunk = data.byteslice(sub, sub_end - sub)
|
|
183
|
+
|
|
184
|
+
if sub_chunk.bytesize >= 4 && rle_chunk?(sub_chunk)
|
|
185
|
+
write_block_header(sub_last ? 1 : 0, BLOCK_TYPE_RLE,
|
|
186
|
+
sub_chunk.bytesize)
|
|
187
|
+
@output_stream.putc(sub_chunk.getbyte(0))
|
|
188
|
+
else
|
|
189
|
+
seq_store = MatchFinder::SeqStore.new(reps.dup)
|
|
190
|
+
MatchFinder.compress_range(data, sub, sub_end, seq_store,
|
|
191
|
+
ms, params[:min_match],
|
|
192
|
+
params[:lazy], ldm, max_distance)
|
|
193
|
+
content, new_reps = try_compressed(seq_store, reps)
|
|
194
|
+
if content.nil?
|
|
195
|
+
write_block_header(sub_last ? 1 : 0, BLOCK_TYPE_RAW,
|
|
196
|
+
sub_chunk.bytesize)
|
|
197
|
+
@output_stream.write(sub_chunk)
|
|
198
|
+
else
|
|
199
|
+
write_block_header(sub_last ? 1 : 0,
|
|
200
|
+
BLOCK_TYPE_COMPRESSED,
|
|
201
|
+
content.bytesize)
|
|
202
|
+
@output_stream.write(content)
|
|
203
|
+
reps = new_reps
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
sub = sub_end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
offset = block_end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
# rubocop:enable Metrics/MethodLength
|
|
214
|
+
|
|
215
|
+
def write_empty_last_block
|
|
216
|
+
write_block_header(1, BLOCK_TYPE_RAW, 0)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Whether the byte distributions of a chunk's halves diverge
|
|
220
|
+
# (total-variation sum above 0.5 = "different content
|
|
221
|
+
# regimes", per the Rust reference).
|
|
222
|
+
def halves_diverge(chunk)
|
|
223
|
+
mid = chunk.bytesize / 2
|
|
224
|
+
ha = Array.new(256, 0)
|
|
225
|
+
hb = Array.new(256, 0)
|
|
226
|
+
chunk.byteslice(0, mid).each_byte { |b| ha[b] += 1 }
|
|
227
|
+
chunk.byteslice(mid, chunk.bytesize - mid).each_byte { |b| hb[b] += 1 }
|
|
228
|
+
la = mid.to_f
|
|
229
|
+
lb = (chunk.bytesize - mid).to_f
|
|
230
|
+
tvd = 0.0
|
|
231
|
+
256.times { |i| tvd += ((ha[i] / la) - (hb[i] / lb)).abs }
|
|
232
|
+
tvd > 0.5
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Build a Compressed_Block content: literals section plus the
|
|
236
|
+
# sequences section. Returns [content, wire_reps], or [nil,
|
|
237
|
+
# nil] when the result is not smaller than the raw chunk.
|
|
238
|
+
#
|
|
239
|
+
# The chunk's decompressed size is the literal bytes plus every
|
|
240
|
+
# sequence's match length.
|
|
241
|
+
#
|
|
242
|
+
# @param initial_reps [Array<Integer>] wire rep state the
|
|
243
|
+
# decoder holds before this block
|
|
244
|
+
def try_compressed(seq_store, initial_reps)
|
|
245
|
+
literals_section = LiteralsEncoder.encode(seq_store.literals)
|
|
246
|
+
sequences_section, wire_reps =
|
|
247
|
+
SequencesEncoder.encode_section(seq_store, initial_reps)
|
|
248
|
+
content = literals_section + sequences_section
|
|
249
|
+
chunk_size = seq_store.literals.bytesize +
|
|
250
|
+
seq_store.sequences.sum(&:match_length)
|
|
251
|
+
return [nil, nil] if content.bytesize >= chunk_size
|
|
252
|
+
|
|
253
|
+
[content, wire_reps]
|
|
254
|
+
rescue Omnizip::CompressionError
|
|
255
|
+
[nil, nil]
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def rle_chunk?(chunk)
|
|
259
|
+
first = chunk.getbyte(0)
|
|
260
|
+
idx = 1
|
|
261
|
+
while idx < chunk.bytesize
|
|
262
|
+
return false if chunk.getbyte(idx) != first
|
|
263
|
+
|
|
264
|
+
idx += 1
|
|
265
|
+
end
|
|
266
|
+
true
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def write_block_header(last, type, size)
|
|
270
|
+
header = (last & 1) | (type << 1) | (size << 3)
|
|
271
|
+
@output_stream.putc(header & 0xFF)
|
|
272
|
+
@output_stream.putc((header >> 8) & 0xFF)
|
|
273
|
+
@output_stream.putc((header >> 16) & 0xFF)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def write_u16le(value)
|
|
277
|
+
@output_stream.putc(value & 0xFF)
|
|
278
|
+
@output_stream.putc((value >> 8) & 0xFF)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def write_u32le(value)
|
|
282
|
+
@output_stream.putc(value & 0xFF)
|
|
283
|
+
@output_stream.putc((value >> 8) & 0xFF)
|
|
284
|
+
@output_stream.putc((value >> 16) & 0xFF)
|
|
285
|
+
@output_stream.putc((value >> 24) & 0xFF)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def write_u64le(value)
|
|
289
|
+
8.times { |i| @output_stream.putc((value >> (8 * i)) & 0xFF) }
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
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
|
+
module Frame
|
|
27
|
+
# Zstandard block header parser (RFC 8878 Section 3.1.1.2)
|
|
28
|
+
#
|
|
29
|
+
# Block_Header structure (3 bytes, little-endian):
|
|
30
|
+
# - Last_Block: bit 0
|
|
31
|
+
# - Block_Type: bits 1-2
|
|
32
|
+
# - Block_Size: bits 3-23
|
|
33
|
+
class Block
|
|
34
|
+
include Constants
|
|
35
|
+
|
|
36
|
+
# @return [Boolean] True if this is the last block
|
|
37
|
+
attr_reader :last_block
|
|
38
|
+
|
|
39
|
+
# @return [Integer] Block type (0=Raw, 1=RLE, 2=Compressed, 3=Reserved)
|
|
40
|
+
attr_reader :block_type
|
|
41
|
+
|
|
42
|
+
# @return [Integer] Block size in bytes
|
|
43
|
+
attr_reader :block_size
|
|
44
|
+
|
|
45
|
+
# @return [Integer] Block header bytes
|
|
46
|
+
attr_reader :raw_header
|
|
47
|
+
|
|
48
|
+
# Parse block header from input
|
|
49
|
+
#
|
|
50
|
+
# @param input [IO] Input stream positioned at block header
|
|
51
|
+
# @return [Block] Parsed block header
|
|
52
|
+
def self.parse(input)
|
|
53
|
+
bytes = input.read(3)
|
|
54
|
+
# Read 3 bytes as little-endian 24-bit value
|
|
55
|
+
raw = bytes.nil? ? 0 : (bytes.getbyte(0) | (bytes.getbyte(1) << 8) | (bytes.getbyte(2) << 16))
|
|
56
|
+
last_block = raw.allbits?(0x01)
|
|
57
|
+
block_type = (raw >> 1) & 0x03
|
|
58
|
+
block_size = (raw >> 3) & 0x1FFFFF
|
|
59
|
+
|
|
60
|
+
new(last_block, block_type, block_size, raw)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Parse block header from a byte string.
|
|
64
|
+
#
|
|
65
|
+
# @param data [String]
|
|
66
|
+
# @param pos [Integer] offset of the 3-byte header
|
|
67
|
+
# @return [Array(Block, Integer)] block and position after the
|
|
68
|
+
# header
|
|
69
|
+
def self.parse_from(data, pos)
|
|
70
|
+
raw = data.getbyte(pos) |
|
|
71
|
+
(data.getbyte(pos + 1) << 8) |
|
|
72
|
+
(data.getbyte(pos + 2) << 16)
|
|
73
|
+
last_block = raw.allbits?(0x01)
|
|
74
|
+
block_type = (raw >> 1) & 0x03
|
|
75
|
+
block_size = (raw >> 3) & 0x1FFFFF
|
|
76
|
+
|
|
77
|
+
[new(last_block, block_type, block_size, raw), pos + 3]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Initialize with parsed values
|
|
81
|
+
#
|
|
82
|
+
# @param last_block [Boolean]
|
|
83
|
+
# @param block_type [Integer]
|
|
84
|
+
# @param block_size [Integer]
|
|
85
|
+
# @param raw_header [Integer]
|
|
86
|
+
def initialize(last_block, block_type, block_size, raw_header)
|
|
87
|
+
@last_block = last_block
|
|
88
|
+
@block_type = block_type
|
|
89
|
+
@block_size = block_size
|
|
90
|
+
@raw_header = raw_header
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Check if this is a raw (uncompressed) block
|
|
94
|
+
#
|
|
95
|
+
# @return [Boolean]
|
|
96
|
+
def raw?
|
|
97
|
+
@block_type == BLOCK_TYPE_RAW
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Check if this is an RLE block
|
|
101
|
+
#
|
|
102
|
+
# @return [Boolean]
|
|
103
|
+
def rle?
|
|
104
|
+
@block_type == BLOCK_TYPE_RLE
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Check if this is a compressed block
|
|
108
|
+
#
|
|
109
|
+
# @return [Boolean]
|
|
110
|
+
def compressed?
|
|
111
|
+
@block_type == BLOCK_TYPE_COMPRESSED
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Check if block type is reserved
|
|
115
|
+
#
|
|
116
|
+
# @return [Boolean]
|
|
117
|
+
def reserved?
|
|
118
|
+
@block_type == BLOCK_TYPE_RESERVED
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Validate block type
|
|
122
|
+
#
|
|
123
|
+
# @return [Boolean] True if block type is valid
|
|
124
|
+
def valid?
|
|
125
|
+
!reserved?
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Get block type name
|
|
129
|
+
#
|
|
130
|
+
# @return [Symbol]
|
|
131
|
+
def type_name
|
|
132
|
+
case @block_type
|
|
133
|
+
when BLOCK_TYPE_RAW then :raw
|
|
134
|
+
when BLOCK_TYPE_RLE then :rle
|
|
135
|
+
when BLOCK_TYPE_COMPRESSED then :compressed
|
|
136
|
+
when BLOCK_TYPE_RESERVED then :reserved
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,233 @@
|
|
|
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
|
+
module Frame
|
|
27
|
+
# Zstandard frame header parser (RFC 8878 Section 3.1.1.1)
|
|
28
|
+
#
|
|
29
|
+
# Frame_Header structure:
|
|
30
|
+
# - Frame_Header_Descriptor: 1 byte
|
|
31
|
+
# - Window_Descriptor: 0-1 byte (optional)
|
|
32
|
+
# - Dictionary_ID: 0-4 bytes (optional)
|
|
33
|
+
# - Frame_Content_Size: 0-8 bytes (optional)
|
|
34
|
+
class Header
|
|
35
|
+
include Constants
|
|
36
|
+
|
|
37
|
+
# @return [Integer] Frame content size flag (bits 6-7)
|
|
38
|
+
attr_reader :content_size_flag
|
|
39
|
+
|
|
40
|
+
# @return [Boolean] Single segment flag (bit 5)
|
|
41
|
+
attr_reader :single_segment
|
|
42
|
+
|
|
43
|
+
# @return [Integer] Content checksum flag (bit 2)
|
|
44
|
+
attr_reader :checksum_flag
|
|
45
|
+
|
|
46
|
+
# @return [Integer] Dictionary ID flag (bits 0-1)
|
|
47
|
+
attr_reader :dictionary_id_flag
|
|
48
|
+
|
|
49
|
+
# @return [Integer, nil] Window log value
|
|
50
|
+
attr_reader :window_log
|
|
51
|
+
|
|
52
|
+
# @return [Integer, nil] Dictionary ID
|
|
53
|
+
attr_reader :dictionary_id
|
|
54
|
+
|
|
55
|
+
# @return [Integer, nil] Frame content size
|
|
56
|
+
attr_reader :content_size
|
|
57
|
+
|
|
58
|
+
# @return [Integer] Total header size in bytes
|
|
59
|
+
attr_reader :header_size
|
|
60
|
+
|
|
61
|
+
# Parse frame header from input
|
|
62
|
+
#
|
|
63
|
+
# @param input [IO] Input stream positioned at frame header
|
|
64
|
+
# @return [Header] Parsed header
|
|
65
|
+
def self.parse(input)
|
|
66
|
+
parse_from(input.read, 0).first
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Parse frame header from a byte string.
|
|
70
|
+
#
|
|
71
|
+
# @param data [String]
|
|
72
|
+
# @param pos [Integer] offset of the descriptor byte
|
|
73
|
+
# @return [Array(Header, Integer)] header and position after
|
|
74
|
+
# the header
|
|
75
|
+
def self.parse_from(data, pos)
|
|
76
|
+
descriptor = data.getbyte(pos)
|
|
77
|
+
|
|
78
|
+
header = new(descriptor)
|
|
79
|
+
offset = pos + 1
|
|
80
|
+
|
|
81
|
+
if header.window_descriptor?
|
|
82
|
+
header.parse_window_descriptor_byte(data.getbyte(offset))
|
|
83
|
+
offset += 1
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if header.dictionary_id?
|
|
87
|
+
size = header.dictionary_id_size
|
|
88
|
+
bytes = data.byteslice(offset, size)
|
|
89
|
+
offset += size
|
|
90
|
+
header.assign_dictionary_id(bytes)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if header.content_size?
|
|
94
|
+
size = header.content_size_size
|
|
95
|
+
bytes = data.byteslice(offset, size)
|
|
96
|
+
offset += size
|
|
97
|
+
header.assign_content_size(bytes)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
[header, offset]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Initialize with descriptor byte
|
|
104
|
+
#
|
|
105
|
+
# @param descriptor [Integer] Frame header descriptor byte
|
|
106
|
+
def initialize(descriptor)
|
|
107
|
+
@descriptor = descriptor
|
|
108
|
+
|
|
109
|
+
# Extract flags from descriptor byte
|
|
110
|
+
@content_size_flag = (descriptor >> 6) & 0x03
|
|
111
|
+
@single_segment = (descriptor >> 5).allbits?(0x01)
|
|
112
|
+
@checksum_flag = (descriptor >> 2) & 0x01
|
|
113
|
+
@dictionary_id_flag = descriptor & 0x03
|
|
114
|
+
|
|
115
|
+
@window_log = nil
|
|
116
|
+
@window_mantissa = 0
|
|
117
|
+
@dictionary_id = nil
|
|
118
|
+
@content_size = nil
|
|
119
|
+
@header_size = 1
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Check if window descriptor is present
|
|
123
|
+
#
|
|
124
|
+
# @return [Boolean]
|
|
125
|
+
def window_descriptor?
|
|
126
|
+
!@single_segment
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Check if dictionary ID is present
|
|
130
|
+
#
|
|
131
|
+
# @return [Boolean]
|
|
132
|
+
def dictionary_id?
|
|
133
|
+
@dictionary_id_flag != 0
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Check if content size is present
|
|
137
|
+
#
|
|
138
|
+
# @return [Boolean]
|
|
139
|
+
def content_size?
|
|
140
|
+
@content_size_flag != 0 || @single_segment
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Check if content checksum is present
|
|
144
|
+
#
|
|
145
|
+
# @return [Boolean]
|
|
146
|
+
def content_checksum?
|
|
147
|
+
@checksum_flag == 1
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Get the size of dictionary ID field
|
|
151
|
+
#
|
|
152
|
+
# @return [Integer]
|
|
153
|
+
def dictionary_id_size
|
|
154
|
+
case @dictionary_id_flag
|
|
155
|
+
when 0 then 0
|
|
156
|
+
when 1 then 1
|
|
157
|
+
when 2 then 2
|
|
158
|
+
when 3 then 4
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Get the size of content size field
|
|
163
|
+
#
|
|
164
|
+
# @return [Integer]
|
|
165
|
+
def content_size_size
|
|
166
|
+
if @single_segment
|
|
167
|
+
# For single segment, FCS size depends on content_size_flag
|
|
168
|
+
case @content_size_flag
|
|
169
|
+
when 0 then 1
|
|
170
|
+
when 1 then 2
|
|
171
|
+
when 2 then 4
|
|
172
|
+
when 3 then 8
|
|
173
|
+
end
|
|
174
|
+
else
|
|
175
|
+
case @content_size_flag
|
|
176
|
+
when 0 then 0
|
|
177
|
+
when 1 then 2
|
|
178
|
+
when 2 then 4
|
|
179
|
+
when 3 then 8
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Get window size
|
|
185
|
+
#
|
|
186
|
+
# windowAdd = (windowBase / 8) * Mantissa (RFC 8878
|
|
187
|
+
# §3.1.1.1.2); the mantissa occupies descriptor bits 0-2 and
|
|
188
|
+
# the exponent bits 3-7.
|
|
189
|
+
#
|
|
190
|
+
# @return [Integer, nil] Window size or nil if not applicable
|
|
191
|
+
def window_size
|
|
192
|
+
return nil unless @window_log
|
|
193
|
+
|
|
194
|
+
window_base = 1 << @window_log
|
|
195
|
+
window_base + ((window_base / 8) * @window_mantissa)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Parse window descriptor byte
|
|
199
|
+
def parse_window_descriptor_byte(byte)
|
|
200
|
+
@window_mantissa = byte & 0x07
|
|
201
|
+
@window_log = 10 + ((byte >> 3) & 0x1F)
|
|
202
|
+
@header_size += 1
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Assign the dictionary ID from its wire bytes.
|
|
206
|
+
def assign_dictionary_id(bytes)
|
|
207
|
+
@dictionary_id = case bytes.bytesize
|
|
208
|
+
when 1 then bytes.ord
|
|
209
|
+
when 2 then bytes.unpack1("v")
|
|
210
|
+
when 4 then bytes.unpack1("V")
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
@header_size += bytes.bytesize
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Assign the content size from its wire bytes.
|
|
217
|
+
def assign_content_size(bytes)
|
|
218
|
+
@content_size = case bytes.bytesize
|
|
219
|
+
when 1 then bytes.ord
|
|
220
|
+
when 2 then bytes.unpack1("v") + 256
|
|
221
|
+
when 4 then bytes.unpack1("V")
|
|
222
|
+
when 8
|
|
223
|
+
low, high = bytes.unpack("VV")
|
|
224
|
+
low + (high << 32)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
@header_size += bytes.bytesize
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
# Frame module namespace
|
|
27
|
+
module Frame
|
|
28
|
+
autoload :Header, "omnizip/algorithms/zstandard/frame/header"
|
|
29
|
+
autoload :Block, "omnizip/algorithms/zstandard/frame/block"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|