1use std::fmt::Debug;
2
3#[cfg(feature = "ppmd")]
4use ppmd_rust::{PPMD7_MAX_MEM_SIZE, PPMD7_MAX_ORDER, PPMD7_MIN_MEM_SIZE, PPMD7_MIN_ORDER};
5
6#[cfg(feature = "compress")]
7use crate::EncoderConfiguration;
8#[cfg(feature = "aes256")]
9use crate::Password;
10
11#[cfg(feature = "compress")]
12#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
13#[derive(Debug, Clone)]
14pub struct LZMAOptions(pub(crate) lzma_rust2::LZMAOptions);
16
17impl Default for LZMAOptions {
18 fn default() -> Self {
19 Self(lzma_rust2::LZMAOptions::with_preset(6))
20 }
21}
22
23#[cfg(feature = "compress")]
24impl LZMAOptions {
25 pub fn from_level(level: u32) -> Self {
30 Self(lzma_rust2::LZMAOptions::with_preset(level))
31 }
32}
33
34#[cfg(feature = "compress")]
35#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
36#[derive(Debug, Clone)]
37pub struct LZMA2Options {
39 pub(crate) options: lzma_rust2::LZMAOptions,
40 pub(crate) threads: u32,
41 pub(crate) stream_size: Option<u64>,
42}
43
44impl Default for LZMA2Options {
45 fn default() -> Self {
46 Self {
47 options: lzma_rust2::LZMAOptions::with_preset(6),
48 threads: 1,
49 stream_size: None,
50 }
51 }
52}
53
54#[cfg(feature = "compress")]
55impl LZMA2Options {
56 pub fn from_level(level: u32) -> Self {
62 Self {
63 options: lzma_rust2::LZMAOptions::with_preset(level),
64 threads: 1,
65 stream_size: None,
66 }
67 }
68
69 pub fn from_level_mt(level: u32, threads: u32, stream_size: u64) -> Self {
80 Self {
81 options: lzma_rust2::LZMAOptions::with_preset(level),
82 threads,
83 stream_size: Some(stream_size.max(lzma_rust2::MIN_STREAM_SIZE)),
84 }
85 }
86
87 pub fn set_dictionary_size(&mut self, dict_size: u32) {
91 self.options.dict_size =
92 dict_size.clamp(lzma_rust2::DICT_SIZE_MIN, lzma_rust2::DICT_SIZE_MAX);
93 }
94}
95
96#[cfg(feature = "bzip2")]
97#[cfg_attr(docsrs, doc(cfg(feature = "bzip2")))]
98#[derive(Debug, Copy, Clone)]
99pub struct Bzip2Options(pub(crate) u32);
101
102#[cfg(feature = "bzip2")]
103impl Bzip2Options {
104 pub const fn from_level(level: u32) -> Self {
109 Self(level)
110 }
111}
112
113#[cfg(feature = "bzip2")]
114impl Default for Bzip2Options {
115 fn default() -> Self {
116 Self(6)
117 }
118}
119
120#[cfg(any(feature = "brotli", feature = "lz4"))]
121const MINIMAL_SKIPPABLE_FRAME_SIZE: u32 = 64 * 1024;
122#[cfg(feature = "brotli")]
123const DEFAULT_SKIPPABLE_FRAME_SIZE: u32 = 128 * 1024;
124
125#[cfg(feature = "brotli")]
126#[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
127#[derive(Debug, Copy, Clone)]
128pub struct BrotliOptions {
130 pub(crate) quality: u32,
131 pub(crate) window: u32,
132 pub(crate) skippable_frame_size: u32,
133}
134
135#[cfg(feature = "brotli")]
136impl BrotliOptions {
137 pub const fn from_quality_window(quality: u32, window: u32) -> Self {
143 let quality = if quality > 11 { 11 } else { quality };
144 let window = if window > 24 { 24 } else { window };
145 Self {
146 quality,
147 window,
148 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
149 }
150 }
151
152 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
160 if skippable_frame_size == 0 {
161 self.skippable_frame_size = 0;
162 } else {
163 self.skippable_frame_size =
164 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
165 }
166
167 self
168 }
169}
170
171#[cfg(feature = "brotli")]
172impl Default for BrotliOptions {
173 fn default() -> Self {
174 Self {
175 quality: 11,
176 window: 22,
177 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
178 }
179 }
180}
181
182#[cfg(feature = "compress")]
183#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
184#[derive(Debug, Copy, Clone)]
185pub struct DeltaOptions(pub(crate) u32);
187
188#[cfg(feature = "compress")]
189impl DeltaOptions {
190 pub const fn from_distance(distance: u32) -> Self {
195 let distance = if distance == 0 {
196 1
197 } else if distance > 256 {
198 256
199 } else {
200 distance
201 };
202 Self(distance)
203 }
204}
205
206#[cfg(feature = "compress")]
207impl Default for DeltaOptions {
208 fn default() -> Self {
209 Self(1)
210 }
211}
212
213#[cfg(feature = "deflate")]
214#[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
215#[derive(Debug, Copy, Clone)]
216pub struct DeflateOptions(pub(crate) u32);
218
219#[cfg(feature = "deflate")]
220impl DeflateOptions {
221 pub const fn from_level(level: u32) -> Self {
226 let level = if level > 9 { 9 } else { level };
227 Self(level)
228 }
229}
230
231#[cfg(feature = "deflate")]
232impl Default for DeflateOptions {
233 fn default() -> Self {
234 Self(6)
235 }
236}
237
238#[cfg(feature = "lz4")]
239#[cfg_attr(docsrs, doc(cfg(feature = "lz4")))]
240#[derive(Debug, Copy, Clone, Default)]
241pub struct LZ4Options {
243 pub(crate) skippable_frame_size: u32,
244}
245
246#[cfg(feature = "lz4")]
247impl LZ4Options {
248 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
259 if skippable_frame_size == 0 {
260 self.skippable_frame_size = 0;
261 } else {
262 self.skippable_frame_size =
263 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
264 }
265
266 self
267 }
268}
269
270#[cfg(feature = "ppmd")]
271#[cfg_attr(docsrs, doc(cfg(feature = "ppmd")))]
272#[derive(Debug, Copy, Clone)]
273pub struct PPMDOptions {
275 pub(crate) order: u32,
276 pub(crate) memory_size: u32,
277}
278
279#[cfg(feature = "ppmd")]
280impl PPMDOptions {
281 pub const fn from_level(level: u32) -> Self {
286 const ORDERS: [u32; 10] = [3, 4, 4, 5, 5, 6, 8, 16, 24, 32];
287
288 let level = if level > 9 { 9 } else { level };
289 let order = ORDERS[level as usize];
290 let memory_size = 1 << (level + 19);
291
292 Self { order, memory_size }
293 }
294
295 pub const fn from_order_memory_size(order: u32, memory_size: u32) -> Self {
301 let order = if order > PPMD7_MAX_ORDER {
302 PPMD7_MAX_ORDER
303 } else if order < PPMD7_MIN_ORDER {
304 PPMD7_MIN_ORDER
305 } else {
306 order
307 };
308 let memory_size = if memory_size > PPMD7_MAX_MEM_SIZE {
309 PPMD7_MAX_MEM_SIZE
310 } else if memory_size < PPMD7_MIN_MEM_SIZE {
311 PPMD7_MIN_MEM_SIZE
312 } else {
313 memory_size
314 };
315 Self { order, memory_size }
316 }
317}
318
319#[cfg(feature = "ppmd")]
320impl Default for PPMDOptions {
321 fn default() -> Self {
322 Self::from_level(6)
323 }
324}
325
326#[cfg(feature = "zstd")]
327#[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
328#[derive(Debug, Copy, Clone)]
329pub struct ZStandardOptions(pub(crate) u32);
331
332#[cfg(feature = "zstd")]
333impl ZStandardOptions {
334 pub const fn from_level(level: u32) -> Self {
339 let level = if level > 22 { 22 } else { level };
340 Self(level)
341 }
342}
343
344#[cfg(feature = "zstd")]
345impl Default for ZStandardOptions {
346 fn default() -> Self {
347 Self(3)
348 }
349}
350
351#[cfg_attr(docsrs, doc(cfg(feature = "aes256")))]
352#[cfg(feature = "aes256")]
353#[derive(Debug, Clone)]
354pub struct AesEncoderOptions {
356 pub password: Password,
358 pub iv: [u8; 16],
360 pub salt: [u8; 16],
362 pub num_cycles_power: u8,
364}
365
366#[cfg(feature = "aes256")]
367impl AesEncoderOptions {
368 pub fn new(password: Password) -> Self {
375 let mut iv = [0; 16];
376 getrandom::fill(&mut iv).expect("Can't generate IV");
377
378 let mut salt = [0; 16];
379 getrandom::fill(&mut salt).expect("Can't generate salt");
380
381 Self {
382 password,
383 iv,
384 salt,
385 num_cycles_power: 8,
386 }
387 }
388
389 pub(crate) fn properties(&self) -> [u8; 34] {
390 let mut props = [0u8; 34];
391 self.write_properties(&mut props);
392 props
393 }
394
395 #[inline]
396 pub(crate) fn write_properties(&self, props: &mut [u8]) {
397 assert!(props.len() >= 34);
398 props[0] = (self.num_cycles_power & 0x3F) | 0xC0;
399 props[1] = 0xFF;
400 props[2..18].copy_from_slice(&self.salt);
401 props[18..34].copy_from_slice(&self.iv);
402 }
403}
404
405#[derive(Debug, Clone)]
407pub enum EncoderOptions {
408 #[cfg(feature = "compress")]
409 #[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
410 Delta(DeltaOptions),
412 #[cfg(feature = "compress")]
413 #[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
414 LZMA(LZMAOptions),
416 #[cfg(feature = "compress")]
417 #[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
418 LZMA2(LZMA2Options),
420 #[cfg(feature = "brotli")]
421 #[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
422 BROTLI(BrotliOptions),
424 #[cfg(feature = "bzip2")]
425 #[cfg_attr(docsrs, doc(cfg(feature = "bzip2")))]
426 BZIP2(Bzip2Options),
428 #[cfg(feature = "deflate")]
429 #[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
430 DEFLATE(DeflateOptions),
432 #[cfg(feature = "lz4")]
433 #[cfg_attr(docsrs, doc(cfg(feature = "lz4")))]
434 LZ4(LZ4Options),
436 #[cfg(feature = "ppmd")]
437 #[cfg_attr(docsrs, doc(cfg(feature = "ppmd")))]
438 PPMD(PPMDOptions),
440 #[cfg(feature = "zstd")]
441 #[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
442 ZSTD(ZStandardOptions),
444 #[cfg(feature = "aes256")]
445 #[cfg_attr(docsrs, doc(cfg(feature = "aes256")))]
446 Aes(AesEncoderOptions),
448}
449
450#[cfg(feature = "aes256")]
451impl From<AesEncoderOptions> for EncoderOptions {
452 fn from(value: AesEncoderOptions) -> Self {
453 Self::Aes(value)
454 }
455}
456
457#[cfg(all(feature = "aes256", feature = "compress"))]
458impl From<AesEncoderOptions> for EncoderConfiguration {
459 fn from(value: AesEncoderOptions) -> Self {
460 Self::new(crate::EncoderMethod::AES256SHA256).with_options(EncoderOptions::Aes(value))
461 }
462}
463
464#[cfg(feature = "compress")]
465impl From<DeltaOptions> for EncoderConfiguration {
466 fn from(options: DeltaOptions) -> Self {
467 Self::new(crate::EncoderMethod::DELTA_FILTER).with_options(EncoderOptions::Delta(options))
468 }
469}
470
471#[cfg(feature = "compress")]
472impl From<LZMA2Options> for EncoderConfiguration {
473 fn from(options: LZMA2Options) -> Self {
474 Self::new(crate::EncoderMethod::LZMA2).with_options(EncoderOptions::LZMA2(options))
475 }
476}
477
478#[cfg(feature = "bzip2")]
479impl From<Bzip2Options> for EncoderConfiguration {
480 fn from(options: Bzip2Options) -> Self {
481 Self::new(crate::EncoderMethod::BZIP2).with_options(EncoderOptions::BZIP2(options))
482 }
483}
484
485#[cfg(feature = "brotli")]
486impl From<BrotliOptions> for EncoderConfiguration {
487 fn from(options: BrotliOptions) -> Self {
488 Self::new(crate::EncoderMethod::BROTLI).with_options(EncoderOptions::BROTLI(options))
489 }
490}
491
492#[cfg(feature = "deflate")]
493impl From<DeflateOptions> for EncoderConfiguration {
494 fn from(options: DeflateOptions) -> Self {
495 Self::new(crate::EncoderMethod::DEFLATE).with_options(EncoderOptions::DEFLATE(options))
496 }
497}
498
499#[cfg(feature = "lz4")]
500impl From<LZ4Options> for EncoderConfiguration {
501 fn from(options: LZ4Options) -> Self {
502 Self::new(crate::EncoderMethod::LZ4).with_options(EncoderOptions::LZ4(options))
503 }
504}
505
506#[cfg(feature = "ppmd")]
507impl From<PPMDOptions> for EncoderConfiguration {
508 fn from(options: PPMDOptions) -> Self {
509 Self::new(crate::EncoderMethod::PPMD).with_options(EncoderOptions::PPMD(options))
510 }
511}
512
513#[cfg(feature = "zstd")]
514impl From<ZStandardOptions> for EncoderConfiguration {
515 fn from(options: ZStandardOptions) -> Self {
516 Self::new(crate::EncoderMethod::ZSTD).with_options(EncoderOptions::ZSTD(options))
517 }
518}
519
520#[cfg(feature = "compress")]
521impl From<DeltaOptions> for EncoderOptions {
522 fn from(o: DeltaOptions) -> Self {
523 Self::Delta(o)
524 }
525}
526
527#[cfg(feature = "compress")]
528impl From<LZMA2Options> for EncoderOptions {
529 fn from(o: LZMA2Options) -> Self {
530 Self::LZMA2(o)
531 }
532}
533
534#[cfg(feature = "bzip2")]
535impl From<Bzip2Options> for EncoderOptions {
536 fn from(o: Bzip2Options) -> Self {
537 Self::BZIP2(o)
538 }
539}
540
541#[cfg(feature = "brotli")]
542impl From<BrotliOptions> for EncoderOptions {
543 fn from(o: BrotliOptions) -> Self {
544 Self::BROTLI(o)
545 }
546}
547
548#[cfg(feature = "deflate")]
549impl From<DeflateOptions> for EncoderOptions {
550 fn from(o: DeflateOptions) -> Self {
551 Self::DEFLATE(o)
552 }
553}
554
555#[cfg(feature = "lz4")]
556impl From<LZ4Options> for EncoderOptions {
557 fn from(o: LZ4Options) -> Self {
558 Self::LZ4(o)
559 }
560}
561
562#[cfg(feature = "ppmd")]
563impl From<PPMDOptions> for EncoderOptions {
564 fn from(o: PPMDOptions) -> Self {
565 Self::PPMD(o)
566 }
567}
568
569#[cfg(feature = "zstd")]
570impl From<ZStandardOptions> for EncoderOptions {
571 fn from(o: ZStandardOptions) -> Self {
572 Self::ZSTD(o)
573 }
574}
575
576impl EncoderOptions {
577 pub fn get_lzma_dict_size(&self) -> u32 {
581 match self {
582 #[cfg(feature = "compress")]
583 EncoderOptions::LZMA(o) => o.0.dict_size,
584 #[cfg(feature = "compress")]
585 EncoderOptions::LZMA2(o) => o.options.dict_size,
586 #[allow(unused)]
587 _ => 0,
588 }
589 }
590}