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,671 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module SevenZip
6
+ # Binary data parser for .7z format
7
+ # Implements variable-length encoding and bit vector handling
8
+ class Parser
9
+ include Omnizip::Formats::SevenZip::Constants
10
+
11
+ attr_reader :data, :position
12
+
13
+ # Initialize parser with binary data
14
+ #
15
+ # @param data [String] Binary data to parse
16
+ def initialize(data)
17
+ @data = data.b
18
+ @position = 0
19
+ end
20
+
21
+ # Read a single byte
22
+ #
23
+ # @return [Integer] Byte value (0-255)
24
+ # @raise [EOFError] if no more data available
25
+ def read_byte
26
+ raise EOFError, "End of data" if @position >= @data.bytesize
27
+
28
+ byte = @data.getbyte(@position)
29
+ @position += 1
30
+ byte
31
+ end
32
+
33
+ # Read variable-length integer (7-Zip VLI format)
34
+ #
35
+ # 7-Zip VLI encoding uses the first byte's high bits to determine
36
+ # the number of additional bytes:
37
+ # 0xxxxxxx : value = xxxxxxx (0-127)
38
+ # 10xxxxxx BYTE y[1] : value = (xxxxxx << 8) + y
39
+ # 110xxxxx BYTE y[2] : value = (xxxxx << 16) + y
40
+ # 1110xxxx BYTE y[3] : value = (xxxx << 24) + y
41
+ # ...up to 8 bytes total
42
+ #
43
+ # @return [Integer] Decoded number
44
+ def read_number
45
+ first_byte = read_byte
46
+
47
+ # Single byte encoding (0-127)
48
+ return first_byte if first_byte.nobits?(0x80)
49
+
50
+ # 7-Zip VLI: extra bytes are in little-endian order.
51
+ # Per 7-Zip SDK CInByte2::ReadNumber():
52
+ # - Each set bit in first_byte (from MSB) means one more extra byte
53
+ # - Extra bytes are placed at increasing byte positions (LE)
54
+ # - The remaining data bits from first_byte go at the highest position
55
+ mask = 0x80
56
+ value = 0
57
+ shift = 0
58
+
59
+ while first_byte.anybits?(mask)
60
+ value |= (read_byte << shift)
61
+ shift += 8
62
+ mask >>= 1
63
+ end
64
+
65
+ # The data bits from first_byte go at the highest position
66
+ # When mask reaches 0 (first_byte == 0xFF, 8 extra bytes), there are no data bits
67
+ data_bits = mask.zero? ? 0 : (first_byte & (mask - 1))
68
+ value |= (data_bits << shift)
69
+
70
+ value
71
+ end
72
+
73
+ # Read 32-bit variable-length number
74
+ #
75
+ # @return [Integer] Number value (max 32-bit)
76
+ # @raise [RuntimeError] if value exceeds 32-bit range
77
+ def read_number32
78
+ first_byte = peek_byte
79
+ if first_byte.nobits?(0x80)
80
+ @position += 1
81
+ return first_byte
82
+ end
83
+
84
+ value = read_number
85
+ raise Omnizip::InvalidArchiveError, "Unsupported 32-bit value" if value >= 0x80000000
86
+
87
+ value
88
+ end
89
+
90
+ # Read property ID
91
+ #
92
+ # @return [Integer] Property ID
93
+ def read_id
94
+ read_number
95
+ end
96
+
97
+ # Read fixed-size unsigned 32-bit integer (little-endian)
98
+ #
99
+ # @return [Integer] 32-bit value
100
+ def read_uint32
101
+ raise EOFError if @position + 4 > @data.bytesize
102
+
103
+ value = @data[@position, 4].unpack1("V")
104
+ @position += 4
105
+ value
106
+ end
107
+
108
+ # Read fixed-size unsigned 64-bit integer (little-endian)
109
+ #
110
+ # @return [Integer] 64-bit value
111
+ def read_uint64
112
+ raise EOFError if @position + 8 > @data.bytesize
113
+
114
+ value = @data[@position, 8].unpack1("Q<")
115
+ @position += 8
116
+ value
117
+ end
118
+
119
+ # Read bit vector
120
+ # Format: 1 byte flag, then either all 1s or bit array
121
+ #
122
+ # @param num_items [Integer] Number of items in bit vector
123
+ # @return [Array<Boolean>] Bit vector
124
+ # Raw MSB-first bit vector without an all-defined marker
125
+ # (kEmptyStream/kEmptyFile/kAnti layout)
126
+ def read_raw_bit_vector(num_items)
127
+ num_bytes = (num_items + 7) / 8
128
+ raise EOFError if @position + num_bytes > @data.bytesize
129
+
130
+ bits_data = @data[@position, num_bytes]
131
+ @position += num_bytes
132
+ decode_bit_vector(bits_data, num_items)
133
+ end
134
+
135
+ # Bit vector with an all-defined marker byte (kCRC/kWinAttrib
136
+ # defined-bits layout)
137
+ def read_bit_vector(num_items)
138
+ all_defined = read_byte
139
+ num_bytes = (num_items + 7) / 8
140
+
141
+ if all_defined.zero?
142
+ # Explicit bit vector
143
+ raise EOFError if @position + num_bytes > @data.bytesize
144
+
145
+ bits_data = @data[@position, num_bytes]
146
+ @position += num_bytes
147
+ decode_bit_vector(bits_data, num_items)
148
+ else
149
+ # All bits are set (return 1 for each item, not true)
150
+ Array.new(num_items, 1)
151
+ end
152
+ end
153
+
154
+ # Read raw bytes
155
+ #
156
+ # @param count [Integer] Number of bytes to read
157
+ # @return [String] Binary string
158
+ def read_bytes(count)
159
+ raise EOFError if @position + count > @data.bytesize
160
+
161
+ bytes = @data[@position, count]
162
+ @position += count
163
+ bytes
164
+ end
165
+
166
+ # Skip bytes
167
+ #
168
+ # @param count [Integer] Number of bytes to skip
169
+ def skip(count)
170
+ @position += count
171
+ end
172
+
173
+ # Peek at next byte without advancing position
174
+ #
175
+ # @return [Integer] Next byte value
176
+ def peek_byte
177
+ raise EOFError if @position >= @data.bytesize
178
+
179
+ @data.getbyte(@position)
180
+ end
181
+
182
+ # Check if at end of data
183
+ #
184
+ # @return [Boolean] true if no more data
185
+ def eof?
186
+ @position >= @data.bytesize
187
+ end
188
+
189
+ # Get remaining byte count
190
+ #
191
+ # @return [Integer] Bytes remaining
192
+ def remaining
193
+ @data.bytesize - @position
194
+ end
195
+
196
+ # Read pack info section
197
+ # Contains information about packed streams
198
+ #
199
+ # @param stream_info [StreamInfo] Stream info to populate
200
+ def read_pack_info(stream_info)
201
+ # Read pack position
202
+ stream_info.pack_pos = read_number
203
+
204
+ # Read number of pack streams
205
+ num_pack_streams = read_number
206
+
207
+ # Read properties in any order (7z format allows variable ordering)
208
+ sizes_read = false
209
+
210
+ until eof? || peek_byte == PropertyId::K_END
211
+ prop_type = peek_byte
212
+
213
+ case prop_type
214
+ when PropertyId::SIZE
215
+ read_byte
216
+ num_pack_streams.times do
217
+ stream_info.pack_sizes << read_number
218
+ end
219
+ sizes_read = true
220
+ when PropertyId::CRC
221
+ read_byte
222
+ defined_vec = read_bit_vector(num_pack_streams)
223
+ num_pack_streams.times do |i|
224
+ stream_info.pack_crcs << (defined_vec[i] ? read_uint32 : nil)
225
+ end
226
+ when PropertyId::K_END
227
+ break
228
+ else
229
+ # Unknown property - skip it
230
+ read_byte
231
+ skip_data unless eof?
232
+ end
233
+ end
234
+
235
+ # Verify required SIZE property was present
236
+ raise Omnizip::InvalidArchiveError, "Missing SIZE property in pack info" unless sizes_read
237
+
238
+ # K_END is optional in some 7-Zip versions
239
+ read_byte if !eof? && peek_byte == PropertyId::K_END
240
+ end
241
+
242
+ # Read folders section
243
+ # Contains compression method and coder information
244
+ #
245
+ # @param stream_info [StreamInfo] Stream info to populate
246
+ def read_folders(stream_info)
247
+ num_folders = read_number
248
+
249
+ # Read External flag (similar to names)
250
+ external = read_byte
251
+
252
+ # Only read folders if they're stored inline (external == 0)
253
+ if external.zero?
254
+ # Read each folder
255
+ num_folders.times do
256
+ folder = Models::Folder.new
257
+ read_folder(folder)
258
+ stream_info.folders << folder
259
+ end
260
+ else
261
+ # External folders not supported
262
+ raise Omnizip::UnsupportedFormatError, "External folders not supported"
263
+ end
264
+ end
265
+
266
+ # Read single folder definition
267
+ #
268
+ # @param folder [Models::Folder] Folder to populate
269
+ def read_folder(folder)
270
+ num_coders = read_number
271
+ raise Omnizip::InvalidArchiveError, "Too many coders" if num_coders > Constants::MAX_NUM_CODERS
272
+
273
+ num_in_streams = 0
274
+ num_out_streams = 0
275
+
276
+ # Read coders
277
+ num_coders.times do
278
+ coder = Models::CoderInfo.new
279
+ read_coder(coder)
280
+ folder.coders << coder
281
+ num_in_streams += coder.num_in_streams
282
+ num_out_streams += coder.num_out_streams
283
+ end
284
+
285
+ # Read bind pairs
286
+ num_bind_pairs = num_out_streams - 1
287
+ num_bind_pairs.times do
288
+ in_index = read_number
289
+ out_index = read_number
290
+ folder.bind_pairs << [in_index, out_index]
291
+ end
292
+
293
+ # Read pack stream indices
294
+ num_pack_streams = num_in_streams - num_bind_pairs
295
+ if num_pack_streams == 1
296
+ # Single pack stream - find unused input
297
+ (0...num_in_streams).each do |i|
298
+ used = folder.bind_pairs.any? { |pair| pair[0] == i }
299
+ unless used
300
+ folder.pack_stream_indices << i
301
+ break
302
+ end
303
+ end
304
+ else
305
+ # Multiple pack streams - read indices
306
+ num_pack_streams.times do
307
+ folder.pack_stream_indices << read_number
308
+ end
309
+ end
310
+ end
311
+
312
+ # Read coder definition
313
+ #
314
+ # @param coder [Models::CoderInfo] Coder to populate
315
+ def read_coder(coder)
316
+ main_byte = read_byte
317
+
318
+ # Extract coder flags
319
+ id_size = main_byte & 0x0F
320
+ has_attributes = main_byte.anybits?(0x20)
321
+ complex_streams = main_byte.anybits?(0x10)
322
+
323
+ # Read method ID
324
+ method_id = 0
325
+ id_size.times do
326
+ method_id = (method_id << 8) | read_byte
327
+ end
328
+ coder.method_id = method_id
329
+
330
+ # Read stream counts if complex
331
+ if complex_streams
332
+ coder.num_in_streams = read_number
333
+ coder.num_out_streams = read_number
334
+ else
335
+ coder.num_in_streams = 1
336
+ coder.num_out_streams = 1
337
+ end
338
+
339
+ # Read properties if present
340
+ return unless has_attributes
341
+
342
+ props_size = read_number
343
+ coder.properties = read_bytes(props_size)
344
+ end
345
+
346
+ # Read unpack info section
347
+ # Contains information about unpacked streams
348
+ #
349
+ # @param stream_info [StreamInfo] Stream info to populate
350
+ def read_unpack_info(stream_info)
351
+ # Read properties in any order (7z format allows variable ordering)
352
+ folders_read = false
353
+ unpack_sizes_read = false
354
+
355
+ until eof? || peek_byte == PropertyId::K_END
356
+ prop_type = read_byte
357
+
358
+ case prop_type
359
+ when PropertyId::FOLDER
360
+ read_folders(stream_info)
361
+ folders_read = true
362
+ when PropertyId::CODERS_UNPACK_SIZE
363
+ # Read unpack sizes for each folder based on numOutStreams
364
+ stream_info.folders.each do |folder|
365
+ # For folders with 0 coders (Copy method), treat as having 1 output stream
366
+ num_out_streams = folder.num_out_streams
367
+ num_out_streams = 1 if num_out_streams.zero?
368
+
369
+ num_out_streams.times do
370
+ folder.unpack_sizes << read_number
371
+ end
372
+ end
373
+ unpack_sizes_read = true
374
+ when PropertyId::CRC
375
+ # Optional: read CRCs
376
+ defined_vec = read_bit_vector(stream_info.num_folders)
377
+ stream_info.num_folders.times do |i|
378
+ stream_info.folders[i].unpack_crc = read_uint32 if defined_vec[i]
379
+ end
380
+ when PropertyId::K_END
381
+ break
382
+ else
383
+ # Skip unknown properties
384
+ skip_data unless eof?
385
+ end
386
+ end
387
+
388
+ # Verify required properties were present
389
+ raise Omnizip::InvalidArchiveError, "Missing FOLDER property in unpack info" unless folders_read
390
+ raise Omnizip::InvalidArchiveError, "Missing CODERS_UNPACK_SIZE property in unpack info" unless unpack_sizes_read
391
+
392
+ # K_END is optional in some 7-Zip versions
393
+ read_byte if !eof? && peek_byte == PropertyId::K_END
394
+ end
395
+
396
+ # Read substreams info section
397
+ # Maps files to compressed streams
398
+ #
399
+ # @param stream_info [StreamInfo] Stream info to populate
400
+ def read_substreams_info(stream_info)
401
+ # Read number of unpack streams per folder
402
+ if !eof? && peek_byte == PropertyId::NUM_UNPACK_STREAM
403
+ read_byte
404
+ stream_info.folders.each do
405
+ stream_info.num_unpack_streams_in_folders << read_number
406
+ end
407
+ else
408
+ # Default: one stream per folder
409
+ stream_info.folders.size.times do
410
+ stream_info.num_unpack_streams_in_folders << 1
411
+ end
412
+ end
413
+
414
+ # Read unpack sizes
415
+ if !eof? && peek_byte == PropertyId::SIZE
416
+ read_byte
417
+ stream_info.folders.each_with_index do |folder, i|
418
+ num_streams = stream_info.num_unpack_streams_in_folders[i]
419
+ start_idx = stream_info.unpack_sizes.size
420
+
421
+ if num_streams > 1
422
+ (num_streams - 1).times do
423
+ size = read_number
424
+ stream_info.unpack_sizes << size
425
+ end
426
+ end
427
+ # Last stream size = folder's final output size - sum of sizes we just read for this folder
428
+ folder_total_size = folder.uncompressed_size
429
+ sum = stream_info.unpack_sizes[start_idx..]&.sum || 0
430
+ last_size = folder_total_size - sum
431
+ stream_info.unpack_sizes << last_size
432
+ end
433
+ else
434
+ # No SIZE property - use folder unpack sizes directly
435
+ # This happens when each folder has exactly one stream
436
+ stream_info.folders.each_with_index do |folder, i|
437
+ num_streams = stream_info.num_unpack_streams_in_folders[i]
438
+ if num_streams == 1
439
+ # Single stream - use folder's total unpack size
440
+ folder_size = folder.unpack_sizes.empty? ? 0 : folder.unpack_sizes.sum
441
+ stream_info.unpack_sizes << folder_size
442
+ end
443
+ end
444
+ end
445
+
446
+ # Read digests (CRCs)
447
+ num_digests = stream_info.num_unpack_streams_in_folders.sum
448
+ if !(eof? || peek_byte == PropertyId::K_END) && (peek_byte == PropertyId::CRC)
449
+ read_byte
450
+ defined_vec = read_bit_vector(num_digests)
451
+ num_digests.times do |i|
452
+ stream_info.digests << (defined_vec[i] ? read_uint32 : nil)
453
+ end
454
+ end
455
+
456
+ # K_END is optional in some 7-Zip versions
457
+ read_byte if !eof? && peek_byte == PropertyId::K_END
458
+ end
459
+
460
+ # Read files info section
461
+ # Contains file metadata (names, timestamps, attributes)
462
+ #
463
+ # @return [Array<Models::FileEntry>] Array of file entries
464
+ def read_files_info
465
+ num_files = read_number
466
+ entries = Array.new(num_files) { Models::FileEntry.new }
467
+
468
+ # Read file properties
469
+ until eof? || peek_byte == PropertyId::K_END
470
+ prop_type = read_byte
471
+
472
+ case prop_type
473
+ when PropertyId::NAME
474
+ read_names(entries)
475
+ when PropertyId::EMPTY_STREAM
476
+ read_empty_stream(entries)
477
+ when PropertyId::EMPTY_FILE
478
+ read_empty_file(entries)
479
+ when PropertyId::ANTI
480
+ read_anti(entries)
481
+ when PropertyId::CTIME
482
+ read_timestamps(entries, :ctime)
483
+ when PropertyId::ATIME
484
+ read_timestamps(entries, :atime)
485
+ when PropertyId::MTIME
486
+ read_timestamps(entries, :mtime)
487
+ when PropertyId::WIN_ATTRIB
488
+ read_attributes(entries)
489
+ when PropertyId::DUMMY
490
+ skip_data
491
+ else
492
+ skip_data
493
+ end
494
+ end
495
+
496
+ read_byte if !eof? && peek_byte == PropertyId::K_END
497
+
498
+ entries
499
+ end
500
+
501
+ # Read file names
502
+ #
503
+ # @param entries [Array<Models::FileEntry>] File entries
504
+ def read_names(entries)
505
+ # Size of all names in bytes
506
+ size = read_number
507
+ start_pos = @position
508
+ external = read_byte
509
+
510
+ if external.zero?
511
+ # Names stored inline as UTF-16LE null-terminated strings
512
+ entries.each do |entry|
513
+ name_bytes = +""
514
+ loop do
515
+ ch1 = read_byte
516
+ ch2 = read_byte
517
+ break if ch1.zero? && ch2.zero?
518
+
519
+ name_bytes << [ch1, ch2].pack("CC")
520
+ end
521
+ entry.name = name_bytes.encode("UTF-8", "UTF-16LE")
522
+ end
523
+ end
524
+
525
+ # Ensure we consumed expected bytes
526
+ consumed = @position - start_pos
527
+ skip(size - consumed) if consumed < size
528
+ end
529
+
530
+ # Read empty stream flags
531
+ #
532
+ # @param entries [Array<Models::FileEntry>] File entries
533
+ def read_empty_stream(entries)
534
+ skip_size
535
+ # kEmptyStream carries a RAW bit vector — no all-defined
536
+ # marker byte (unlike kCRC/kWinAttrib)
537
+ empty_stream = read_raw_bit_vector(entries.size)
538
+ entries.each_with_index do |entry, i|
539
+ entry.has_stream = empty_stream[i].zero?
540
+ entry.is_dir = (empty_stream[i] == 1)
541
+ end
542
+ end
543
+
544
+ # Read empty file flags
545
+ #
546
+ # @param entries [Array<Models::FileEntry>] File entries
547
+ def read_empty_file(entries)
548
+ skip_size
549
+ empty_files = entries.reject(&:has_stream)
550
+ empty_bits = read_raw_bit_vector(empty_files.size)
551
+ empty_files.each_with_index do |entry, i|
552
+ # Bit set = zero-byte FILE (not a directory)
553
+ entry.is_empty = empty_bits[i] == 1
554
+ entry.is_dir = false if entry.is_empty
555
+ end
556
+ end
557
+
558
+ # Read anti flags
559
+ #
560
+ # @param entries [Array<Models::FileEntry>] File entries
561
+ def read_anti(entries)
562
+ skip_size
563
+ anti_files = entries.select { |e| !e.has_stream && !e.is_empty }
564
+ anti_bits = read_raw_bit_vector(anti_files.size)
565
+ anti_files.each_with_index do |entry, i|
566
+ entry.is_anti = anti_bits[i]
567
+ end
568
+ end
569
+
570
+ # Read timestamps
571
+ #
572
+ # @param entries [Array<Models::FileEntry>] File entries
573
+ # @param attr [Symbol] Attribute name (:mtime, :atime, :ctime)
574
+ def read_timestamps(entries, attr)
575
+ skip_size
576
+ defined_bits = read_bit_vector(entries.size)
577
+ external = read_byte
578
+
579
+ return unless external.zero?
580
+
581
+ entries.each_with_index do |entry, i|
582
+ next unless defined_bits[i]
583
+
584
+ time_val = read_uint64
585
+ # Convert Windows FILETIME to Ruby Time
586
+ # (100-nanosecond intervals since 1601-01-01)
587
+ entry.public_send(:"#{attr}=", windows_time_to_unix(time_val))
588
+ end
589
+ end
590
+
591
+ # Read file attributes
592
+ #
593
+ # @param entries [Array<Models::FileEntry>] File entries
594
+ def read_attributes(entries)
595
+ skip_size
596
+ defined_bits = read_bit_vector(entries.size)
597
+ external = read_byte
598
+
599
+ return unless external.zero?
600
+
601
+ entries.each_with_index do |entry, i|
602
+ entry.attributes = read_uint32 if defined_bits[i]
603
+ end
604
+ end
605
+
606
+ # Expect specific property ID
607
+ #
608
+ # @param expected [Integer] Expected property ID
609
+ # @raise [RuntimeError] if property doesn't match
610
+ def expect_property(expected)
611
+ actual = read_byte
612
+ return if actual == expected
613
+
614
+ raise Omnizip::InvalidArchiveError, "Expected property 0x#{expected.to_s(16)}, " \
615
+ "got 0x#{actual.to_s(16)}"
616
+ end
617
+
618
+ # Skip size field
619
+ def skip_size
620
+ read_number
621
+ end
622
+
623
+ # Skip property data
624
+ def skip_data
625
+ size = read_number
626
+ skip(size)
627
+ end
628
+
629
+ # Convert Windows FILETIME to Unix timestamp
630
+ #
631
+ # @param windows_time [Integer] Windows FILETIME
632
+ # @return [Time] Ruby Time object
633
+ def windows_time_to_unix(windows_time)
634
+ # Windows FILETIME epoch: 1601-01-01
635
+ # Unix epoch: 1970-01-01
636
+ # Difference: 11644473600 seconds
637
+ unix_time = (windows_time / 10_000_000) - 11_644_473_600
638
+ Time.at(unix_time)
639
+ rescue StandardError
640
+ nil
641
+ end
642
+
643
+ private
644
+
645
+ # Decode bit vector from packed bytes
646
+ #
647
+ # @param bits_data [String] Packed bit data
648
+ # @param num_items [Integer] Number of items
649
+ # @return [Array<Boolean>] Decoded bits
650
+ def decode_bit_vector(bits_data, num_items)
651
+ result = []
652
+ byte_idx = 0
653
+ bit_idx = 7
654
+
655
+ num_items.times do
656
+ byte = bits_data.getbyte(byte_idx)
657
+ result << ((byte >> bit_idx) & 1)
658
+
659
+ bit_idx -= 1
660
+ if bit_idx.negative?
661
+ bit_idx = 7
662
+ byte_idx += 1
663
+ end
664
+ end
665
+
666
+ result
667
+ end
668
+ end
669
+ end
670
+ end
671
+ end