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,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (C) 2025 Ribose Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a
7
+ # copy of this software and associated documentation files (the "Software"),
8
+ # to deal in the Software without restriction, including without limitation
9
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ # and/or sell copies of the Software, and to permit persons to whom the
11
+ # Software is furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ # DEALINGS IN THE SOFTWARE.
23
+ #
24
+ # XZ Utils Delta filter implementation.
25
+ #
26
+ # This is the XZ Utils Delta filter (filter ID 0x03), which is DIFFERENT
27
+ # from the 7-Zip Delta filter. Both compute byte-wise differences but use
28
+ # different algorithms:
29
+ #
30
+ # - 7-Zip Delta: Simple forward difference (new[i] = old[i] - old[i-distance])
31
+ # - XZ Utils Delta: Uses a 256-byte circular history buffer
32
+ #
33
+ # Reference: /Users/mulgogi/src/external/xz/src/liblzma/delta/
34
+ #
35
+ # Algorithm summary:
36
+ # - Maintains a 256-byte circular history buffer
37
+ # - Encoder: out[i] = in[i] - history[(distance + pos) & 0xFF]
38
+ # - Decoder: out[i] = in[i] + history[(distance + pos) & 0xFF]
39
+ # - history[pos & 0xFF] = processed_byte (updated in both encode/decode)
40
+ # - pos decrements each byte, wrapping via & 0xFF
41
+ #
42
+ # The distance parameter (1-256) determines how far back in the history
43
+ # to look for the delta reference value.
44
+
45
+ module Omnizip
46
+ module Filters
47
+ # XZ Utils Delta filter.
48
+ #
49
+ # This filter computes byte-wise differences using a 256-byte circular
50
+ # history buffer. It is particularly effective for:
51
+ # - Stereo audio (distance=4 for 16-bit samples)
52
+ # - RGB images (distance=3)
53
+ # - RGBA images (distance=4)
54
+ # - Multi-channel data with regular patterns
55
+ #
56
+ # This is DIFFERENT from the 7-Zip Delta filter which uses simple
57
+ # forward differences without a history buffer.
58
+ #
59
+ # Reference: XZ Utils delta_encoder.c, delta_decoder.c
60
+ class XzDeltaFilter
61
+ # Filter ID for XZ format
62
+ FILTER_ID = 0x03
63
+
64
+ # Minimum distance value (XZ Utils LZMA_DELTA_DIST_MIN)
65
+ DELTA_DIST_MIN = 1
66
+
67
+ # Maximum distance value (XZ Utils LZMA_DELTA_DIST_MAX)
68
+ DELTA_DIST_MAX = 256
69
+
70
+ # History buffer size (always 256 bytes in XZ Utils)
71
+ HISTORY_SIZE = 256
72
+
73
+ # Delta type (only BYTE is supported in XZ Utils)
74
+ DELTA_TYPE_BYTE = 0
75
+
76
+ attr_reader :distance
77
+
78
+ # Initialize the Delta filter.
79
+ #
80
+ # @param distance [Integer] Byte distance for delta calculation (1-256)
81
+ # @raise [ArgumentError] If distance is invalid
82
+ def initialize(distance = DELTA_DIST_MIN)
83
+ validate_distance(distance)
84
+ @distance = distance
85
+ # Initialize state (matches XZ Utils lzma_delta_coder_init)
86
+ @pos = 0
87
+ @history = ("\x00" * HISTORY_SIZE).b
88
+ end
89
+
90
+ # Encode (preprocess) data by computing forward differences.
91
+ #
92
+ # For each byte:
93
+ # tmp = history[(distance + pos) & 0xFF]
94
+ # history[pos & 0xFF] = in[i]
95
+ # out[i] = in[i] - tmp (mod 256)
96
+ # pos--
97
+ #
98
+ # Reference: XZ Utils delta_encoder.c:copy_and_encode
99
+ #
100
+ # @param data [String] Binary data to encode
101
+ # @return [String] Encoded binary data
102
+ def encode(data)
103
+ return data.dup.b if data.empty?
104
+
105
+ result = data.dup.b
106
+ data.bytes.each_with_index do |byte, i|
107
+ # Get historical value from distance positions back
108
+ tmp = @history.getbyte((@distance + @pos) & 0xFF)
109
+
110
+ # Store current byte in history
111
+ @history.setbyte(@pos & 0xFF, byte)
112
+
113
+ # Output is the difference
114
+ result.setbyte(i, (byte - tmp) & 0xFF)
115
+
116
+ # Move position backward (wraps via & 0xFF)
117
+ @pos = (@pos - 1) & 0xFF
118
+ end
119
+
120
+ result
121
+ end
122
+
123
+ # Decode (postprocess) data by restoring from differences.
124
+ #
125
+ # For each byte:
126
+ # buffer[i] += history[(distance + pos) & 0xFF] (mod 256)
127
+ # history[pos & 0xFF] = buffer[i]
128
+ # pos--
129
+ #
130
+ # Reference: XZ Utils delta_decoder.c:decode_buffer
131
+ #
132
+ # @param data [String] Binary data to decode
133
+ # @return [String] Decoded binary data
134
+ def decode(data)
135
+ return data.dup.b if data.empty?
136
+
137
+ result = data.dup.b
138
+ data.bytes.each_with_index do |byte, i|
139
+ # Get historical value from distance positions back
140
+ tmp = @history.getbyte((@distance + @pos) & 0xFF)
141
+
142
+ # Restore original value by adding the difference
143
+ result.setbyte(i, (byte + tmp) & 0xFF)
144
+
145
+ # Store restored byte in history
146
+ @history.setbyte(@pos & 0xFF, result.getbyte(i))
147
+
148
+ # Move position backward (wraps via & 0xFF)
149
+ @pos = (@pos - 1) & 0xFF
150
+ end
151
+
152
+ result
153
+ end
154
+
155
+ # Reset the filter state.
156
+ #
157
+ # This clears the history buffer and resets position to 0.
158
+ # Used when initializing a new filter chain.
159
+ #
160
+ # @return [void]
161
+ def reset
162
+ @pos = 0
163
+ @history = ("\x00" * HISTORY_SIZE).b
164
+ end
165
+
166
+ class << self
167
+ # Decode properties byte to get distance.
168
+ #
169
+ # XZ Utils encodes distance as: props[0] = dist - 1
170
+ # So we decode as: dist = props[0] + 1
171
+ #
172
+ # Reference: XZ Utils delta_decoder.c:lzma_delta_props_decode
173
+ #
174
+ # @param properties [String] Properties byte (1 byte)
175
+ # @return [Integer] Distance value (1-256)
176
+ # @raise [ArgumentError] If properties size is invalid
177
+ def decode_properties(properties)
178
+ unless properties.is_a?(String) && properties.bytesize == 1
179
+ raise ArgumentError,
180
+ "Delta filter requires exactly 1 property byte, got #{properties&.bytesize}"
181
+ end
182
+
183
+ props_byte = properties.getbyte(0)
184
+ # XZ Utils: opt->dist = props[0] + LZMA_DELTA_DIST_MIN
185
+ # where LZMA_DELTA_DIST_MIN = 1
186
+ distance = props_byte + DELTA_DIST_MIN
187
+
188
+ # Validate distance is in valid range (inline for class method)
189
+ unless distance.between?(DELTA_DIST_MIN, DELTA_DIST_MAX)
190
+ raise ArgumentError,
191
+ "Invalid distance #{distance}, must be between #{DELTA_DIST_MIN} and #{DELTA_DIST_MAX}"
192
+ end
193
+
194
+ distance
195
+ end
196
+
197
+ # Encode distance to properties byte.
198
+ #
199
+ # XZ Utils encodes distance as: props[0] = dist - 1
200
+ #
201
+ # Reference: XZ Utils delta_encoder.c:lzma_delta_props_encode
202
+ #
203
+ # @param distance [Integer] Distance value (1-256)
204
+ # @return [String] Properties byte (1 byte)
205
+ # @raise [ArgumentError] If distance is invalid
206
+ def encode_properties(distance)
207
+ # Validate distance (inline for class method)
208
+ unless distance.is_a?(Integer)
209
+ raise ArgumentError,
210
+ "Distance must be an integer, got #{distance.class}"
211
+ end
212
+
213
+ unless distance.between?(DELTA_DIST_MIN, DELTA_DIST_MAX)
214
+ raise ArgumentError,
215
+ "Distance must be between #{DELTA_DIST_MIN} and #{DELTA_DIST_MAX}, got #{distance}"
216
+ end
217
+
218
+ # XZ Utils: out[0] = opt->dist - LZMA_DELTA_DIST_MIN
219
+ # where LZMA_DELTA_DIST_MIN = 1
220
+ props_byte = distance - DELTA_DIST_MIN
221
+
222
+ [props_byte].pack("C")
223
+ end
224
+
225
+ # Get metadata about this filter.
226
+ #
227
+ # @return [Hash] Filter metadata
228
+ def metadata
229
+ {
230
+ name: "XZ Delta",
231
+ description: "XZ Utils Delta filter with 256-byte circular history buffer",
232
+ filter_id: FILTER_ID,
233
+ typical_usage: "WAV audio (distance=4), BMP images (distance=3), " \
234
+ "multi-channel data with regular patterns",
235
+ }
236
+ end
237
+ end
238
+
239
+ private
240
+
241
+ # Validate distance parameter.
242
+ #
243
+ # @param dist [Integer] Distance value to validate
244
+ # @raise [ArgumentError] If distance is invalid
245
+ # @return [void]
246
+ def validate_distance(dist)
247
+ unless dist.is_a?(Integer)
248
+ raise ArgumentError, "Distance must be an integer, got #{dist.class}"
249
+ end
250
+
251
+ unless dist.between?(DELTA_DIST_MIN, DELTA_DIST_MAX)
252
+ raise ArgumentError,
253
+ "Distance must be between #{DELTA_DIST_MIN} and #{DELTA_DIST_MAX}, got #{dist}"
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ # Filter implementations for preprocessing data before compression
5
+ module Filters
6
+ autoload :BCJ, "omnizip/filters/bcj"
7
+ autoload :BcjX86, "omnizip/filters/bcj_x86"
8
+ autoload :Bcj2, "omnizip/filters/bcj2"
9
+ autoload :Bcj2Constants, "omnizip/filters/bcj2/constants"
10
+ autoload :Bcj2StreamData, "omnizip/filters/bcj2/stream_data"
11
+ autoload :Bcj2Decoder, "omnizip/filters/bcj2/decoder"
12
+ autoload :Bcj2Encoder, "omnizip/filters/bcj2/encoder"
13
+ autoload :BcjArm, "omnizip/filters/bcj_arm"
14
+ autoload :BcjArm64, "omnizip/filters/bcj_arm64"
15
+ autoload :BcjPpc, "omnizip/filters/bcj_ppc"
16
+ autoload :BcjSparc, "omnizip/filters/bcj_sparc"
17
+ autoload :BcjIa64, "omnizip/filters/bcj_ia64"
18
+ autoload :Delta, "omnizip/filters/delta"
19
+ end
20
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ # Detects archive format from file signature/magic bytes
5
+ #
6
+ # This class identifies archive formats based on their file signatures.
7
+ # It distinguishes between XZ Utils format (.xz) and 7-Zip format (.7z)
8
+ # which are DIFFERENT implementations of LZMA/LZMA2 compression.
9
+ #
10
+ # @example Basic usage
11
+ # format = Omnizip::FormatDetector.detect("archive.xz")
12
+ # case format
13
+ # when :xz
14
+ # # Use XZ Utils implementation
15
+ # when :seven_zip
16
+ # # Use 7-Zip implementation
17
+ # end
18
+ #
19
+ class FormatDetector
20
+ # XZ Utils format signature: "\xFD7zXZ\x00"
21
+ XZ_SIGNATURE = [0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00].freeze
22
+
23
+ # 7-Zip format signature: "7z\xBC\xAF\x27\x1C"
24
+ SEVEN_ZIP_SIGNATURE = [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C].freeze
25
+
26
+ # RAR5 format signature: "Rar!\x1A\x07\x01\x00"
27
+ RAR5_SIGNATURE = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00].freeze
28
+
29
+ # RAR4 format signature: "Rar!\x1A\x07\x00"
30
+ RAR4_SIGNATURE = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00].freeze
31
+
32
+ # ZIP format signature: "PK\x03\x04"
33
+ ZIP_SIGNATURE = [0x50, 0x4B, 0x03, 0x04].freeze
34
+
35
+ # GZIP format signature: "\x1F\x8B"
36
+ GZIP_SIGNATURE = [0x1F, 0x8B].freeze
37
+
38
+ # BZIP2 format signature: "BZ"
39
+ BZIP2_SIGNATURE = [0x42, 0x5A].freeze
40
+
41
+ # Detect archive format from file path
42
+ #
43
+ # @param file_path [String] Path to the archive file
44
+ # @return [Symbol, nil] Format identifier (:xz, :seven_zip, :rar5, :rar4,
45
+ # :zip, :gzip, :bzip2, :lzma_alone) or nil if unknown
46
+ def self.detect(file_path)
47
+ return nil unless File.exist?(file_path)
48
+
49
+ header = File.binread(file_path, 16)
50
+ return nil if header.nil? || header.empty?
51
+
52
+ bytes = header.bytes
53
+
54
+ case bytes
55
+ in [0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00, *]
56
+ :xz
57
+ in [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C, *]
58
+ :seven_zip
59
+ in [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00, *]
60
+ :rar5
61
+ in [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00, *]
62
+ :rar4
63
+ in [0x50, 0x4B, 0x03, 0x04, *]
64
+ :zip
65
+ in [0x1F, 0x8B, *]
66
+ :gzip
67
+ in [0x42, 0x5A, *]
68
+ :bzip2
69
+ else
70
+ # Check for LZMA_Alone format (13-byte header with properties)
71
+ detect_lzma_alone(bytes)
72
+ end
73
+ end
74
+
75
+ # Check if file is XZ Utils format
76
+ #
77
+ # @param file_path [String] Path to the file
78
+ # @return [Boolean] true if XZ format
79
+ def self.xz?(file_path)
80
+ detect(file_path) == :xz
81
+ end
82
+
83
+ # Check if file is 7-Zip format
84
+ #
85
+ # @param file_path [String] Path to the file
86
+ # @return [Boolean] true if 7-Zip format
87
+ def self.seven_zip?(file_path)
88
+ detect(file_path) == :seven_zip
89
+ end
90
+
91
+ # Check if file is RAR5 format
92
+ #
93
+ # @param file_path [String] Path to the file
94
+ # @return [Boolean] true if RAR5 format
95
+ def self.rar5?(file_path)
96
+ detect(file_path) == :rar5
97
+ end
98
+
99
+ # Check if file is RAR4 format
100
+ #
101
+ # @param file_path [String] Path to the file
102
+ # @return [Boolean] true if RAR4 format
103
+ def self.rar4?(file_path)
104
+ detect(file_path) == :rar4
105
+ end
106
+
107
+ # Mapping of detected format symbols to (extension, constant-path)
108
+ # tuples. The constant path is resolved lazily so autoload fires
109
+ # only when a format is actually requested.
110
+ READER_FOR_FORMAT = {
111
+ xz: ["omnizip/formats/xz", "Omnizip::Formats::Xz"],
112
+ seven_zip: ["omnizip/formats/seven_zip", "Omnizip::Formats::SevenZip::Reader"],
113
+ rar5: ["omnizip/formats/rar5", "Omnizip::Formats::Rar5::Reader"],
114
+ rar4: ["omnizip/formats/rar3", "Omnizip::Formats::Rar3::Reader"],
115
+ zip: ["omnizip/formats/zip", "Omnizip::Formats::Zip::Reader"],
116
+ gzip: ["omnizip/formats/gzip", "Omnizip::Formats::Gzip"],
117
+ bzip2: ["omnizip/formats/bzip2_file", "Omnizip::Formats::Bzip2File"],
118
+ }.freeze
119
+
120
+ # Get the appropriate reader class for the format
121
+ #
122
+ # @param file_path [String] Path to the archive file
123
+ # @return [Class, nil] Reader class or nil if unknown format
124
+ def self.reader_for(file_path)
125
+ format = detect(file_path)
126
+ return nil unless format
127
+
128
+ mapping = READER_FOR_FORMAT[format]
129
+ return nil unless mapping
130
+
131
+ _path, const_path = mapping
132
+ Object.const_get(const_path)
133
+ end
134
+
135
+ # Detect LZMA_Alone format
136
+ #
137
+ # LZMA_Alone format has a 13-byte header:
138
+ # - 1 byte: properties (lc, lp, pb encoded)
139
+ # - 4 bytes: dictionary size (little-endian)
140
+ # - 8 bytes: uncompressed size (little-endian, -1 for unknown)
141
+ #
142
+ # @param bytes [Array<Integer>] First bytes of file
143
+ # @return [Symbol, nil] :lzma_alone or nil
144
+ def self.detect_lzma_alone(bytes)
145
+ return nil if bytes.size < 13
146
+
147
+ # Check properties byte (must be valid lc/lp/pb encoding)
148
+ props = bytes[0]
149
+ return nil if props > 225 # Max valid value is (9 * 5 * 5) - 1 = 224
150
+
151
+ lc = props % 9
152
+ lp = (props / 9) % 5
153
+ pb = props / 45
154
+
155
+ # Validate ranges
156
+ return nil if lc > 8 || lp > 4 || pb > 4
157
+
158
+ # Dictionary size should be power of 2 or close to it
159
+ dict_size = bytes[1, 4].pack("C*").unpack1("V")
160
+ return nil if dict_size.zero? || dict_size > (1 << 30) # Max ~1GB
161
+
162
+ :lzma_alone
163
+ end
164
+ private_class_method :detect_lzma_alone
165
+ end
166
+ end
File without changes
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ module Omnizip
6
+ module Formats
7
+ # BZIP2 file format
8
+ #
9
+ # BZIP2 is a file compression format that uses the BZip2 algorithm
10
+ # with block-sorting compression (Burrows-Wheeler Transform).
11
+ #
12
+ # Format structure:
13
+ # - Magic bytes: "BZh" (0x42 0x5A 0x68)
14
+ # - Block size indicator: '1'-'9' (100KB - 900KB)
15
+ # - Compressed blocks
16
+ # - End-of-stream marker
17
+ #
18
+ # The format supports multiple compressed blocks, each with its own
19
+ # CRC32 checksum for data integrity verification.
20
+ module Bzip2File
21
+ # BZIP2 magic bytes
22
+ BZIP2_MAGIC = "BZh"
23
+
24
+ # Block size markers ('1' to '9')
25
+ BLOCK_SIZE_MIN = 1
26
+ BLOCK_SIZE_MAX = 9
27
+
28
+ # Stream markers
29
+ STREAM_MAGIC = 0x314159265359 # π in hex
30
+ BLOCK_MAGIC = 0x177245385090 # Block start marker
31
+ STREAM_END_MAGIC = 0x177245385090 # Stream end marker
32
+
33
+ class << self
34
+ # Compress a file with BZIP2
35
+ #
36
+ # @param input_path [String] Input file path
37
+ # @param output_path [String] Output BZIP2 file path
38
+ # @param options [Hash] Compression options
39
+ # @option options [Integer] :level Compression level (1-9)
40
+ def compress(input_path, output_path, options = {})
41
+ input_data = File.binread(input_path)
42
+
43
+ File.open(output_path, "wb") do |output|
44
+ compress_stream(StringIO.new(input_data), output, options)
45
+ end
46
+ end
47
+
48
+ # Decompress a BZIP2 file
49
+ #
50
+ # @param input_path [String] Input BZIP2 file path
51
+ # @param output_path [String] Output file path
52
+ def decompress(input_path, output_path)
53
+ File.open(input_path, "rb") do |input|
54
+ File.open(output_path, "wb") do |output|
55
+ decompress_stream(input, output)
56
+ end
57
+ end
58
+ end
59
+
60
+ # Compress data stream with BZIP2
61
+ #
62
+ # @param input_io [IO] Input stream
63
+ # @param output_io [IO] Output stream
64
+ # @param options [Hash] Compression options
65
+ def compress_stream(input_io, output_io, options = {})
66
+ level = options[:level] || 9
67
+ level = level.clamp(BLOCK_SIZE_MIN, BLOCK_SIZE_MAX)
68
+
69
+ input_data = input_io.read
70
+
71
+ # Write BZIP2 header
72
+ write_header(output_io, level)
73
+
74
+ # Get BZip2 algorithm
75
+ bzip2 = AlgorithmRegistry.get(:bzip2).new
76
+
77
+ # Compress data
78
+ compressed_io = StringIO.new
79
+ compressed_io.set_encoding(Encoding::BINARY)
80
+
81
+ bzip2.compress(
82
+ StringIO.new(input_data),
83
+ compressed_io,
84
+ build_compression_options(level),
85
+ )
86
+
87
+ # Write compressed data
88
+ compressed_io.rewind
89
+ compressed_data = compressed_io.read
90
+ output_io.write(compressed_data)
91
+ end
92
+
93
+ # Decompress BZIP2 stream
94
+ #
95
+ # @param input_io [IO] Input stream
96
+ # @param output_io [IO] Output stream
97
+ def decompress_stream(input_io, output_io)
98
+ # Read and verify header
99
+ read_header(input_io)
100
+
101
+ # Get BZip2 algorithm
102
+ bzip2 = AlgorithmRegistry.get(:bzip2).new
103
+
104
+ # Decompress data
105
+ decompressed_io = StringIO.new
106
+ decompressed_io.set_encoding(Encoding::BINARY)
107
+
108
+ bzip2.decompress(input_io, decompressed_io)
109
+
110
+ # Write decompressed data
111
+ decompressed_io.rewind
112
+ output_io.write(decompressed_io.read)
113
+ end
114
+
115
+ private
116
+
117
+ # Write BZIP2 header
118
+ #
119
+ # @param output [IO] Output stream
120
+ # @param level [Integer] Compression level (1-9)
121
+ def write_header(output, level)
122
+ # BZIP2 magic: "BZh" + block size
123
+ header = "#{BZIP2_MAGIC}#{level}"
124
+ output.write(header)
125
+ end
126
+
127
+ # Read BZIP2 header
128
+ #
129
+ # @param input [IO] Input stream
130
+ # @return [Integer] Block size level
131
+ def read_header(input)
132
+ magic = input.read(3)
133
+ unless magic == BZIP2_MAGIC
134
+ raise Error, "Not a BZIP2 file (invalid magic bytes)"
135
+ end
136
+
137
+ level_char = input.read(1)
138
+ level = level_char.to_i
139
+
140
+ unless level.between?(BLOCK_SIZE_MIN, BLOCK_SIZE_MAX)
141
+ raise Error, "Invalid BZIP2 block size: #{level_char}"
142
+ end
143
+
144
+ level
145
+ end
146
+
147
+ # Build compression options
148
+ #
149
+ # @param level [Integer] Compression level
150
+ # @return [Object] Compression options
151
+ def build_compression_options(level)
152
+ Models::CompressionOptions.new.tap do |opts|
153
+ opts.level = level
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Cpio
6
+ # IO wrapper that limits reading to a specific byte count
7
+ #
8
+ # Used to read file content from CPIO archives where the file size
9
+ # is known in advance but the underlying IO stream continues.
10
+ class BoundedIO
11
+ attr_reader :length, :remaining
12
+
13
+ # Initialize bounded IO
14
+ #
15
+ # @param io [IO] Underlying IO stream
16
+ # @param length [Integer] Maximum bytes to read
17
+ # @yield Block called when EOF is reached (for reading padding)
18
+ def initialize(io, length, &eof_callback)
19
+ @io = io
20
+ @length = length
21
+ @remaining = length
22
+ @eof_callback = eof_callback
23
+ @eof = false
24
+ end
25
+
26
+ # Read bytes from the IO
27
+ #
28
+ # @param size [Integer, nil] Number of bytes to read (nil = remaining)
29
+ # @return [String, nil] Data read or nil at EOF
30
+ def read(size = nil)
31
+ return nil if eof?
32
+
33
+ size = @remaining if size.nil?
34
+ data = @io.read(size)
35
+ return nil if data.nil?
36
+
37
+ @remaining -= data.bytesize
38
+ eof?
39
+ data
40
+ end
41
+
42
+ # System read (raises on EOF)
43
+ #
44
+ # @param size [Integer] Number of bytes to read
45
+ # @return [String] Data read
46
+ # @raise [EOFError] If at end of bounded region
47
+ def sysread(size)
48
+ raise EOFError, "end of file reached" if eof?
49
+
50
+ read(size)
51
+ end
52
+
53
+ # Check if at end of bounded region
54
+ #
55
+ # @return [Boolean] True if no more bytes to read
56
+ def eof?
57
+ return false if @remaining.positive?
58
+ return @eof if @eof
59
+
60
+ @eof_callback&.call
61
+ @eof = true
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end