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.
Files changed (632) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +293 -0
  5. data/CHANGELOG.md +1647 -0
  6. data/CONTEXT.md +68 -0
  7. data/COPYING +502 -0
  8. data/Gemfile +19 -0
  9. data/LICENSE +12 -0
  10. data/README.adoc +1327 -0
  11. data/Rakefile +15 -0
  12. data/TODO.refactor/00-overview.md +67 -0
  13. data/TODO.refactor/01-registry-base-class.md +81 -0
  14. data/TODO.refactor/02-error-hierarchy.md +57 -0
  15. data/TODO.refactor/03-autoload-entry-point.md +69 -0
  16. data/TODO.refactor/04-filter-base-consolidation.md +49 -0
  17. data/TODO.refactor/05-send-private-methods.md +64 -0
  18. data/TODO.refactor/06-instance-variable-access.md +69 -0
  19. data/TODO.refactor/07-respond-to-replacement.md +237 -0
  20. data/TODO.refactor/08-spec-doubles.md +27 -0
  21. data/TODO.refactor/09-cli-shared-module.md +35 -0
  22. data/TODO.refactor/10-format-detector-ocp.md +34 -0
  23. data/TODO.refactor/11-convenience-decoupling.md +38 -0
  24. data/TODO.refactor/12-thread-safety.md +8 -0
  25. data/TODO.refactor/13-lutaml-model-migration.md +158 -0
  26. data/TODO.refactor/14-add-missing-specs.md +25 -0
  27. data/benchmark/README.md +260 -0
  28. data/benchmark/benchmark_suite.rb +125 -0
  29. data/benchmark/compression_bench.rb +181 -0
  30. data/benchmark/filter_bench.rb +180 -0
  31. data/benchmark/models/benchmark_result.rb +59 -0
  32. data/benchmark/models/comparison_result.rb +69 -0
  33. data/benchmark/profile_suite.rb +167 -0
  34. data/benchmark/reporter.rb +150 -0
  35. data/benchmark/run_benchmarks.rb +66 -0
  36. data/benchmark/test_data.rb +137 -0
  37. data/config/formats/rar3_spec.yml +92 -0
  38. data/config/formats/rar5_spec.yml +102 -0
  39. data/docs/.github/workflows/docs.yml +142 -0
  40. data/docs/.gitignore +21 -0
  41. data/docs/.lychee.toml +67 -0
  42. data/docs/Gemfile +13 -0
  43. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  44. data/docs/README.md +101 -0
  45. data/docs/_config.yml +112 -0
  46. data/docs/assets/logo.svg +1 -0
  47. data/docs/assets/omnizip-logo.pdf +1540 -11
  48. data/docs/comparison/feature-matrix.adoc +694 -0
  49. data/docs/comparison/index.adoc +113 -0
  50. data/docs/comparison/vs-7zip.adoc +309 -0
  51. data/docs/comparison/vs-peazip.adoc +77 -0
  52. data/docs/comparison/vs-rubyzip.adoc +342 -0
  53. data/docs/comparison/vs-winrar.adoc +100 -0
  54. data/docs/compatibility.adoc +579 -0
  55. data/docs/concepts/index.adoc +129 -0
  56. data/docs/developer/architecture.adoc +256 -0
  57. data/docs/developer/contributing.adoc +158 -0
  58. data/docs/developer/index.adoc +25 -0
  59. data/docs/developer/testing.adoc +212 -0
  60. data/docs/getting-started/basic-usage.adoc +263 -0
  61. data/docs/getting-started/index.adoc +42 -0
  62. data/docs/getting-started/installation.adoc +138 -0
  63. data/docs/getting-started/quick-start.adoc +183 -0
  64. data/docs/getting-started/your-first-archive.adoc +219 -0
  65. data/docs/guides/advanced-features/encryption.adoc +277 -0
  66. data/docs/guides/advanced-features/index.adoc +59 -0
  67. data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
  68. data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
  69. data/docs/guides/advanced-features/streaming.adoc +142 -0
  70. data/docs/guides/archive-formats/gzip-format.adoc +105 -0
  71. data/docs/guides/archive-formats/index.adoc +160 -0
  72. data/docs/guides/archive-formats/ole-format.adoc +151 -0
  73. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  74. data/docs/guides/archive-formats/rar5.adoc +521 -0
  75. data/docs/guides/archive-formats/rpm-format.adoc +108 -0
  76. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  77. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  78. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  79. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  80. data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
  81. data/docs/guides/compression-algorithms/deflate.adoc +313 -0
  82. data/docs/guides/compression-algorithms/index.adoc +190 -0
  83. data/docs/guides/compression-algorithms/lzma.adoc +394 -0
  84. data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
  85. data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
  86. data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
  87. data/docs/guides/creating-archives.adoc +348 -0
  88. data/docs/guides/extracting-archives.adoc +53 -0
  89. data/docs/guides/format-conversion.adoc +64 -0
  90. data/docs/guides/index.adoc +49 -0
  91. data/docs/guides/migration-rubyzip.adoc +217 -0
  92. data/docs/guides/parity-archives.adoc +605 -0
  93. data/docs/guides/performance-tuning.adoc +88 -0
  94. data/docs/index.adoc +228 -0
  95. data/docs/lychee.toml +67 -0
  96. data/docs/reference/api/overview.adoc +187 -0
  97. data/docs/reference/cli/compress-command.adoc +114 -0
  98. data/docs/reference/cli/overview.adoc +140 -0
  99. data/docs/reference/index.adoc +26 -0
  100. data/docs/resources/faq.adoc +185 -0
  101. data/docs/resources/quick-reference.adoc +222 -0
  102. data/docs/rust-backend.md +0 -0
  103. data/docs/troubleshooting/index.adoc +207 -0
  104. data/docs/xar_format.md +216 -0
  105. data/examples/api_comparison.rb +205 -0
  106. data/examples/deflate64_example.rb +96 -0
  107. data/examples/par2_demo.rb +121 -0
  108. data/examples/quick_start_native.rb +150 -0
  109. data/examples/quick_start_rubyzip.rb +115 -0
  110. data/examples/rubyzip_compatibility_demo.rb +194 -0
  111. data/exe/omnizip +27 -0
  112. data/lib/omnizip/algorithm.rb +176 -0
  113. data/lib/omnizip/algorithm_registry.rb +65 -0
  114. data/lib/omnizip/algorithms/.keep +0 -0
  115. data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
  116. data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
  117. data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
  118. data/lib/omnizip/algorithms/bzip2.rb +108 -0
  119. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  120. data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
  121. data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
  122. data/lib/omnizip/algorithms/deflate.rb +135 -0
  123. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  124. data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
  125. data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
  126. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
  127. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
  128. data/lib/omnizip/algorithms/deflate64.rb +118 -0
  129. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  130. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  131. data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
  132. data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
  133. data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
  134. data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
  135. data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
  136. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
  137. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
  138. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
  139. data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
  140. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
  141. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  142. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  143. data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
  144. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  145. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
  146. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
  147. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  148. data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
  149. data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
  150. data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
  151. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  152. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
  153. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
  154. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
  155. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
  156. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
  157. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
  158. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  159. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
  160. data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
  161. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
  162. data/lib/omnizip/algorithms/lzma.rb +266 -0
  163. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
  164. data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
  165. data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
  166. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
  167. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  168. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
  169. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  170. data/lib/omnizip/algorithms/lzma2.rb +133 -0
  171. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  172. data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
  173. data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
  174. data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
  175. data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
  176. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  177. data/lib/omnizip/algorithms/ppmd7.rb +146 -0
  178. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  179. data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
  180. data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
  181. data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
  182. data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
  183. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  184. data/lib/omnizip/algorithms/ppmd8.rb +122 -0
  185. data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
  186. data/lib/omnizip/algorithms/registration.rb +28 -0
  187. data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
  188. data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
  189. data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
  190. data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
  191. data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
  192. data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
  193. data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
  194. data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
  195. data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
  196. data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
  197. data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
  198. data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
  199. data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
  200. data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
  201. data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
  202. data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
  203. data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
  204. data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
  205. data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
  206. data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
  207. data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
  208. data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
  209. data/lib/omnizip/algorithms/zstandard.rb +210 -0
  210. data/lib/omnizip/algorithms.rb +35 -0
  211. data/lib/omnizip/archive/builder.rb +48 -0
  212. data/lib/omnizip/archive/reader_session.rb +67 -0
  213. data/lib/omnizip/archive.rb +86 -0
  214. data/lib/omnizip/archive_handler.rb +82 -0
  215. data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
  216. data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
  217. data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
  218. data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
  219. data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
  220. data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
  221. data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
  222. data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
  223. data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
  224. data/lib/omnizip/archive_handlers.rb +18 -0
  225. data/lib/omnizip/backends.rb +160 -0
  226. data/lib/omnizip/buffer/memory_archive.rb +246 -0
  227. data/lib/omnizip/buffer/memory_extractor.rb +234 -0
  228. data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
  229. data/lib/omnizip/buffer.rb +187 -0
  230. data/lib/omnizip/checksum_registry.rb +41 -0
  231. data/lib/omnizip/checksums/crc32.rb +101 -0
  232. data/lib/omnizip/checksums/crc64.rb +102 -0
  233. data/lib/omnizip/checksums/crc_base.rb +158 -0
  234. data/lib/omnizip/checksums/registration.rb +16 -0
  235. data/lib/omnizip/checksums/verifier.rb +130 -0
  236. data/lib/omnizip/checksums.rb +11 -0
  237. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  238. data/lib/omnizip/chunked/reader.rb +78 -0
  239. data/lib/omnizip/chunked/writer.rb +123 -0
  240. data/lib/omnizip/chunked.rb +123 -0
  241. data/lib/omnizip/cli/output_formatter.rb +112 -0
  242. data/lib/omnizip/cli.rb +604 -0
  243. data/lib/omnizip/commands/.keep +0 -0
  244. data/lib/omnizip/commands/archive_create_command.rb +245 -0
  245. data/lib/omnizip/commands/archive_extract_command.rb +231 -0
  246. data/lib/omnizip/commands/archive_list_command.rb +204 -0
  247. data/lib/omnizip/commands/archive_repair_command.rb +129 -0
  248. data/lib/omnizip/commands/archive_verify_command.rb +115 -0
  249. data/lib/omnizip/commands/compress_command.rb +115 -0
  250. data/lib/omnizip/commands/decompress_command.rb +149 -0
  251. data/lib/omnizip/commands/list_command.rb +51 -0
  252. data/lib/omnizip/commands/metadata_command.rb +215 -0
  253. data/lib/omnizip/commands/parity_create_command.rb +114 -0
  254. data/lib/omnizip/commands/parity_repair_command.rb +120 -0
  255. data/lib/omnizip/commands/parity_verify_command.rb +122 -0
  256. data/lib/omnizip/commands/profile_list_command.rb +54 -0
  257. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  258. data/lib/omnizip/commands.rb +21 -0
  259. data/lib/omnizip/convenience.rb +389 -0
  260. data/lib/omnizip/converter/conversion_registry.rb +50 -0
  261. data/lib/omnizip/converter/conversion_strategy.rb +108 -0
  262. data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
  263. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
  264. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
  265. data/lib/omnizip/converter.rb +124 -0
  266. data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
  267. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  268. data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
  269. data/lib/omnizip/crypto/aes256.rb +102 -0
  270. data/lib/omnizip/crypto.rb +11 -0
  271. data/lib/omnizip/entry.rb +44 -0
  272. data/lib/omnizip/error.rb +110 -0
  273. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
  274. data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
  275. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  276. data/lib/omnizip/eta/sample_history.rb +143 -0
  277. data/lib/omnizip/eta/time_estimator.rb +106 -0
  278. data/lib/omnizip/eta.rb +68 -0
  279. data/lib/omnizip/extraction/filter_chain.rb +179 -0
  280. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  281. data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
  282. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  283. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  284. data/lib/omnizip/extraction/selective_extractor.rb +247 -0
  285. data/lib/omnizip/extraction.rb +115 -0
  286. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  287. data/lib/omnizip/file_type.rb +117 -0
  288. data/lib/omnizip/filter.rb +141 -0
  289. data/lib/omnizip/filter_pipeline.rb +108 -0
  290. data/lib/omnizip/filter_registry.rb +113 -0
  291. data/lib/omnizip/filters/bcj.rb +277 -0
  292. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  293. data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
  294. data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
  295. data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
  296. data/lib/omnizip/filters/bcj2.rb +93 -0
  297. data/lib/omnizip/filters/bcj_arm.rb +174 -0
  298. data/lib/omnizip/filters/bcj_arm64.rb +242 -0
  299. data/lib/omnizip/filters/bcj_ia64.rb +194 -0
  300. data/lib/omnizip/filters/bcj_ppc.rb +188 -0
  301. data/lib/omnizip/filters/bcj_sparc.rb +174 -0
  302. data/lib/omnizip/filters/bcj_x86.rb +191 -0
  303. data/lib/omnizip/filters/delta.rb +195 -0
  304. data/lib/omnizip/filters/xz_delta.rb +258 -0
  305. data/lib/omnizip/filters.rb +20 -0
  306. data/lib/omnizip/format_detector.rb +166 -0
  307. data/lib/omnizip/formats/.keep +0 -0
  308. data/lib/omnizip/formats/bzip2_file.rb +159 -0
  309. data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
  310. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  311. data/lib/omnizip/formats/cpio/entry.rb +389 -0
  312. data/lib/omnizip/formats/cpio/reader.rb +194 -0
  313. data/lib/omnizip/formats/cpio/writer.rb +232 -0
  314. data/lib/omnizip/formats/cpio.rb +132 -0
  315. data/lib/omnizip/formats/format_spec_loader.rb +228 -0
  316. data/lib/omnizip/formats/gzip.rb +236 -0
  317. data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
  318. data/lib/omnizip/formats/iso/directory_record.rb +162 -0
  319. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  320. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  321. data/lib/omnizip/formats/iso/reader.rb +194 -0
  322. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  323. data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
  324. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  325. data/lib/omnizip/formats/iso/writer.rb +543 -0
  326. data/lib/omnizip/formats/iso.rb +133 -0
  327. data/lib/omnizip/formats/lzip.rb +161 -0
  328. data/lib/omnizip/formats/lzma_alone.rb +149 -0
  329. data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
  330. data/lib/omnizip/formats/msi/constants.rb +157 -0
  331. data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
  332. data/lib/omnizip/formats/msi/entry.rb +134 -0
  333. data/lib/omnizip/formats/msi/reader.rb +301 -0
  334. data/lib/omnizip/formats/msi/string_pool.rb +246 -0
  335. data/lib/omnizip/formats/msi/table_parser.rb +244 -0
  336. data/lib/omnizip/formats/msi.rb +73 -0
  337. data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
  338. data/lib/omnizip/formats/ole/constants.rb +61 -0
  339. data/lib/omnizip/formats/ole/dirent.rb +439 -0
  340. data/lib/omnizip/formats/ole/header.rb +199 -0
  341. data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
  342. data/lib/omnizip/formats/ole/storage.rb +482 -0
  343. data/lib/omnizip/formats/ole/types/variant.rb +338 -0
  344. data/lib/omnizip/formats/ole.rb +143 -0
  345. data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
  346. data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
  347. data/lib/omnizip/formats/rar/block_parser.rb +282 -0
  348. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  349. data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
  350. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
  351. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
  352. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  353. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  354. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  355. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  356. data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
  357. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
  358. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
  359. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
  360. data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
  361. data/lib/omnizip/formats/rar/compression.rb +17 -0
  362. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  363. data/lib/omnizip/formats/rar/constants.rb +88 -0
  364. data/lib/omnizip/formats/rar/decompressor.rb +316 -0
  365. data/lib/omnizip/formats/rar/external_writer.rb +311 -0
  366. data/lib/omnizip/formats/rar/header.rb +209 -0
  367. data/lib/omnizip/formats/rar/license_validator.rb +111 -0
  368. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  369. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  370. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  371. data/lib/omnizip/formats/rar/models.rb +14 -0
  372. data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
  373. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
  374. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
  375. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  376. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  377. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
  378. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  379. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
  380. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  381. data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
  382. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  383. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  384. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  385. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  386. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  387. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
  388. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  389. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
  390. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
  391. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
  392. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  393. data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
  394. data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
  395. data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
  396. data/lib/omnizip/formats/rar/reader.rb +377 -0
  397. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  398. data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
  399. data/lib/omnizip/formats/rar/writer.rb +437 -0
  400. data/lib/omnizip/formats/rar.rb +193 -0
  401. data/lib/omnizip/formats/rar3/compressor.rb +71 -0
  402. data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
  403. data/lib/omnizip/formats/rar3/reader.rb +107 -0
  404. data/lib/omnizip/formats/rar3/writer.rb +220 -0
  405. data/lib/omnizip/formats/rar3.rb +15 -0
  406. data/lib/omnizip/formats/rar5/compressor.rb +71 -0
  407. data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
  408. data/lib/omnizip/formats/rar5/reader.rb +130 -0
  409. data/lib/omnizip/formats/rar5/writer.rb +65 -0
  410. data/lib/omnizip/formats/rar5.rb +15 -0
  411. data/lib/omnizip/formats/rpm/constants.rb +58 -0
  412. data/lib/omnizip/formats/rpm/entry.rb +106 -0
  413. data/lib/omnizip/formats/rpm/header.rb +106 -0
  414. data/lib/omnizip/formats/rpm/lead.rb +132 -0
  415. data/lib/omnizip/formats/rpm/tag.rb +228 -0
  416. data/lib/omnizip/formats/rpm/writer.rb +652 -0
  417. data/lib/omnizip/formats/rpm.rb +458 -0
  418. data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
  419. data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
  420. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  421. data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
  422. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
  423. data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
  424. data/lib/omnizip/formats/seven_zip/header.rb +102 -0
  425. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
  426. data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
  427. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  428. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
  429. data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
  430. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  431. data/lib/omnizip/formats/seven_zip/models.rb +20 -0
  432. data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
  433. data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
  434. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
  435. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
  436. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  437. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
  438. data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
  439. data/lib/omnizip/formats/seven_zip.rb +179 -0
  440. data/lib/omnizip/formats/tar/constants.rb +73 -0
  441. data/lib/omnizip/formats/tar/entry.rb +98 -0
  442. data/lib/omnizip/formats/tar/header.rb +206 -0
  443. data/lib/omnizip/formats/tar/reader.rb +119 -0
  444. data/lib/omnizip/formats/tar/writer.rb +212 -0
  445. data/lib/omnizip/formats/tar.rb +74 -0
  446. data/lib/omnizip/formats/xar/constants.rb +119 -0
  447. data/lib/omnizip/formats/xar/entry.rb +268 -0
  448. data/lib/omnizip/formats/xar/header.rb +223 -0
  449. data/lib/omnizip/formats/xar/reader.rb +400 -0
  450. data/lib/omnizip/formats/xar/toc.rb +570 -0
  451. data/lib/omnizip/formats/xar/writer.rb +461 -0
  452. data/lib/omnizip/formats/xar.rb +145 -0
  453. data/lib/omnizip/formats/xz/reader.rb +121 -0
  454. data/lib/omnizip/formats/xz/writer.rb +416 -0
  455. data/lib/omnizip/formats/xz.rb +210 -0
  456. data/lib/omnizip/formats/xz_const.rb +49 -0
  457. data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
  458. data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
  459. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  460. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
  461. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  462. data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
  463. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
  464. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
  465. data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
  466. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
  467. data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
  468. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
  469. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  470. data/lib/omnizip/formats/xz_impl.rb +52 -0
  471. data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
  472. data/lib/omnizip/formats/zip/constants.rb +69 -0
  473. data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
  474. data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
  475. data/lib/omnizip/formats/zip/reader.rb +376 -0
  476. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  477. data/lib/omnizip/formats/zip/writer.rb +489 -0
  478. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
  479. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
  480. data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
  481. data/lib/omnizip/formats/zip.rb +50 -0
  482. data/lib/omnizip/formats.rb +29 -0
  483. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  484. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  485. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  486. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  487. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  488. data/lib/omnizip/implementations/base.rb +19 -0
  489. data/lib/omnizip/implementations/rust/archive.rb +93 -0
  490. data/lib/omnizip/implementations/rust/library.rb +221 -0
  491. data/lib/omnizip/implementations/rust.rb +26 -0
  492. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
  493. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
  494. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
  495. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
  496. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
  497. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
  498. data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
  499. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
  500. data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
  501. data/lib/omnizip/implementations/seven_zip.rb +11 -0
  502. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
  503. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
  504. data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
  505. data/lib/omnizip/implementations/xz_utils.rb +10 -0
  506. data/lib/omnizip/implementations.rb +25 -0
  507. data/lib/omnizip/io/buffered_input.rb +147 -0
  508. data/lib/omnizip/io/buffered_output.rb +106 -0
  509. data/lib/omnizip/io/source.rb +143 -0
  510. data/lib/omnizip/io/stream_manager.rb +117 -0
  511. data/lib/omnizip/io.rb +15 -0
  512. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  513. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  514. data/lib/omnizip/link_handler.rb +129 -0
  515. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  516. data/lib/omnizip/metadata/entry_metadata.rb +153 -0
  517. data/lib/omnizip/metadata/metadata_editor.rb +169 -0
  518. data/lib/omnizip/metadata/metadata_registry.rb +71 -0
  519. data/lib/omnizip/metadata/metadata_validator.rb +101 -0
  520. data/lib/omnizip/metadata.rb +58 -0
  521. data/lib/omnizip/models/.keep +0 -0
  522. data/lib/omnizip/models/algorithm_metadata.rb +41 -0
  523. data/lib/omnizip/models/attribute_apply.rb +40 -0
  524. data/lib/omnizip/models/compression_options.rb +53 -0
  525. data/lib/omnizip/models/conversion_options.rb +79 -0
  526. data/lib/omnizip/models/conversion_result.rb +141 -0
  527. data/lib/omnizip/models/eta_result.rb +45 -0
  528. data/lib/omnizip/models/extraction_rule.rb +115 -0
  529. data/lib/omnizip/models/filter_chain.rb +142 -0
  530. data/lib/omnizip/models/filter_config.rb +148 -0
  531. data/lib/omnizip/models/match_result.rb +141 -0
  532. data/lib/omnizip/models/optimization_suggestion.rb +95 -0
  533. data/lib/omnizip/models/parallel_options.rb +116 -0
  534. data/lib/omnizip/models/performance_result.rb +85 -0
  535. data/lib/omnizip/models/profile_report.rb +116 -0
  536. data/lib/omnizip/models/progress_options.rb +39 -0
  537. data/lib/omnizip/models/split_options.rb +116 -0
  538. data/lib/omnizip/optimization_registry.rb +45 -0
  539. data/lib/omnizip/parallel/engine.rb +52 -0
  540. data/lib/omnizip/parallel/job_queue.rb +209 -0
  541. data/lib/omnizip/parallel/job_scheduler.rb +225 -0
  542. data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
  543. data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
  544. data/lib/omnizip/parallel/thread_pool.rb +60 -0
  545. data/lib/omnizip/parallel/worker_pool.rb +227 -0
  546. data/lib/omnizip/parallel.rb +156 -0
  547. data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
  548. data/lib/omnizip/parity/galois16.rb +145 -0
  549. data/lib/omnizip/parity/models/creator_packet.rb +71 -0
  550. data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
  551. data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
  552. data/lib/omnizip/parity/models/main_packet.rb +126 -0
  553. data/lib/omnizip/parity/models/packet.rb +156 -0
  554. data/lib/omnizip/parity/models/packet_registry.rb +102 -0
  555. data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
  556. data/lib/omnizip/parity/models.rb +27 -0
  557. data/lib/omnizip/parity/par2_creator.rb +496 -0
  558. data/lib/omnizip/parity/par2_repairer.rb +409 -0
  559. data/lib/omnizip/parity/par2_verifier.rb +373 -0
  560. data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
  561. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  562. data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
  563. data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
  564. data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
  565. data/lib/omnizip/parity.rb +207 -0
  566. data/lib/omnizip/password/encryption_registry.rb +26 -0
  567. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  568. data/lib/omnizip/password/password_validator.rb +129 -0
  569. data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
  570. data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
  571. data/lib/omnizip/password.rb +88 -0
  572. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  573. data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
  574. data/lib/omnizip/pipe.rb +120 -0
  575. data/lib/omnizip/platform/ntfs_streams.rb +200 -0
  576. data/lib/omnizip/platform.rb +189 -0
  577. data/lib/omnizip/profile/archive_profile.rb +36 -0
  578. data/lib/omnizip/profile/balanced_profile.rb +31 -0
  579. data/lib/omnizip/profile/binary_profile.rb +33 -0
  580. data/lib/omnizip/profile/compression_profile.rb +157 -0
  581. data/lib/omnizip/profile/custom_profile.rb +155 -0
  582. data/lib/omnizip/profile/fast_profile.rb +31 -0
  583. data/lib/omnizip/profile/maximum_profile.rb +31 -0
  584. data/lib/omnizip/profile/profile_detector.rb +108 -0
  585. data/lib/omnizip/profile/profile_registry.rb +160 -0
  586. data/lib/omnizip/profile/text_profile.rb +33 -0
  587. data/lib/omnizip/profile.rb +261 -0
  588. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  589. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  590. data/lib/omnizip/profiler/report_generator.rb +158 -0
  591. data/lib/omnizip/profiler.rb +192 -0
  592. data/lib/omnizip/progress/callback_reporter.rb +34 -0
  593. data/lib/omnizip/progress/console_reporter.rb +59 -0
  594. data/lib/omnizip/progress/log_reporter.rb +89 -0
  595. data/lib/omnizip/progress/operation_progress.rb +118 -0
  596. data/lib/omnizip/progress/progress_bar.rb +156 -0
  597. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  598. data/lib/omnizip/progress/progress_tracker.rb +215 -0
  599. data/lib/omnizip/progress/silent_reporter.rb +22 -0
  600. data/lib/omnizip/progress.rb +131 -0
  601. data/lib/omnizip/registry.rb +111 -0
  602. data/lib/omnizip/rubyzip_compat.rb +61 -0
  603. data/lib/omnizip/temp/safe_extract.rb +124 -0
  604. data/lib/omnizip/temp/temp_file.rb +123 -0
  605. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  606. data/lib/omnizip/temp.rb +184 -0
  607. data/lib/omnizip/version.rb +5 -0
  608. data/lib/omnizip/zip/entry.rb +160 -0
  609. data/lib/omnizip/zip/file.rb +485 -0
  610. data/lib/omnizip/zip/input_stream.rb +270 -0
  611. data/lib/omnizip/zip/output_stream.rb +320 -0
  612. data/lib/omnizip/zip.rb +23 -0
  613. data/lib/omnizip.rb +157 -0
  614. data/lib/tasks/msi_test_files.rake +66 -0
  615. data/lib/tasks/platform_gems.rake +147 -0
  616. data/lib/tasks/rust_backend.rake +48 -0
  617. data/readme-docs/advanced-features.adoc +514 -0
  618. data/readme-docs/api-usage.adoc +445 -0
  619. data/readme-docs/architecture.adoc +450 -0
  620. data/readme-docs/archive-formats.adoc +479 -0
  621. data/readme-docs/cli-usage.adoc +222 -0
  622. data/readme-docs/compression-algorithms.adoc +446 -0
  623. data/readme-docs/compression-profiles.adoc +247 -0
  624. data/readme-docs/encryption-checksums.adoc +328 -0
  625. data/readme-docs/format-converter.adoc +316 -0
  626. data/readme-docs/installation.adoc +228 -0
  627. data/readme-docs/par2-archives.adoc +608 -0
  628. data/readme-docs/performance-profiler.adoc +389 -0
  629. data/readme-docs/preprocessing-filters.adoc +280 -0
  630. data/vendor/libomnizip_ffi.so +0 -0
  631. data/xz-file-format-1.2.1.txt +1174 -0
  632. metadata +768 -0
