omnizip 0.4.7-x86_64-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,437 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "zlib"
5
+ require "stringio"
6
+ require "tmpdir"
7
+
8
+ module Omnizip
9
+ module Formats
10
+ module Rar
11
+ # Pure Ruby RAR archive writer
12
+ #
13
+ # Writes RAR 1.5-4.x ("RAR4") archives per the on-disk layout
14
+ # unrar accepts: HEAD_CRC holds the low 16 bits of a CRC32 over
15
+ # the header bytes that follow it, HEAD_SIZE counts the whole
16
+ # block including the CRC field, and the 7-byte signature is
17
+ # itself the marker block (no second marker follows).
18
+ #
19
+ # Only METHOD_STORE output is interoperable with official RAR
20
+ # tools; the LZ/PPMd encoders produce Omnizip-internal streams
21
+ # that Omnizip can read back but unrar cannot.
22
+ #
23
+ # @example Create a RAR archive
24
+ # writer = Writer.new('archive.rar')
25
+ # writer.add_file('document.pdf')
26
+ # writer.add_directory('photos/')
27
+ # writer.write
28
+ #
29
+ # @example Create with options
30
+ # writer = Writer.new('archive.rar',
31
+ # compression: :best
32
+ # )
33
+ class Writer
34
+ include Omnizip::Formats::Rar::Constants
35
+
36
+ # @return [String] Output archive path
37
+ attr_reader :output_path
38
+
39
+ # @return [Hash] Compression options
40
+ attr_reader :options
41
+
42
+ # @return [Array<Hash>] Files to add
43
+ attr_reader :files
44
+
45
+ # @return [Array<Hash>] Directories to add
46
+ attr_reader :directories
47
+
48
+ # Check if RAR creation is available
49
+ #
50
+ # @return [Boolean] always true for pure Ruby implementation
51
+ def self.available?
52
+ true
53
+ end
54
+
55
+ # Get RAR writer information
56
+ #
57
+ # @return [Hash] Writer type and version
58
+ def self.info
59
+ {
60
+ available: true,
61
+ type: :pure_ruby,
62
+ version: "4.0",
63
+ }
64
+ end
65
+
66
+ # Initialize RAR writer
67
+ #
68
+ # @param output_path [String] Output RAR file path
69
+ # @param options [Hash] Compression options
70
+ # @option options [Symbol] :compression Compression level
71
+ # (:store, :fastest, :fast, :normal, :good, :best)
72
+ # @option options [Boolean] :solid Create solid archive
73
+ # (not implemented; ignored with a warning)
74
+ # @option options [Integer] :recovery Recovery record
75
+ # percentage (not implemented; ignored with a warning)
76
+ # @option options [String] :password Archive password
77
+ # (RAR4 encryption is not implemented)
78
+ # @option options [Integer] :volume_size Split into volumes
79
+ # (not implemented; ignored with a warning)
80
+ # @option options [Boolean] :test_after_create Test archive after creation
81
+ # @raise [NotImplementedError] if :password or :encrypt_headers is given
82
+ def initialize(output_path, options = {})
83
+ @output_path = output_path
84
+ @options = default_options.merge(options)
85
+ @files = []
86
+ @directories = []
87
+
88
+ if @options[:password] || @options[:encrypt_headers]
89
+ raise NotImplementedError,
90
+ "RAR4 encryption is not implemented"
91
+ end
92
+
93
+ warn_unimplemented_options
94
+ end
95
+
96
+ # Add a name-only directory entry (empty trees survive
97
+ # archive creation instead of vanishing)
98
+ #
99
+ # @param archive_path [String] Directory path inside the
100
+ # archive (trailing slash optional)
101
+ # @return [self]
102
+ def add_directory_entry(archive_path)
103
+ @files << {
104
+ source: nil,
105
+ archive_path: archive_path.chomp("/"),
106
+ directory: true,
107
+ }
108
+ self
109
+ end
110
+
111
+ # Add file to archive
112
+ #
113
+ # @param file_path [String] Path to file
114
+ # @param archive_path [String, nil] Path within archive
115
+ # @raise [ArgumentError] if file does not exist
116
+ def add_file(file_path, archive_path = nil)
117
+ raise ArgumentError, "File not found: #{file_path}" unless
118
+ File.exist?(file_path)
119
+
120
+ @files << {
121
+ source: File.expand_path(file_path),
122
+ archive_path: archive_path,
123
+ }
124
+ end
125
+
126
+ # Add directory to archive
127
+ #
128
+ # @param dir_path [String] Path to directory
129
+ # @param recursive [Boolean] Include subdirectories
130
+ # @param archive_path [String, nil] Path within archive
131
+ # @raise [ArgumentError] if directory does not exist
132
+ def add_directory(dir_path, recursive: true, archive_path: nil)
133
+ raise ArgumentError, "Directory not found: #{dir_path}" unless
134
+ Dir.exist?(dir_path)
135
+
136
+ @directories << {
137
+ source: File.expand_path(dir_path),
138
+ recursive: recursive,
139
+ archive_path: archive_path,
140
+ }
141
+ end
142
+
143
+ # Create RAR archive
144
+ #
145
+ # @return [String] Path to created archive
146
+ def write
147
+ File.open(@output_path, "wb") do |io|
148
+ write_signature(io)
149
+ write_archive_header(io)
150
+ write_file_entries(io)
151
+ write_end_block(io)
152
+ end
153
+
154
+ test_archive if @options[:test_after_create]
155
+
156
+ @output_path
157
+ end
158
+
159
+ private
160
+
161
+ # Default compression options
162
+ #
163
+ # @return [Hash] Default options
164
+ def default_options
165
+ {
166
+ compression: :normal,
167
+ solid: false,
168
+ recovery: 0,
169
+ encrypt_headers: false,
170
+ password: nil,
171
+ volume_size: nil,
172
+ test_after_create: false,
173
+ }
174
+ end
175
+
176
+ # Warn about accepted-but-unimplemented options so the
177
+ # resulting archive never advertises features it lacks.
178
+ def warn_unimplemented_options
179
+ if @options[:solid]
180
+ warn "RAR4 writer ignores solid: not implemented " \
181
+ "(no corresponding flag is written)"
182
+ end
183
+ if @options[:volume_size]
184
+ warn "RAR4 writer ignores volume_size: not implemented " \
185
+ "(no corresponding flag is written)"
186
+ end
187
+ recovery = @options[:recovery]
188
+ return unless recovery.is_a?(Numeric) && recovery.positive?
189
+ return if recovery == true
190
+
191
+ warn "RAR4 writer ignores recovery: not implemented " \
192
+ "(no corresponding flag is written)"
193
+ end
194
+
195
+ # RAR4 HEAD_CRC: low 16 bits of the CRC32 over every header
196
+ # byte that follows the 2-byte CRC field (unrar archive.cpp).
197
+ #
198
+ # @param header_data [String] Header bytes after the CRC field
199
+ # @return [Integer] 16-bit CRC value
200
+ def calculate_header_crc(header_data)
201
+ Zlib.crc32(header_data) & 0xFFFF
202
+ end
203
+
204
+ # Convert Ruby Time to DOS time format
205
+ #
206
+ # @param time [Time] Ruby time object
207
+ # @return [Integer] DOS time format (32-bit)
208
+ def dos_time(time)
209
+ dos_date = ((time.year - 1980) << 9) | (time.month << 5) | time.day
210
+ dos_time_part = (time.hour << 11) | (time.min << 5) | (time.sec / 2)
211
+ (dos_date << 16) | dos_time_part
212
+ end
213
+
214
+ # Write RAR signature (the marker block itself)
215
+ #
216
+ # @param io [IO] Output stream
217
+ def write_signature(io)
218
+ io.write(RAR4_SIGNATURE.pack("C*"))
219
+ end
220
+
221
+ # Write archive header (MAIN_HEAD, 13 bytes total)
222
+ #
223
+ # @param io [IO] Output stream
224
+ def write_archive_header(io)
225
+ header_data = [BLOCK_ARCHIVE].pack("C") +
226
+ [0x0000].pack("v") + # HEAD_FLAGS
227
+ [0x000D].pack("v") + # HEAD_SIZE
228
+ [0].pack("v") + [0].pack("V") # HighPosAV, PosAV
229
+
230
+ io.write([calculate_header_crc(header_data)].pack("v"))
231
+ io.write(header_data)
232
+ end
233
+
234
+ # Write file entries
235
+ #
236
+ # @param io [IO] Output stream
237
+ def write_file_entries(io)
238
+ @directories.each do |dir_info|
239
+ write_directory_entries(io, dir_info)
240
+ end
241
+ @files.each do |file_info|
242
+ write_file_entry(io, file_info)
243
+ end
244
+ end
245
+
246
+ # Write a single file entry
247
+ #
248
+ # @param io [IO] Output stream
249
+ # @param file_info [Hash] File information
250
+ def write_file_entry(io, file_info)
251
+ file_path = file_info[:source]
252
+ archive_path = file_info[:archive_path] || File.basename(file_path)
253
+ directory = file_info[:directory] || false
254
+
255
+ file_data = directory ? "" : File.binread(file_path)
256
+
257
+ method = file_info[:method] ||
258
+ (directory ? METHOD_STORE : select_compression_method(file_data))
259
+ compressed_data = compress_data(file_data, method)
260
+
261
+ if directory && file_path.nil?
262
+ # Name-only directory entry: no source to stat
263
+ file_attr = 0o040755
264
+ file_time = dos_time(Time.now)
265
+ data_crc = 0
266
+ else
267
+ stat = File.stat(file_path)
268
+ file_attr = directory ? 0o040755 : stat.mode
269
+ file_time = dos_time(stat.mtime)
270
+ data_crc = Zlib.crc32(file_data)
271
+ end
272
+
273
+ name_bytes = archive_path.encode("UTF-8").bytes
274
+
275
+ # HEAD_FLAGS bit 0x8000 (LONG_BLOCK) marks a data area of
276
+ # PACK_SIZE bytes; the full dictionary mask 0xE0 marks
277
+ # directory entries (a directory has no dictionary) —
278
+ # confirmed against unrar extraction behavior.
279
+ flags = BLOCK_LONG
280
+ flags |= FILE_DIRECTORY if directory
281
+ flags |= FILE_LARGE if file_data.bytesize > 0xFFFFFFFF
282
+
283
+ # Fixed fields after HEAD_SIZE: PACK(4) + UNP(4) + HOST_OS(1)
284
+ # + FILE_CRC(4) + FTIME(4) + UNP_VER(1) + METHOD(1) +
285
+ # NAME_SIZE(2) + ATTR(4) = 25 bytes; plus TYPE(1) +
286
+ # FLAGS(2) + SIZE(2) and the 2-byte CRC itself.
287
+ header_size = 32 + name_bytes.size
288
+ header_size += 8 if flags.anybits?(FILE_LARGE)
289
+
290
+ header_data = [BLOCK_FILE].pack("C") +
291
+ [flags].pack("v") +
292
+ [header_size].pack("v") +
293
+ [compressed_data.bytesize & 0xFFFFFFFF].pack("V") +
294
+ [file_data.bytesize & 0xFFFFFFFF].pack("V") +
295
+ [OS_UNIX].pack("C") +
296
+ [data_crc].pack("V") +
297
+ [file_time].pack("V") +
298
+ [compression_version(method)].pack("C") +
299
+ [method].pack("C") +
300
+ [name_bytes.size].pack("v") +
301
+ [file_attr].pack("V")
302
+
303
+ if flags.anybits?(FILE_LARGE)
304
+ header_data += [(compressed_data.bytesize >> 32) & 0xFFFFFFFF].pack("V")
305
+ header_data += [(file_data.bytesize >> 32) & 0xFFFFFFFF].pack("V")
306
+ end
307
+
308
+ header_data += name_bytes.pack("C*")
309
+
310
+ io.write([calculate_header_crc(header_data)].pack("v"))
311
+ io.write(header_data)
312
+ io.write(compressed_data)
313
+ end
314
+
315
+ # Write directory tree as explicit directory entries plus the
316
+ # files inside them
317
+ #
318
+ # @param io [IO] Output stream
319
+ # @param dir_info [Hash] Directory information
320
+ def write_directory_entries(io, dir_info)
321
+ dir_path = dir_info[:source]
322
+ prefix = dir_info[:archive_path].to_s.gsub(%r{^/+|/+$}, "")
323
+
324
+ pattern = dir_info[:recursive] ? File.join(dir_path, "**", "*") : File.join(dir_path, "*")
325
+ Dir.glob(pattern).each do |path|
326
+ relative = path.delete_prefix("#{dir_path}/")
327
+ name = prefix.empty? ? relative : "#{prefix}/#{relative}"
328
+
329
+ if File.directory?(path)
330
+ write_file_entry(io, {
331
+ source: path,
332
+ archive_path: name,
333
+ directory: true,
334
+ })
335
+ else
336
+ write_file_entry(io, {
337
+ source: path,
338
+ archive_path: name,
339
+ })
340
+ end
341
+ end
342
+ end
343
+
344
+ # Write end block (ENDARC, 7 bytes total)
345
+ #
346
+ # @param io [IO] Output stream
347
+ def write_end_block(io)
348
+ header_data = [BLOCK_ENDARC].pack("C") +
349
+ [0x0000].pack("v") +
350
+ [0x0007].pack("v")
351
+
352
+ io.write([calculate_header_crc(header_data)].pack("v"))
353
+ io.write(header_data)
354
+ end
355
+
356
+ # Compress data using native RAR compression
357
+ #
358
+ # @param data [String] Data to compress
359
+ # @param method [Integer] RAR compression method (default: METHOD_NORMAL)
360
+ # @return [String] Compressed data
361
+ def compress_data(data, method = METHOD_NORMAL)
362
+ input = StringIO.new(data)
363
+ output = StringIO.new
364
+
365
+ Compression::Dispatcher.compress(method, input, output, @options)
366
+
367
+ output.string
368
+ end
369
+
370
+ # Select appropriate compression method based on data
371
+ #
372
+ # @param data [String] Data to compress
373
+ # @return [Integer] RAR compression method code
374
+ def select_compression_method(data)
375
+ # Small files: use METHOD_STORE to avoid Huffman tree overhead (258 bytes)
376
+ return METHOD_STORE if data.size < 300
377
+
378
+ # User-specified compression level takes precedence
379
+ case @options[:compression]
380
+ when :store
381
+ METHOD_STORE
382
+ when :fastest
383
+ METHOD_FASTEST
384
+ when :fast
385
+ METHOD_FAST
386
+ when :normal
387
+ METHOD_NORMAL
388
+ when :good
389
+ METHOD_GOOD
390
+ when :best
391
+ METHOD_BEST
392
+ else
393
+ # Default based on compression level option if numeric
394
+ if @options[:level] == 9
395
+ METHOD_BEST # PPMd for maximum compression
396
+ else
397
+ METHOD_NORMAL # LZ77+Huffman default
398
+ end
399
+ end
400
+ end
401
+
402
+ # Get compression version needed to extract. WinRAR writes 20
403
+ # for stored files and 29 for every compressed method,
404
+ # including PPMd (method 0x35) — confirmed against libarchive
405
+ # RAR4 fixtures created by the official tool.
406
+ #
407
+ # @param method [Integer] Compression method
408
+ # @return [Integer] Version code
409
+ def compression_version(method)
410
+ method == METHOD_STORE ? 20 : 29
411
+ end
412
+
413
+ # Test archive integrity by reading it back with the RAR
414
+ # reader and comparing every extracted entry to its source
415
+ #
416
+ # @return [Boolean] true if valid
417
+ def test_archive
418
+ return false unless File.exist?(@output_path)
419
+
420
+ reader = Reader.new(@output_path)
421
+ reader.open
422
+
423
+ Dir.mktmpdir("omnizip_rar_test") do |tmp|
424
+ @files.map { |f| f[:archive_path] || File.basename(f[:source]) }
425
+ .zip(@files.map { |f| f[:source] }).all? do |name, source|
426
+ dest = File.join(tmp, name)
427
+ reader.extract_entry(name, dest)
428
+ FileUtils.compare_file(source, dest)
429
+ end
430
+ end
431
+ rescue StandardError
432
+ false
433
+ end
434
+ end
435
+ end
436
+ end
437
+ end
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ # RAR archive format support
6
+ #
7
+ # - Formats::Rar::Reader — the primary parser, verified against
8
+ # real WinRAR archives: listing, directories, mtimes, and
9
+ # extraction (native STORE decode with stored-CRC verification;
10
+ # foreign compressed streams fall back to the unrar command
11
+ # after the CRC check rejects them)
12
+ # - Formats::Rar::Writer (RAR4) and Formats::Rar::Rar5::Writer —
13
+ # STORE output is unrar-verified; compressed methods produce
14
+ # Omnizip-internal streams (see the README interop table)
15
+ # - Formats::Rar3 / Formats::Rar5 — legacy interfaces, thin
16
+ # adapters over the primary reader and the RAR5 writer
17
+ # - Multi-volume archives, encryption (RAR5), recovery records
18
+ module Rar
19
+ # Nested classes - autoloaded
20
+ autoload :Constants, "omnizip/formats/rar/constants"
21
+ autoload :Header, "omnizip/formats/rar/header"
22
+ autoload :BlockParser, "omnizip/formats/rar/block_parser"
23
+ autoload :Decompressor, "omnizip/formats/rar/decompressor"
24
+ autoload :VolumeManager, "omnizip/formats/rar/volume_manager"
25
+ autoload :RecoveryRecord, "omnizip/formats/rar/recovery_record"
26
+ autoload :ParityHandler, "omnizip/formats/rar/parity_handler"
27
+ autoload :ArchiveVerifier, "omnizip/formats/rar/archive_verifier"
28
+ autoload :ArchiveRepairer, "omnizip/formats/rar/archive_repairer"
29
+ autoload :Reader, "omnizip/formats/rar/reader"
30
+ autoload :Writer, "omnizip/formats/rar/writer"
31
+ autoload :RarFormatBase, "omnizip/formats/rar/rar_format_base"
32
+ autoload :ExternalWriter, "omnizip/formats/rar/external_writer"
33
+ autoload :LicenseValidator, "omnizip/formats/rar/license_validator"
34
+ # Models
35
+ autoload :Models, "omnizip/formats/rar/models"
36
+ # RAR5 support
37
+ module Rar5
38
+ autoload :VINT, "omnizip/formats/rar/rar5/vint"
39
+ autoload :CRC32, "omnizip/formats/rar/rar5/crc32"
40
+ autoload :Header, "omnizip/formats/rar/rar5/header"
41
+ # MainHeader/FileHeader live in header.rb directly under Rar5;
42
+ # without their own autoload entries, referencing them only
43
+ # works if something else loaded the file first.
44
+ autoload :MainHeader, "omnizip/formats/rar/rar5/header"
45
+ autoload :FileHeader, "omnizip/formats/rar/rar5/header"
46
+ autoload :Writer, "omnizip/formats/rar/rar5/writer"
47
+ # RAR5 compression
48
+ module Compression
49
+ autoload :Store, "omnizip/formats/rar/rar5/compression/store"
50
+ autoload :Lzma, "omnizip/formats/rar/rar5/compression/lzma"
51
+ autoload :Lzss, "omnizip/formats/rar/rar5/compression/lzss"
52
+ end
53
+
54
+ # RAR5 multi-volume
55
+ module MultiVolume
56
+ autoload :VolumeManager,
57
+ "omnizip/formats/rar/rar5/multi_volume/volume_manager"
58
+ autoload :VolumeWriter,
59
+ "omnizip/formats/rar/rar5/multi_volume/volume_writer"
60
+ autoload :VolumeSplitter,
61
+ "omnizip/formats/rar/rar5/multi_volume/volume_splitter"
62
+ end
63
+
64
+ # RAR5 models
65
+ module Models
66
+ autoload :VolumeOptions,
67
+ "omnizip/formats/rar/rar5/models/volume_options"
68
+ autoload :SolidOptions,
69
+ "omnizip/formats/rar/rar5/models/solid_options"
70
+ autoload :EncryptionOptions,
71
+ "omnizip/formats/rar/rar5/models/encryption_options"
72
+ autoload :RecoveryOptions,
73
+ "omnizip/formats/rar/rar5/models/recovery_options"
74
+ end
75
+
76
+ # RAR5 solid compression
77
+ module Solid
78
+ autoload :SolidManager, "omnizip/formats/rar/rar5/solid/solid_manager"
79
+ autoload :SolidEncoder, "omnizip/formats/rar/rar5/solid/solid_encoder"
80
+ autoload :SolidStream, "omnizip/formats/rar/rar5/solid/solid_stream"
81
+ end
82
+
83
+ # RAR5 encryption
84
+ module Encryption
85
+ autoload :Aes256Cbc, "omnizip/formats/rar/rar5/encryption/aes256_cbc"
86
+ autoload :EncryptionHeader,
87
+ "omnizip/formats/rar/rar5/encryption/encryption_header"
88
+ autoload :KeyDerivation,
89
+ "omnizip/formats/rar/rar5/encryption/key_derivation"
90
+ autoload :EncryptionManager,
91
+ "omnizip/formats/rar/rar5/encryption/encryption_manager"
92
+ end
93
+
94
+ # RAR5 compression
95
+ module Compression
96
+ autoload :Store, "omnizip/formats/rar/rar5/compression/store"
97
+ autoload :Lzma, "omnizip/formats/rar/rar5/compression/lzma"
98
+ autoload :Lzss, "omnizip/formats/rar/rar5/compression/lzss"
99
+ end
100
+ end
101
+
102
+ # Compression layer
103
+ module Compression
104
+ autoload :BitStream, "omnizip/formats/rar/compression/bit_stream"
105
+ autoload :Dispatcher, "omnizip/formats/rar/compression/dispatcher"
106
+ module PPMd
107
+ autoload :Context, "omnizip/formats/rar/compression/ppmd/context"
108
+ autoload :Decoder, "omnizip/formats/rar/compression/ppmd/decoder"
109
+ autoload :Encoder, "omnizip/formats/rar/compression/ppmd/encoder"
110
+ end
111
+
112
+ module LZ77Huffman
113
+ autoload :SlidingWindow,
114
+ "omnizip/formats/rar/compression/lz77_huffman/sliding_window"
115
+ autoload :HuffmanCoder,
116
+ "omnizip/formats/rar/compression/lz77_huffman/huffman_coder"
117
+ autoload :HuffmanBuilder,
118
+ "omnizip/formats/rar/compression/lz77_huffman/huffman_builder"
119
+ autoload :MatchFinder,
120
+ "omnizip/formats/rar/compression/lz77_huffman/match_finder"
121
+ autoload :Decoder,
122
+ "omnizip/formats/rar/compression/lz77_huffman/decoder"
123
+ autoload :Encoder,
124
+ "omnizip/formats/rar/compression/lz77_huffman/encoder"
125
+ end
126
+ end
127
+
128
+ class << self
129
+ # Create a RAR archive, yielding the writer for entries.
130
+ # RAR5 is the default; pass version: 4 for the RAR4 writer.
131
+ # RAR5-only options (solid, multi-volume, password, recovery)
132
+ # are ignored for RAR4 — its writer warns about the
133
+ # unimplemented ones and raises for passwords.
134
+ #
135
+ # @param path [String] Output archive path
136
+ # @param options [Hash] Writer options
137
+ # @return [String, Array<String>] Path(s) of the created
138
+ # archive (a volume set returns every volume)
139
+ def create(path, options = {})
140
+ version = options.fetch(:version, 5)
141
+ writer = if version == 4
142
+ Writer.new(path, options)
143
+ else
144
+ Rar5::Writer.new(path, rar5_options(options))
145
+ end
146
+ yield writer if block_given?
147
+ writer.write
148
+ end
149
+
150
+ # Check if RAR extraction is available
151
+ #
152
+ # @return [Boolean] true if unrar available
153
+ def available?
154
+ Decompressor.available?
155
+ end
156
+
157
+ # Get decompressor information
158
+ #
159
+ # @return [Hash] Decompressor type and version
160
+ def decompressor_info
161
+ Decompressor.info
162
+ end
163
+
164
+ # Verify archive integrity
165
+ #
166
+ # @param archive_path [String] Path to RAR archive
167
+ # @return [ArchiveVerifier::VerificationResult] Verification result
168
+ def verify(archive_path, use_recovery: true)
169
+ ArchiveVerifier.new(archive_path).verify(use_recovery: use_recovery)
170
+ end
171
+
172
+ # Repair corrupted archive
173
+ #
174
+ # @param archive_path [String] Path to corrupted RAR archive
175
+ # @param output_path [String] Path for repaired archive
176
+ # @return [ArchiveRepairer::RepairResult] Repair result
177
+ def repair(archive_path, output_path, options = {})
178
+ ArchiveRepairer.new.repair(archive_path, output_path, options)
179
+ end
180
+
181
+ private
182
+
183
+ # Writer keywords the RAR5 writer understands
184
+ def rar5_options(options)
185
+ options.slice(:compression, :level, :solid, :multi_volume,
186
+ :volume_size, :volume_naming, :password,
187
+ :kdf_iterations, :recovery, :recovery_percent,
188
+ :include_mtime, :include_crc32, :dict_size)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+
5
+ module Omnizip
6
+ module Formats
7
+ module Rar3
8
+ # RAR v3 compressor
9
+ #
10
+ # Compresses data using RAR v3 compression algorithms.
11
+ # This implementation uses DEFLATE as a compatible fallback
12
+ # for demonstration purposes. Full RAR compression requires
13
+ # proprietary algorithms.
14
+ #
15
+ # @example Compressing data
16
+ # compressor = Rar3::Compressor.new
17
+ # compressed = compressor.compress("Hello, World!", method: :normal)
18
+ class Compressor < Rar::RarFormatBase
19
+ # Initialize a RAR v3 compressor
20
+ def initialize
21
+ super("rar3")
22
+ end
23
+
24
+ # Compress data using RAR v3 methods
25
+ #
26
+ # @param data [String] The data to compress
27
+ # @param method [Symbol] The compression method
28
+ # @param options [Hash] Compression options
29
+ # @return [String] The compressed data
30
+ def compress(data, method: :normal, **_options)
31
+ case method
32
+ when :store
33
+ compress_store(data)
34
+ when :fastest
35
+ compress_deflate(data, level: Zlib::BEST_SPEED)
36
+ when :fast
37
+ compress_deflate(data, level: 3)
38
+ when :normal
39
+ compress_deflate(data, level: Zlib::DEFAULT_COMPRESSION)
40
+ when :good
41
+ compress_deflate(data, level: 7)
42
+ when :best
43
+ compress_deflate(data, level: Zlib::BEST_COMPRESSION)
44
+ else
45
+ raise FormatError,
46
+ "Unsupported compression method: #{method}"
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ # Store data without compression
53
+ #
54
+ # @param data [String] The data to store
55
+ # @return [String] The uncompressed data
56
+ def compress_store(data)
57
+ data
58
+ end
59
+
60
+ # Compress using DEFLATE (compatible fallback)
61
+ #
62
+ # @param data [String] The data to compress
63
+ # @param level [Integer] The compression level
64
+ # @return [String] The compressed data
65
+ def compress_deflate(data, level:)
66
+ Zlib::Deflate.deflate(data, level)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end