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.
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,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Parity
5
+ # Chunked block processor for incremental Reed-Solomon recovery
6
+ #
7
+ # Implements correct RS decoding: x = A^-1 * b
8
+ # where b[i] = recovery[i] - sum(present[k] * base[present[k]]^exponent[i])
9
+ #
10
+ # Processes large blocks incrementally in memory-efficient chunks.
11
+ class ChunkedBlockProcessor
12
+ # Default chunk size (1MB)
13
+ DEFAULT_CHUNK_SIZE = 1024 * 1024
14
+
15
+ # @return [ReedSolomonMatrix] RS matrix with precomputed coefficients
16
+ attr_reader :matrix
17
+
18
+ # @return [Hash<Integer, String>] Present input blocks (index => data)
19
+ attr_reader :present_blocks
20
+
21
+ # @return [Hash<Integer, String>] Recovery blocks (exponent => data)
22
+ attr_reader :recovery_blocks
23
+
24
+ # @return [Array<Integer>] Missing block indices to recover
25
+ attr_reader :missing_indices
26
+
27
+ # @return [Integer] Block size in bytes
28
+ attr_reader :block_size
29
+
30
+ # @return [Integer] Chunk size for processing
31
+ attr_reader :chunk_size
32
+
33
+ # Initialize processor
34
+ #
35
+ # @param matrix [ReedSolomonMatrix] Precomputed RS matrix (A^-1)
36
+ # @param present_blocks [Hash<Integer, String>] Present data blocks
37
+ # @param recovery_blocks [Hash<Integer, String>] Recovery blocks (by exponent)
38
+ # @param missing_indices [Array<Integer>] Indices to recover
39
+ # @param block_size [Integer] Block size in bytes
40
+ # @param chunk_size [Integer] Chunk size for processing
41
+ def initialize(matrix, present_blocks, recovery_blocks, missing_indices,
42
+ block_size, chunk_size: DEFAULT_CHUNK_SIZE)
43
+ @matrix = matrix
44
+ @present_blocks = present_blocks
45
+ @recovery_blocks = recovery_blocks
46
+ @missing_indices = missing_indices.sort
47
+ @block_size = block_size
48
+ # Ensure chunk_size is even (we process 16-bit words)
49
+ requested_chunk = [chunk_size, block_size].min
50
+ @chunk_size = requested_chunk - (requested_chunk % 2)
51
+ end
52
+
53
+ # Process all blocks incrementally
54
+ #
55
+ # Implements: x = A^-1 * b
56
+ # where b = recovery - present_contributions
57
+ #
58
+ # @return [Hash<Integer, String>] Recovered blocks
59
+ def process_all
60
+ # Initialize output blocks (all zeros)
61
+ recovered = {}
62
+ missing_indices.each do |idx|
63
+ recovered[idx] = "\x00".b * block_size
64
+ end
65
+
66
+ # Process block chunk by chunk
67
+ block_offset = 0
68
+ while block_offset < block_size
69
+ current_chunk_size = [chunk_size, block_size - block_offset].min
70
+ process_chunk_at_offset(recovered, block_offset, current_chunk_size)
71
+ block_offset += current_chunk_size
72
+ end
73
+
74
+ recovered
75
+ end
76
+
77
+ private
78
+
79
+ # Process one chunk at given offset
80
+ #
81
+ # For each chunk, we:
82
+ # 1. Compute b_vector chunks from recovery blocks
83
+ # 2. Subtract present block contributions to get final b
84
+ # 3. Apply A^-1 matrix to b to get recovered chunks
85
+ #
86
+ # @param recovered [Hash<Integer, String>] Recovered blocks being built
87
+ # @param offset [Integer] Current offset within blocks
88
+ # @param length [Integer] Chunk length
89
+ def process_chunk_at_offset(recovered, offset, length)
90
+ # Step 1: Initialize b vector from recovery blocks
91
+ # b_vector[i] starts as recovery[i] (for each recovery exponent used)
92
+ b_vector = compute_b_vector_chunks(offset, length)
93
+
94
+ # Step 2: Apply A^-1 to b vector to get recovered chunks
95
+ # For each missing block j: recovered[j] = sum(A^-1[j,i] * b[i])
96
+ apply_inverse_matrix(recovered, b_vector, offset, length)
97
+ end
98
+
99
+ # Compute b vector chunks
100
+ #
101
+ # b[i] = recovery[i] - sum(present[k] * base[present[k]]^exponent[i])
102
+ #
103
+ # @param offset [Integer] Offset within blocks
104
+ # @param length [Integer] Chunk length
105
+ # @return [Array<String>] B vector chunks (one per recovery block used)
106
+ def compute_b_vector_chunks(offset, length)
107
+ b_chunks = []
108
+
109
+ # For each recovery block being used (must match matrix computation!)
110
+ matrix.used_recovery_exponents.each_with_index do |exponent, _exp_idx|
111
+ # Start with recovery block chunk
112
+ recovery_data = recovery_blocks[exponent]
113
+ b_chunk = recovery_data[offset, length].dup
114
+
115
+ # Subtract contributions from present blocks
116
+ present_blocks.each do |present_idx, present_data|
117
+ coefficient = matrix.present_contribution_coefficient(present_idx,
118
+ exponent)
119
+ next if coefficient.zero?
120
+
121
+ present_chunk = present_data[offset, length]
122
+
123
+ # Subtract: b -= present * coefficient
124
+ # In GF(2^16), subtraction is XOR, so: b ^= present * coefficient
125
+ subtract_contribution(b_chunk, present_chunk, coefficient, length)
126
+ end
127
+
128
+ b_chunks << b_chunk
129
+ end
130
+
131
+ b_chunks
132
+ end
133
+
134
+ # Subtract present block contribution from b chunk
135
+ #
136
+ # b_chunk ^= present_chunk * coefficient (GF subtraction is XOR)
137
+ #
138
+ # @param b_chunk [String] B vector chunk (modified in place)
139
+ # @param present_chunk [String] Present block chunk
140
+ # @param coefficient [Integer] Galois field coefficient
141
+ # @param length [Integer] Chunk length
142
+ def subtract_contribution(b_chunk, present_chunk, coefficient, length)
143
+ num_words = length / 2
144
+
145
+ num_words.times do |i|
146
+ word_offset = i * 2
147
+
148
+ # Read present word
149
+ present_word = present_chunk.getbyte(word_offset) |
150
+ (present_chunk.getbyte(word_offset + 1) << 8)
151
+
152
+ # Read current b word
153
+ b_word = b_chunk.getbyte(word_offset) |
154
+ (b_chunk.getbyte(word_offset + 1) << 8)
155
+
156
+ # Compute: b ^= present * coefficient
157
+ contribution = Galois16.multiply(present_word, coefficient)
158
+ result = Galois16.add(b_word, contribution) # add is XOR in GF(2^16)
159
+
160
+ # Write back
161
+ b_chunk.setbyte(word_offset, result & 0xFF)
162
+ b_chunk.setbyte(word_offset + 1, (result >> 8) & 0xFF)
163
+ end
164
+ end
165
+
166
+ # Apply inverse matrix to b vector
167
+ #
168
+ # For each missing block j:
169
+ # recovered[j] += sum_i(A^-1[j,i] * b[i])
170
+ #
171
+ # @param recovered [Hash<Integer, String>] Recovered blocks being built
172
+ # @param b_vector [Array<String>] B vector chunks
173
+ # @param offset [Integer] Offset within blocks
174
+ # @param length [Integer] Chunk length
175
+ def apply_inverse_matrix(recovered, b_vector, offset, length)
176
+ # For each output (missing block)
177
+ missing_indices.each_with_index do |missing_idx, output_idx|
178
+ output_block = recovered[missing_idx]
179
+
180
+ # For each b vector element (recovery block)
181
+ b_vector.each_with_index do |b_chunk, recovery_idx|
182
+ # Get coefficient from A^-1
183
+ coefficient = matrix.coefficient(output_idx, recovery_idx)
184
+ next if coefficient.zero?
185
+
186
+ # CRITICAL: Accumulate chunk at the correct offset
187
+ matrix.process_chunk(coefficient, b_chunk, output_block, length,
188
+ output_offset: offset)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Parity
5
+ # Pure implementation of Galois Field GF(2^16) arithmetic
6
+ # Uses generator polynomial 0x1100B (69643) as per PAR2 specification
7
+ #
8
+ # This is pure algorithm code with no I/O dependencies.
9
+ # All operations are exact (no floating point) and work in GF(2^16).
10
+ class Galois16
11
+ BITS = 16
12
+ GENERATOR = 0x1100B # 69643 in decimal
13
+ FIELD_SIZE = 1 << BITS # 65536
14
+ LIMIT = FIELD_SIZE - 1 # 65535
15
+
16
+ # Lookup tables for efficient operations
17
+ @log_table = nil
18
+ @antilog_table = nil
19
+
20
+ class << self
21
+ # Build log and antilog tables
22
+ # This is called once when the class is loaded
23
+ def build_tables
24
+ return if @log_table && @antilog_table
25
+
26
+ @log_table = Array.new(FIELD_SIZE)
27
+ @antilog_table = Array.new(FIELD_SIZE)
28
+
29
+ b = 1
30
+ LIMIT.times do |l|
31
+ @log_table[b] = l
32
+ @antilog_table[l] = b
33
+
34
+ b <<= 1
35
+ b ^= GENERATOR if b.anybits?(FIELD_SIZE)
36
+ end
37
+
38
+ # Special cases for zero
39
+ @log_table[0] = LIMIT
40
+ @antilog_table[LIMIT] = 0
41
+ end
42
+
43
+ # Get log value (discrete logarithm)
44
+ def log(value)
45
+ @log_table[value & 0xFFFF]
46
+ end
47
+
48
+ # Get antilog value (inverse of log)
49
+ def antilog(value)
50
+ @antilog_table[value % FIELD_SIZE]
51
+ end
52
+
53
+ # Addition in GF(2^16) - same as subtraction (XOR)
54
+ def add(a, b)
55
+ (a ^ b) & 0xFFFF
56
+ end
57
+
58
+ # Subtraction in GF(2^16) - same as addition (XOR)
59
+ alias subtract add
60
+
61
+ # Multiplication in GF(2^16)
62
+ def multiply(a, b)
63
+ a &= 0xFFFF
64
+ b &= 0xFFFF
65
+
66
+ return 0 if a.zero? || b.zero?
67
+
68
+ sum = @log_table[a] + @log_table[b]
69
+ sum -= LIMIT if sum >= LIMIT
70
+ @antilog_table[sum]
71
+ end
72
+
73
+ # Division in GF(2^16)
74
+ def divide(a, b)
75
+ a &= 0xFFFF
76
+ b &= 0xFFFF
77
+
78
+ return 0 if a.zero?
79
+ raise ArgumentError, "Division by zero in GF(2^16)" if b.zero?
80
+
81
+ diff = @log_table[a] - @log_table[b]
82
+ diff += LIMIT if diff.negative?
83
+ @antilog_table[diff]
84
+ end
85
+
86
+ # Power in GF(2^16): compute a^n
87
+ def power(a, n)
88
+ a &= 0xFFFF
89
+
90
+ return 1 if n.zero?
91
+ return 0 if a.zero?
92
+
93
+ product = @log_table[a] * n
94
+
95
+ # Reduce modulo LIMIT using the identity:
96
+ # product mod LIMIT = (product >> BITS) + (product & LIMIT)
97
+ product = (product >> BITS) + (product & LIMIT)
98
+ product -= LIMIT if product >= LIMIT
99
+
100
+ @antilog_table[product]
101
+ end
102
+
103
+ # Compute GCD using Euclidean algorithm
104
+ def gcd(a, b)
105
+ while a != 0 && b != 0
106
+ if a > b
107
+ a %= b
108
+ else
109
+ b %= a
110
+ end
111
+ end
112
+ a + b
113
+ end
114
+
115
+ # Select base values for Reed-Solomon matrix
116
+ # Par2cmdline uses sequential logbases: base[i] = antilog[i]
117
+ # base[0] = antilog[0] = 1, base[1] = antilog[1] = 2, etc.
118
+ def select_bases(count)
119
+ raise ArgumentError, "Too many bases requested" if count >= LIMIT
120
+
121
+ bases = []
122
+
123
+ count.times do |i|
124
+ # Par2cmdline uses logbase = i (NOT i+1!)
125
+ # This gives: base[0]=1, base[1]=2, base[2]=4, etc.
126
+ logbase = i
127
+
128
+ if logbase >= LIMIT
129
+ raise ArgumentError,
130
+ "Too many input blocks for Reed Solomon matrix"
131
+ end
132
+
133
+ # Convert log to actual value
134
+ bases << @antilog_table[logbase]
135
+ end
136
+
137
+ bases
138
+ end
139
+ end
140
+
141
+ # Build tables when class is loaded
142
+ build_tables
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Parity
5
+ module Models
6
+ # PAR2 Creator packet
7
+ #
8
+ # Contains information about the tool that created the PAR2 file.
9
+ # This packet is optional but recommended for identification.
10
+ #
11
+ # Body structure:
12
+ # - creator_string (variable): Null-terminated string identifying the tool
13
+ class CreatorPacket < Packet
14
+ # Packet type identifier
15
+ PACKET_TYPE = "PAR 2.0\x00Creator\x00"
16
+
17
+ # Creator identification string (without null terminator)
18
+ attribute :creator_string, :string, default: -> { "Omnizip PAR2" }
19
+
20
+ # Initialize creator packet
21
+ #
22
+ # @param attributes [Hash] Packet attributes
23
+ def initialize(**attributes)
24
+ super
25
+ self.type = PACKET_TYPE
26
+ end
27
+
28
+ # Parse body data into attributes
29
+ #
30
+ # Body format:
31
+ # - creator_string: null-terminated string
32
+ def parse_body
33
+ return if body_data.nil? || body_data.empty?
34
+
35
+ # Read creator string (null-terminated)
36
+ self.creator_string = body_data.unpack1("Z*")
37
+ end
38
+
39
+ # Build body data from attributes
40
+ #
41
+ # Constructs binary body data with null terminator
42
+ #
43
+ # @return [String] Binary body data
44
+ def build_body
45
+ data = +""
46
+
47
+ # Write creator string (null-terminated)
48
+ data << creator_string
49
+ data << "\x00"
50
+
51
+ self.body_data = data
52
+ end
53
+
54
+ # Get creator tool name
55
+ #
56
+ # @return [String] Creator tool name
57
+ def tool_name
58
+ creator_string.split.first || creator_string
59
+ end
60
+
61
+ # Get creator version if available
62
+ #
63
+ # @return [String, nil] Version string or nil
64
+ def version
65
+ parts = creator_string.split
66
+ parts.size > 1 ? parts[1..].join(" ") : nil
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Parity
5
+ module Models
6
+ # PAR2 File Description packet
7
+ #
8
+ # Contains metadata about a protected file including hashes and filename.
9
+ #
10
+ # Body structure:
11
+ # - file_id (16 bytes): MD5 hash identifying the file
12
+ # - file_hash (16 bytes): MD5 hash of complete file content
13
+ # - file_hash_16k (16 bytes): MD5 hash of first 16KB
14
+ # - length (8 bytes, Q<): File size in bytes
15
+ # - filename (variable): Null-terminated filename, padded to multiple of 4
16
+ class FileDescriptionPacket < Packet
17
+ # Packet type identifier
18
+ PACKET_TYPE = "PAR 2.0\x00FileDesc"
19
+
20
+ # File identifier (16 bytes MD5)
21
+ attribute :file_id, :string
22
+
23
+ # Full file hash (16 bytes MD5)
24
+ attribute :file_hash, :string
25
+
26
+ # First 16KB hash (16 bytes MD5)
27
+ attribute :file_hash_16k, :string
28
+
29
+ # File length in bytes
30
+ attribute :length, :integer
31
+
32
+ # Filename (without null terminator or padding)
33
+ attribute :filename, :string
34
+
35
+ # Initialize file description packet
36
+ #
37
+ # @param attributes [Hash] Packet attributes
38
+ def initialize(**attributes)
39
+ super
40
+ self.type = PACKET_TYPE
41
+ end
42
+
43
+ # Parse body data into attributes
44
+ #
45
+ # Body format:
46
+ # - file_id: 16 bytes
47
+ # - file_hash: 16 bytes
48
+ # - file_hash_16k: 16 bytes
49
+ # - length: 8 bytes (Q<)
50
+ # - filename: null-terminated, padded to multiple of 4
51
+ def parse_body
52
+ return if body_data.nil? || body_data.empty?
53
+
54
+ # Validate minimum size (16+16+16+8 = 56 bytes minimum)
55
+ if body_data.bytesize < 56
56
+ warn "FileDescriptionPacket body too short: #{body_data.bytesize} bytes"
57
+ return
58
+ end
59
+
60
+ pos = 0
61
+
62
+ # Read file_id (16 bytes)
63
+ self.file_id = body_data[pos, 16]
64
+ pos += 16
65
+
66
+ # Read file_hash (16 bytes)
67
+ self.file_hash = body_data[pos, 16]
68
+ pos += 16
69
+
70
+ # Read file_hash_16k (16 bytes)
71
+ self.file_hash_16k = body_data[pos, 16]
72
+ pos += 16
73
+
74
+ # Read length (8 bytes, little-endian unsigned 64-bit)
75
+ length_data = body_data[pos, 8]
76
+ return if length_data.nil? || length_data.bytesize < 8
77
+
78
+ self.length = length_data.unpack1("Q<")
79
+ pos += 8
80
+
81
+ # Read filename (null-terminated, remaining bytes)
82
+ filename_data = body_data[pos..]
83
+ self.filename = filename_data&.unpack1("Z*") || ""
84
+ end
85
+
86
+ # Build body data from attributes
87
+ #
88
+ # Constructs binary body data with proper padding
89
+ #
90
+ # @return [String] Binary body data
91
+ def build_body
92
+ data = +""
93
+
94
+ # Validate file_id, file_hash, file_hash_16k are 16 bytes
95
+ [file_id, file_hash, file_hash_16k].each_with_index do |hash, idx|
96
+ field_name = %w[file_id file_hash file_hash_16k][idx]
97
+ if hash.bytesize != 16
98
+ raise ArgumentError,
99
+ "#{field_name} must be 16 bytes, got #{hash.bytesize}"
100
+ end
101
+ end
102
+
103
+ # Write hashes
104
+ data << file_id
105
+ data << file_hash
106
+ data << file_hash_16k
107
+
108
+ # Write length (8 bytes, little-endian)
109
+ data << [length].pack("Q<")
110
+
111
+ # Write filename (null-terminated, padded to multiple of 4)
112
+ data << filename
113
+ data << "\x00"
114
+
115
+ # Add padding to make total length multiple of 4
116
+ padding = (4 - ((filename.bytesize + 1) % 4)) % 4
117
+ data << ("\x00" * padding) if padding.positive?
118
+
119
+ self.body_data = data
120
+ end
121
+
122
+ # Get basename of file
123
+ #
124
+ # @return [String] File basename
125
+ def basename
126
+ File.basename(filename)
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Parity
5
+ module Models
6
+ # PAR2 IFSC (Input File Slice Checksum) packet
7
+ #
8
+ # Contains checksums for individual data blocks of a file.
9
+ # One IFSC packet contains checksums for ALL blocks of a file.
10
+ #
11
+ # Body structure:
12
+ # - file_id (16 bytes): File identifier
13
+ # - For each block:
14
+ # - block_hash (16 bytes): MD5 hash of block data
15
+ # - block_crc32 (4 bytes, L<): CRC32 of block data
16
+ class IfscPacket < Packet
17
+ # Packet type identifier
18
+ PACKET_TYPE = "PAR 2.0\x00IFSC\x00\x00\x00\x00"
19
+
20
+ # File identifier (16 bytes)
21
+ attribute :file_id, :string
22
+
23
+ # Array of block hashes (16 bytes MD5 each)
24
+ attribute :block_hashes, :string, collection: true, default: -> { [] }
25
+
26
+ # Array of block CRC32s (4 bytes each)
27
+ attribute :block_crc32s, :integer, collection: true, default: -> { [] }
28
+
29
+ # Initialize IFSC packet
30
+ #
31
+ # @param attributes [Hash] Packet attributes
32
+ def initialize(**attributes)
33
+ super
34
+ self.type = PACKET_TYPE
35
+ self.block_hashes = [] if block_hashes.nil?
36
+ self.block_crc32s = [] if block_crc32s.nil?
37
+ end
38
+
39
+ # Parse body data into attributes
40
+ #
41
+ # Body format:
42
+ # - file_id: 16 bytes
43
+ # - For each block:
44
+ # - block_hash: 16 bytes
45
+ # - block_crc32: 4 bytes (L<)
46
+ def parse_body
47
+ return if body_data.nil? || body_data.empty?
48
+ return if body_data.bytesize < 16
49
+
50
+ pos = 0
51
+
52
+ # Read file_id (16 bytes)
53
+ self.file_id = body_data[pos, 16]
54
+ pos += 16
55
+
56
+ # Read all blocks (each is 16 bytes hash + 4 bytes CRC = 20 bytes)
57
+ self.block_hashes = []
58
+ self.block_crc32s = []
59
+
60
+ while pos + 20 <= body_data.bytesize
61
+ # Read block_hash (16 bytes)
62
+ block_hash = body_data[pos, 16]
63
+ pos += 16
64
+
65
+ # Read block_crc32 (4 bytes, little-endian unsigned 32-bit)
66
+ block_crc32 = body_data[pos, 4].unpack1("L<")
67
+ pos += 4
68
+
69
+ block_hashes << block_hash
70
+ block_crc32s << block_crc32
71
+ end
72
+ end
73
+
74
+ # Build body data from attributes
75
+ #
76
+ # Constructs binary body data
77
+ #
78
+ # @return [String] Binary body data
79
+ def build_body
80
+ data = +""
81
+
82
+ # Validate file_id is 16 bytes
83
+ if file_id.bytesize != 16
84
+ raise ArgumentError,
85
+ "file_id must be 16 bytes, got #{file_id.bytesize}"
86
+ end
87
+
88
+ # Write file_id
89
+ data << file_id
90
+
91
+ # Write all blocks
92
+ block_hashes.each_with_index do |block_hash, i|
93
+ # Validate block_hash is 16 bytes
94
+ if block_hash.bytesize != 16
95
+ raise ArgumentError,
96
+ "block_hash must be 16 bytes, got #{block_hash.bytesize}"
97
+ end
98
+
99
+ # Write block_hash
100
+ data << block_hash
101
+
102
+ # Write block_crc32 (4 bytes, little-endian)
103
+ data << [block_crc32s[i]].pack("L<")
104
+ end
105
+
106
+ self.body_data = data
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end