@@ -0,0 +1,687 @@
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 BZip2
26
+ # Standard bzip2 wire format (port of the omnizip-rs
27
+ # omnizip-bzip2/src/bz2 module).
28
+ #
29
+ # Output is decodable by `bzip2 -d`; input from the bzip2 CLI
30
+ # decodes here. Pipeline: RLE1 -> BWT -> seeded MTF -> RLE2
31
+ # (RUNA/RUNB) -> canonical Huffman, MSB-first bit packing, with
32
+ # the bzip2 CRC-32 variant on every block and a combined
33
+ # stream CRC.
34
+ module Bz2
35
+ BLOCK_MAGIC = 0x3141_5926_5359
36
+ EOS_MAGIC = 0x1772_4538_5090
37
+ ITERATIONS = 4
38
+ GROUP_SIZE = 50
39
+ MAX_GROUPS = 6
40
+ MAX_CODE_LENGTH = 23
41
+ RUNA = 0
42
+ RUNB = 1
43
+
44
+ module_function
45
+
46
+ # bzip2 CRC-32: non-reflected polynomial 0x04C11DB7, init
47
+ # 0xFFFFFFFF, final complement — NOT the zlib variant.
48
+ def crc32(data)
49
+ table = CRC_TABLE
50
+ crc = 0xFFFF_FFFF
51
+ data.each_byte do |b|
52
+ crc = ((crc << 8) & 0xFFFF_FFFF) ^
53
+ table[((crc >> 24) ^ b) & 0xFF]
54
+ end
55
+ crc ^ 0xFFFF_FFFF
56
+ end
57
+
58
+ CRC_TABLE = Array.new(256) do |i|
59
+ crc = i << 24
60
+ 8.times do
61
+ crc = if crc.nobits?(0x8000_0000)
62
+ (crc << 1) & 0xFFFF_FFFF
63
+ else
64
+ ((crc << 1) ^ 0x04C1_1DB7) & 0xFFFF_FFFF
65
+ end
66
+ end
67
+ crc
68
+ end
69
+
70
+ # Compress `input` into a standard .bz2 stream. `level`
71
+ # (1-9) selects the block size in 100 KB steps.
72
+ def compress(input, level = 9)
73
+ raise Omnizip::CompressionError, "bzip2 level must be 1..9" unless (1..9).cover?(level)
74
+
75
+ block_size = level * 100_000
76
+ writer = BitWriter.new
77
+ writer.write_bits("B".ord, 8)
78
+ writer.write_bits("Z".ord, 8)
79
+ writer.write_bits("h".ord, 8)
80
+ writer.write_bits("0".ord + level, 8)
81
+
82
+ if input.empty?
83
+ writer.write48(EOS_MAGIC)
84
+ writer.write_bits(0, 32)
85
+ return writer.finish
86
+ end
87
+
88
+ combined = 0
89
+ offset = 0
90
+ while offset < input.bytesize
91
+ chunk = input.byteslice(offset, block_size)
92
+ offset += block_size
93
+ block_crc = crc32(chunk)
94
+ combined = rotate_left32(combined, 1) ^ block_crc
95
+ encode_block(chunk, block_crc, writer)
96
+ end
97
+ writer.write48(EOS_MAGIC)
98
+ writer.write_bits(combined, 32)
99
+ writer.finish
100
+ end
101
+
102
+ # rubocop:disable Metrics/MethodLength
103
+ # rubocop:disable-next Metrics/AbcSize
104
+ # rubocop:disable Metrics/MethodLength
105
+ # rubocop:disable-next Metrics/AbcSize
106
+ def encode_block(block, block_crc, writer)
107
+ rle1 = Rle.new.encode(block)
108
+ bwt_data, primary_index = Bwt.new.encode(rle1)
109
+ sequence = build_sequence(bwt_data)
110
+ n_in_use = sequence.length
111
+ mtf = mtf_encode_seeded(bwt_data, sequence)
112
+ symbols = mtf_to_symbols(mtf, n_in_use)
113
+ alphabet_size = n_in_use + 2
114
+
115
+ writer.write48(BLOCK_MAGIC)
116
+ writer.write_bits(block_crc, 32)
117
+ writer.write_bit(false) # never randomised
118
+ writer.write_bits(primary_index & 0xFF_FFFF, 24)
119
+
120
+ groups_used, group_maps = build_symbol_map(bwt_data)
121
+ writer.write_bits(groups_used, 16)
122
+ group_maps.each { |g| writer.write_bits(g, 16) }
123
+
124
+ # Upstream bzip2 table selection: the group count grows
125
+ # with symbol count (2 below 200, 3 below 600, then toward
126
+ # 6), then ITERATIONS rounds of chunk-to-table assignment by
127
+ # cheapest total code length and table recomputation.
128
+ chunks = symbols.each_slice(GROUP_SIZE).to_a
129
+ chunk_freqs = chunks.map do |chunk|
130
+ freq = Array.new(alphabet_size, 0)
131
+ chunk.each { |s| freq[s] += 1 }
132
+ freq
133
+ end
134
+ n_groups = if symbols.length < 200
135
+ 2
136
+ else
137
+ symbols.length < 600 ? 3 : 6
138
+ end
139
+ # The format requires 2..6 groups even for a single chunk.
140
+
141
+ # Seed the tables with upstream bzip2's position ramp
142
+ # (len[t][v] = v / (t+1) + 1): starting every table from
143
+ # the global frequencies collapses the first assignment
144
+ # round onto table 0 and the iteration never differentiates.
145
+ lengths_per_table = Array.new(n_groups) do |t|
146
+ Array.new(alphabet_size) { |v| [(v / (t + 1)) + 1, 20].min }
147
+ end
148
+ selectors = Array.new(chunks.length, 0)
149
+
150
+ ITERATIONS.times do
151
+ selectors = chunks.each_index.map do |ci|
152
+ cf = chunk_freqs[ci]
153
+ (0...n_groups).min_by do |ti|
154
+ lengths = lengths_per_table[ti]
155
+ cost = 0
156
+ cf.each_with_index do |f, sym|
157
+ cost += f * lengths[sym] if f.positive?
158
+ end
159
+ cost
160
+ end
161
+ end
162
+
163
+ table_freqs = Array.new(n_groups) { Array.new(alphabet_size, 0) }
164
+ selectors.each_with_index do |ti, ci|
165
+ cf = chunk_freqs[ci]
166
+ alphabet_size.times { |a| table_freqs[ti][a] += cf[a] }
167
+ end
168
+ lengths_per_table = Array.new(n_groups) { |i| code_lengths(table_freqs[i]) }
169
+ end
170
+
171
+ # MTF the selectors over the final table order.
172
+ order = (0...n_groups).to_a
173
+ mtf_selectors = selectors.map do |t|
174
+ idx = order.index(t)
175
+ order.delete_at(idx)
176
+ order.unshift(t)
177
+ idx
178
+ end
179
+
180
+ n_selectors = [chunks.length, 1].max
181
+ writer.write_bits(n_groups, 3)
182
+ writer.write_bits(n_selectors, 15)
183
+ # MTF value N -> N '1's then '0'.
184
+ mtf_selectors.each do |v|
185
+ v.times { writer.write_bit(true) }
186
+ writer.write_bit(false)
187
+ end
188
+
189
+ tables = lengths_per_table.map { |l| canonical_codes(l) }
190
+ lengths_per_table.each { |l| write_huffman_table(writer, l) }
191
+
192
+ chunks.each_with_index do |chunk, i|
193
+ table = tables[selectors[i]]
194
+ chunk.each do |sym|
195
+ code, len = table[sym]
196
+ writer.write_bits(code, len)
197
+ end
198
+ end
199
+ end
200
+ # rubocop:enable Metrics/AbcSize
201
+ # rubocop:enable Metrics/MethodLength
202
+
203
+ # The active bytes in ascending order (the seeded-MTF table).
204
+ def build_sequence(data)
205
+ seen = Array.new(256, false)
206
+ data.each_byte { |b| seen[b] = true }
207
+ (0...256).select { |b| seen[b] }
208
+ end
209
+
210
+ # rubocop:disable Metrics/MethodLength
211
+ def mtf_encode_seeded(data, sequence)
212
+ table = sequence.dup
213
+ out = []
214
+ data.each_byte do |byte|
215
+ pos = table.index(byte)
216
+ out << pos
217
+ table.delete_at(pos)
218
+ table.unshift(byte)
219
+ end
220
+ out
221
+ end
222
+
223
+ # RUNA/RUNB (bijective base-2) zero-run encoding plus the
224
+ # value/EOB symbols; EOB = n_in_use + 1.
225
+ # rubocop:disable-next Metrics/AbcSize
226
+ def mtf_to_symbols(mtf_values, n_in_use)
227
+ eob = n_in_use + 1
228
+ out = []
229
+ i = 0
230
+ while i < mtf_values.length
231
+ v = mtf_values[i]
232
+ if v.zero?
233
+ run = 0
234
+ while i < mtf_values.length && mtf_values[i].zero?
235
+ run += 1
236
+ i += 1
237
+ end
238
+ n = run
239
+ while n.positive?
240
+ n -= 1
241
+ out << (n.nobits?(1) ? RUNA : RUNB)
242
+ n >>= 1
243
+ end
244
+ else
245
+ out << (v + 1)
246
+ i += 1
247
+ end
248
+ end
249
+ out << eob
250
+ out
251
+ end
252
+ # rubocop:enable Metrics/MethodLength
253
+
254
+ # bzip2 symbol usage map: 16-bit group word, then one 16-bit
255
+ # byte map per used group (bit 15 - index, MSB-first order).
256
+ # rubocop:disable-next Metrics/AbcSize
257
+ def build_symbol_map(data)
258
+ used = Array.new(256, false)
259
+ data.each_byte { |b| used[b] = true }
260
+
261
+ groups_used = 0
262
+ detail = []
263
+ 16.times do |g|
264
+ group_bits = 0
265
+ any = false
266
+ 16.times do |j|
267
+ next unless used[(g * 16) + j]
268
+
269
+ group_bits |= 1 << (15 - j)
270
+ any = true
271
+ end
272
+ next unless any
273
+
274
+ groups_used |= 1 << (15 - g)
275
+ detail << group_bits
276
+ end
277
+ [groups_used, detail]
278
+ end
279
+
280
+ # Canonical Huffman code lengths (every symbol gets a code;
281
+ # zero frequencies become 1) with rescaling to keep lengths
282
+ # within bzip2's 23-bit limit.
283
+ # rubocop:disable Metrics/MethodLength
284
+ # rubocop:disable-next Metrics/AbcSize
285
+ def code_lengths(freqs)
286
+ n = freqs.length
287
+ active = freqs.each_index.map { |i| [(freqs[i].zero? ? 1 : freqs[i]), i] }
288
+ return Array.new(n, 0) if active.empty?
289
+
290
+ loop do
291
+ lengths = huffman_lengths(active, n)
292
+ max_len = lengths.max || 0
293
+ return lengths if max_len <= MAX_CODE_LENGTH
294
+
295
+ scaled = false
296
+ active.map! do |(w, i)|
297
+ if w > 1
298
+ scaled = true
299
+ [(w + 1) / 2, i]
300
+ else
301
+ [w, i]
302
+ end
303
+ end
304
+ # Can't reduce further: clamp.
305
+ return lengths.map { |l| [l, MAX_CODE_LENGTH].min } unless scaled
306
+ end
307
+ end
308
+
309
+ # Standard Huffman via smallest-pair merging with parent
310
+ # pointers; depth = code length per active symbol.
311
+ # rubocop:disable-next Metrics/AbcSize
312
+ def huffman_lengths(active, alphabet_size)
313
+ nodes = active.map { |(w, _i)| { freq: w, parent: -1 } }
314
+ ids = active.map { |_w, i| i }
315
+ next_id = alphabet_size
316
+
317
+ loop do
318
+ roots = []
319
+ nodes.each_index { |k| roots << k if nodes[k][:parent] == -1 }
320
+ break if roots.length <= 1
321
+
322
+ a = -1
323
+ b = -1
324
+ roots.each do |k|
325
+ if a == -1 || nodes[k][:freq] < nodes[a][:freq] ||
326
+ (nodes[k][:freq] == nodes[a][:freq] && ids[k] < ids[a])
327
+ b = a
328
+ a = k
329
+ elsif b == -1 || nodes[k][:freq] < nodes[b][:freq] ||
330
+ (nodes[k][:freq] == nodes[b][:freq] && ids[k] < ids[b])
331
+ b = k
332
+ end
333
+ end
334
+
335
+ nodes[a][:parent] = nodes.length
336
+ nodes[b][:parent] = nodes.length
337
+ nodes << { freq: nodes[a][:freq] + nodes[b][:freq], parent: -1 }
338
+ ids << next_id
339
+ next_id += 1
340
+ end
341
+
342
+ out = Array.new(alphabet_size, 0)
343
+ active.each_index do |k|
344
+ sym = ids[k]
345
+ len = 0
346
+ cur = k
347
+ while nodes[cur][:parent] != -1
348
+ cur = nodes[cur][:parent]
349
+ len += 1
350
+ end
351
+ out[sym] = [len, 1].max
352
+ end
353
+ out
354
+ end
355
+
356
+ # Canonical codes assigned in (length, symbol) order.
357
+ # rubocop:disable-next Metrics/AbcSize
358
+ def canonical_codes(lengths)
359
+ max_len = lengths.max || 0
360
+ codes = Array.new(lengths.length) { [0, 0] }
361
+ return codes if max_len.zero?
362
+
363
+ bl_count = Array.new(max_len + 1, 0)
364
+ lengths.each { |l| bl_count[l] += 1 if l.positive? }
365
+
366
+ next_code = Array.new(max_len + 1, 0)
367
+ code = 0
368
+ (1..max_len).each do |bits|
369
+ code = (code + bl_count[bits - 1]) << 1
370
+ next_code[bits] = code
371
+ end
372
+ lengths.each_with_index do |len, sym|
373
+ next unless len.positive?
374
+
375
+ codes[sym] = [next_code[len], len]
376
+ next_code[len] += 1
377
+ end
378
+ codes
379
+ end
380
+
381
+ # Delta-coded code-length table: 5-bit start length, then
382
+ # '10' (+1) / '11' (-1) adjustments and a '0' terminator per
383
+ # symbol.
384
+ def write_huffman_table(writer, lengths)
385
+ writer.write_bits(lengths[0], 5)
386
+ current = lengths[0]
387
+ lengths.each do |target|
388
+ diff = target - current
389
+ while diff != 0
390
+ writer.write_bit(true)
391
+ if diff.positive?
392
+ writer.write_bit(false)
393
+ diff -= 1
394
+ current += 1
395
+ else
396
+ writer.write_bit(true)
397
+ diff += 1
398
+ current -= 1
399
+ end
400
+ end
401
+ writer.write_bit(false)
402
+ end
403
+ end
404
+ # rubocop:enable Metrics/MethodLength
405
+
406
+ def rotate_left32(v, n)
407
+ ((v << n) | (v >> (32 - n))) & 0xFFFF_FFFF
408
+ end
409
+
410
+ # rubocop:disable Metrics/MethodLength
411
+ # rubocop:disable-next Metrics/AbcSize
412
+ # Decompress a complete .bz2 stream (single member). Verifies
413
+ # every block CRC and the combined stream CRC.
414
+ def decompress(input)
415
+ if input.bytesize < 4 || input.byteslice(0, 3) != "BZh" ||
416
+ !input.getbyte(3).between?("0".ord, "9".ord)
417
+ raise Omnizip::DecompressionError, "not a bzip2 stream (bad header)"
418
+ end
419
+
420
+ r = BitReader.new(input, 4)
421
+ out = String.new(encoding: Encoding::BINARY)
422
+ combined = 0
423
+ # rubocop:disable-next Metrics/BlockLength
424
+ loop do
425
+ magic = r.read48
426
+ if magic == EOS_MAGIC
427
+ stored = r.read_bits(32)
428
+ if stored != combined
429
+ raise Omnizip::DecompressionError,
430
+ format("combined CRC mismatch: stored %08X, " \
431
+ "computed %08X", stored, combined)
432
+ end
433
+ return out
434
+ end
435
+ unless magic == BLOCK_MAGIC
436
+ raise Omnizip::DecompressionError,
437
+ format("bad block magic %012X", magic)
438
+ end
439
+
440
+ block_crc = r.read_bits(32)
441
+ if r.read_bit == 1
442
+ raise Omnizip::DecompressionError,
443
+ "randomised blocks are not supported"
444
+ end
445
+ orig_ptr = r.read_bits(24)
446
+
447
+ groups = r.read_bits(16)
448
+ if groups.zero?
449
+ raise Omnizip::DecompressionError, "empty symbol map"
450
+ end
451
+
452
+ sequence = []
453
+ 16.times do |g|
454
+ next unless groups.anybits?(1 << (15 - g))
455
+
456
+ map = r.read_bits(16)
457
+ 16.times do |b|
458
+ sequence << ((g * 16) + b) if map.anybits?(1 << (15 - b))
459
+ end
460
+ end
461
+ n_in_use = sequence.length
462
+
463
+ n_groups = r.read_bits(3)
464
+ unless (2..MAX_GROUPS).cover?(n_groups)
465
+ raise Omnizip::DecompressionError, "invalid nGroups #{n_groups}"
466
+ end
467
+
468
+ n_selectors = r.read_bits(15)
469
+ if n_selectors.zero?
470
+ raise Omnizip::DecompressionError, "zero selectors"
471
+ end
472
+
473
+ selector_mtf = []
474
+ n_selectors.times do
475
+ j = 0
476
+ while r.read_bit == 1
477
+ j += 1
478
+ if j > MAX_GROUPS
479
+ raise Omnizip::DecompressionError,
480
+ "selector unary run too long"
481
+ end
482
+ end
483
+ selector_mtf << j
484
+ end
485
+ order = (0...n_groups).to_a
486
+ selectors = selector_mtf.map do |j|
487
+ table = order.delete_at(j)
488
+ order.unshift(table)
489
+ table
490
+ end
491
+
492
+ alphabet = n_in_use + 2
493
+ tables = Array.new(n_groups) do
494
+ lengths = Array.new(alphabet, 0)
495
+ cur = r.read_bits(5)
496
+ alphabet.times do |slot|
497
+ loop do
498
+ break if r.read_bit.zero?
499
+
500
+ cur += r.read_bit == 1 ? -1 : 1
501
+ end
502
+ lengths[slot] = cur
503
+ end
504
+ build_table(lengths)
505
+ end
506
+
507
+ eob = n_in_use + 1
508
+ symbols = []
509
+ catch(:eob) do
510
+ selectors.each do |sel|
511
+ table = tables[sel]
512
+ GROUP_SIZE.times do
513
+ sym = decode_symbol(table, r)
514
+ throw :eob if sym == eob
515
+
516
+ symbols << sym
517
+ end
518
+ end
519
+ end
520
+
521
+ mtf = symbols_to_mtf(symbols, n_in_use)
522
+ bwt = mtf_decode_seeded(mtf, sequence)
523
+ block = Bwt.new.decode(bwt, orig_ptr)
524
+ data = Rle.new.decode(block)
525
+ computed = crc32(data)
526
+ if computed != block_crc
527
+ raise Omnizip::DecompressionError,
528
+ format("block CRC mismatch: stored %08X, " \
529
+ "computed %08X", block_crc, computed)
530
+ end
531
+ combined = rotate_left32(combined, 1) ^ block_crc
532
+ out << data
533
+ end
534
+ end
535
+ # rubocop:enable Metrics/MethodLength
536
+
537
+ # RUNA/RUNB symbol stream back to MTF values.
538
+ # rubocop:disable-next Metrics/AbcSize
539
+ def symbols_to_mtf(symbols, n_in_use)
540
+ eob = n_in_use + 1
541
+ mtf = []
542
+ i = 0
543
+ while i < symbols.length
544
+ sym = symbols[i]
545
+ if [RUNA, RUNB].include?(sym)
546
+ run = 0
547
+ bit = 1
548
+ while i < symbols.length && [RUNA, RUNB].include?(symbols[i])
549
+ run += symbols[i] == RUNB ? bit << 1 : bit
550
+ bit <<= 1
551
+ i += 1
552
+ end
553
+ [run, 1 << 24].min.times { mtf << 0 }
554
+ elsif sym == eob
555
+ break
556
+ else
557
+ mtf << (sym - 1)
558
+ i += 1
559
+ end
560
+ end
561
+ mtf
562
+ end
563
+
564
+ # Seed-aware MTF inverse over the active-byte sequence.
565
+ # Returns a binary String (the BWT stage consumes bytes).
566
+ def mtf_decode_seeded(data, sequence)
567
+ list = sequence.dup
568
+ out = Array.new(data.length)
569
+ data.each_with_index do |v, i|
570
+ if v >= list.length
571
+ out[i] = 0
572
+ else
573
+ b = list.delete_at(v)
574
+ list.unshift(b)
575
+ out[i] = b
576
+ end
577
+ end
578
+ out.pack("C*")
579
+ end
580
+
581
+ # Canonical code table: entries sorted for bit-by-bit match.
582
+ def build_table(lengths)
583
+ alphabet = lengths.length
584
+ order = (0...alphabet).sort_by { |i| [lengths[i], i] }
585
+ entries = []
586
+ code = 0
587
+ length = 0
588
+ order.each do |i|
589
+ while length < lengths[i]
590
+ code <<= 1
591
+ length += 1
592
+ end
593
+ next unless lengths[i].positive?
594
+
595
+ entries << [i, code, lengths[i]]
596
+ code += 1
597
+ end
598
+ entries
599
+ end
600
+
601
+ def decode_symbol(table, r)
602
+ code = 0
603
+ len = 0
604
+ loop do
605
+ code = (code << 1) | r.read_bit
606
+ len += 1
607
+ raise Omnizip::DecompressionError, "huffman code too long" if len > 24
608
+
609
+ table.each do |(sym, c, l)|
610
+ return sym if l == len && c == code
611
+ end
612
+ end
613
+ end
614
+
615
+ # MSB-first bit reader.
616
+ class BitReader
617
+ def initialize(data, pos = 0)
618
+ @data = data
619
+ @pos = pos
620
+ @bits = 0
621
+ @nbits = 0
622
+ end
623
+
624
+ def read_bit
625
+ if @nbits.zero?
626
+ raise Omnizip::DecompressionError, "unexpected end of bitstream" if @pos >= @data.bytesize
627
+
628
+ @bits = @data.getbyte(@pos)
629
+ @pos += 1
630
+ @nbits = 8
631
+ end
632
+ @nbits -= 1
633
+ @bits.nobits?(1 << @nbits) ? 0 : 1
634
+ end
635
+
636
+ def read_bits(n)
637
+ v = 0
638
+ n.times { v = (v << 1) | read_bit }
639
+ v
640
+ end
641
+
642
+ def read48
643
+ (read_bits(24) << 24) | read_bits(24)
644
+ end
645
+ end
646
+
647
+ # MSB-first bit packer.
648
+ class BitWriter
649
+ def initialize
650
+ @out = []
651
+ @current = 0
652
+ @nbits = 0
653
+ end
654
+
655
+ def write_bits(bits, n)
656
+ return if n.zero?
657
+
658
+ mask = n == 32 ? bits : bits & ((1 << n) - 1)
659
+ @current = ((@current << n) | mask) & 0xFFFF_FFFF_FFFF_FFFF
660
+ @nbits += n
661
+ while @nbits >= 8
662
+ @nbits -= 8
663
+ @out << ((@current >> @nbits) & 0xFF)
664
+ end
665
+ end
666
+
667
+ def write_bit(bit)
668
+ write_bits(bit ? 1 : 0, 1)
669
+ end
670
+
671
+ def write48(value)
672
+ write_bits(value >> 24, 24)
673
+ write_bits(value & 0xFF_FFFF, 24)
674
+ end
675
+
676
+ def finish
677
+ if @nbits.positive?
678
+ @out << ((@current << (8 - @nbits)) & 0xFF)
679
+ @nbits = 0
680
+ end
681
+ @out.pack("C*")
682
+ end
683
+ end
684
+ end
685
+ end
686
+ end
687
+ end