1use std::{fmt::Debug, num::NonZeroU64};
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#[derive(Debug, Clone)]
13pub struct LzmaOptions(pub(crate) lzma_rust2::LzmaOptions);
15
16impl Default for LzmaOptions {
17 fn default() -> Self {
18 Self(lzma_rust2::LzmaOptions::with_preset(6))
19 }
20}
21
22#[cfg(feature = "compress")]
23impl LzmaOptions {
24 pub fn from_level(level: u32) -> Self {
29 Self(lzma_rust2::LzmaOptions::with_preset(level))
30 }
31}
32
33#[cfg(feature = "compress")]
34#[derive(Debug, Clone)]
35pub struct Lzma2Options {
37 pub(crate) options: lzma_rust2::Lzma2Options,
38 pub(crate) threads: u32,
39}
40
41impl Default for Lzma2Options {
42 fn default() -> Self {
43 Self {
44 options: lzma_rust2::Lzma2Options::with_preset(6),
45 threads: 1,
46 }
47 }
48}
49
50#[cfg(feature = "compress")]
51impl Lzma2Options {
52 pub fn from_level(level: u32) -> Self {
58 Self {
59 options: lzma_rust2::Lzma2Options::with_preset(level),
60 threads: 1,
61 }
62 }
63
64 pub fn from_level_mt(level: u32, threads: u32, chunk_size: u64) -> Self {
75 let mut options = lzma_rust2::Lzma2Options::with_preset(level);
76 options.set_chunk_size(NonZeroU64::new(
77 chunk_size.max(options.lzma_options.dict_size as u64),
78 ));
79 Self { options, threads }
80 }
81
82 pub fn set_dictionary_size(&mut self, dict_size: u32) {
86 self.options.lzma_options.dict_size =
87 dict_size.clamp(lzma_rust2::DICT_SIZE_MIN, lzma_rust2::DICT_SIZE_MAX);
88 }
89}
90
91#[cfg(feature = "bzip2")]
92#[derive(Debug, Copy, Clone)]
93pub struct Bzip2Options(pub(crate) u32);
95
96#[cfg(feature = "bzip2")]
97impl Bzip2Options {
98 pub const fn from_level(level: u32) -> Self {
103 Self(level)
104 }
105}
106
107#[cfg(feature = "bzip2")]
108impl Default for Bzip2Options {
109 fn default() -> Self {
110 Self(6)
111 }
112}
113
114#[cfg(any(feature = "brotli", feature = "lz4"))]
115const MINIMAL_SKIPPABLE_FRAME_SIZE: u32 = 64 * 1024;
116#[cfg(feature = "brotli")]
117const DEFAULT_SKIPPABLE_FRAME_SIZE: u32 = 128 * 1024;
118
119#[cfg(feature = "brotli")]
120#[derive(Debug, Copy, Clone)]
121pub struct BrotliOptions {
123 pub(crate) quality: u32,
124 pub(crate) window: u32,
125 pub(crate) skippable_frame_size: u32,
126}
127
128#[cfg(feature = "brotli")]
129impl BrotliOptions {
130 pub const fn from_quality_window(quality: u32, window: u32) -> Self {
136 let quality = if quality > 11 { 11 } else { quality };
137 let window = if window > 24 { 24 } else { window };
138 Self {
139 quality,
140 window,
141 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
142 }
143 }
144
145 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
153 if skippable_frame_size == 0 {
154 self.skippable_frame_size = 0;
155 } else {
156 self.skippable_frame_size =
157 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
158 }
159
160 self
161 }
162}
163
164#[cfg(feature = "brotli")]
165impl Default for BrotliOptions {
166 fn default() -> Self {
167 Self {
168 quality: 11,
169 window: 22,
170 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
171 }
172 }
173}
174
175#[cfg(feature = "compress")]
176#[derive(Debug, Copy, Clone)]
177pub struct DeltaOptions(pub(crate) u32);
179
180#[cfg(feature = "compress")]
181impl DeltaOptions {
182 pub const fn from_distance(distance: u32) -> Self {
187 let distance = if distance == 0 {
188 1
189 } else if distance > 256 {
190 256
191 } else {
192 distance
193 };
194 Self(distance)
195 }
196}
197
198#[cfg(feature = "compress")]
199impl Default for DeltaOptions {
200 fn default() -> Self {
201 Self(1)
202 }
203}
204
205#[cfg(feature = "deflate")]
206#[derive(Debug, Copy, Clone)]
207pub struct DeflateOptions(pub(crate) u32);
209
210#[cfg(feature = "deflate")]
211impl DeflateOptions {
212 pub const fn from_level(level: u32) -> Self {
217 let level = if level > 9 { 9 } else { level };
218 Self(level)
219 }
220}
221
222#[cfg(feature = "deflate")]
223impl Default for DeflateOptions {
224 fn default() -> Self {
225 Self(6)
226 }
227}
228
229#[cfg(feature = "lz4")]
230#[derive(Debug, Copy, Clone, Default)]
231pub struct Lz4Options {
233 pub(crate) skippable_frame_size: u32,
234}
235
236#[cfg(feature = "lz4")]
237impl Lz4Options {
238 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
249 if skippable_frame_size == 0 {
250 self.skippable_frame_size = 0;
251 } else {
252 self.skippable_frame_size =
253 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
254 }
255
256 self
257 }
258}
259
260#[cfg(feature = "ppmd")]
261#[derive(Debug, Copy, Clone)]
262pub struct PpmdOptions {
264 pub(crate) order: u32,
265 pub(crate) memory_size: u32,
266}
267
268#[cfg(feature = "ppmd")]
269impl PpmdOptions {
270 pub const fn from_level(level: u32) -> Self {
275 const ORDERS: [u32; 10] = [3, 4, 4, 5, 5, 6, 8, 16, 24, 32];
276
277 let level = if level > 9 { 9 } else { level };
278 let order = ORDERS[level as usize];
279 let memory_size = 1 << (level + 19);
280
281 Self { order, memory_size }
282 }
283
284 pub const fn from_order_memory_size(order: u32, memory_size: u32) -> Self {
290 let order = if order > PPMD7_MAX_ORDER {
291 PPMD7_MAX_ORDER
292 } else if order < PPMD7_MIN_ORDER {
293 PPMD7_MIN_ORDER
294 } else {
295 order
296 };
297 let memory_size = if memory_size > PPMD7_MAX_MEM_SIZE {
298 PPMD7_MAX_MEM_SIZE
299 } else if memory_size < PPMD7_MIN_MEM_SIZE {
300 PPMD7_MIN_MEM_SIZE
301 } else {
302 memory_size
303 };
304 Self { order, memory_size }
305 }
306}
307
308#[cfg(feature = "ppmd")]
309impl Default for PpmdOptions {
310 fn default() -> Self {
311 Self::from_level(6)
312 }
313}
314
315#[cfg(feature = "zstd")]
316#[derive(Debug, Copy, Clone)]
317pub struct ZstandardOptions(pub(crate) u32);
319
320#[cfg(feature = "zstd")]
321impl ZstandardOptions {
322 pub const fn from_level(level: u32) -> Self {
327 let level = if level > 22 { 22 } else { level };
328 Self(level)
329 }
330}
331
332#[cfg(feature = "zstd")]
333impl Default for ZstandardOptions {
334 fn default() -> Self {
335 Self(3)
336 }
337}
338
339#[cfg(feature = "aes256")]
340#[derive(Debug, Clone)]
341pub struct AesEncoderOptions {
343 pub password: Password,
345 pub iv: [u8; 16],
347 pub salt: [u8; 16],
349 pub num_cycles_power: u8,
351}
352
353#[cfg(feature = "aes256")]
354impl AesEncoderOptions {
355 pub fn new(password: Password) -> Self {
362 let mut iv = [0; 16];
363 getrandom::fill(&mut iv).expect("Can't generate IV");
364
365 let mut salt = [0; 16];
366 getrandom::fill(&mut salt).expect("Can't generate salt");
367
368 Self {
369 password,
370 iv,
371 salt,
372 num_cycles_power: 8,
373 }
374 }
375
376 pub(crate) fn properties(&self) -> [u8; 34] {
377 let mut props = [0u8; 34];
378 self.write_properties(&mut props);
379 props
380 }
381
382 #[inline]
383 pub(crate) fn write_properties(&self, props: &mut [u8]) {
384 assert!(props.len() >= 34);
385 props[0] = (self.num_cycles_power & 0x3F) | 0xC0;
386 props[1] = 0xFF;
387 props[2..18].copy_from_slice(&self.salt);
388 props[18..34].copy_from_slice(&self.iv);
389 }
390}
391
392#[derive(Debug, Clone)]
394pub enum EncoderOptions {
395 #[cfg(feature = "compress")]
396 Delta(DeltaOptions),
398 #[cfg(feature = "compress")]
399 Lzma(LzmaOptions),
401 #[cfg(feature = "compress")]
402 Lzma2(Lzma2Options),
404 #[cfg(feature = "brotli")]
405 Brotli(BrotliOptions),
407 #[cfg(feature = "bzip2")]
408 Bzip2(Bzip2Options),
410 #[cfg(feature = "deflate")]
411 Deflate(DeflateOptions),
413 #[cfg(feature = "lz4")]
414 Lz4(Lz4Options),
416 #[cfg(feature = "ppmd")]
417 Ppmd(PpmdOptions),
419 #[cfg(feature = "zstd")]
420 Zstd(ZstandardOptions),
422 #[cfg(feature = "aes256")]
423 Aes(AesEncoderOptions),
425}
426
427#[cfg(feature = "aes256")]
428impl From<AesEncoderOptions> for EncoderOptions {
429 fn from(value: AesEncoderOptions) -> Self {
430 Self::Aes(value)
431 }
432}
433
434#[cfg(all(feature = "aes256", feature = "compress"))]
435impl From<AesEncoderOptions> for EncoderConfiguration {
436 fn from(value: AesEncoderOptions) -> Self {
437 Self::new(crate::EncoderMethod::AES256_SHA256).with_options(EncoderOptions::Aes(value))
438 }
439}
440
441#[cfg(feature = "compress")]
442impl From<DeltaOptions> for EncoderConfiguration {
443 fn from(options: DeltaOptions) -> Self {
444 Self::new(crate::EncoderMethod::DELTA_FILTER).with_options(EncoderOptions::Delta(options))
445 }
446}
447
448#[cfg(feature = "compress")]
449impl From<Lzma2Options> for EncoderConfiguration {
450 fn from(options: Lzma2Options) -> Self {
451 Self::new(crate::EncoderMethod::LZMA2).with_options(EncoderOptions::Lzma2(options))
452 }
453}
454
455#[cfg(feature = "bzip2")]
456impl From<Bzip2Options> for EncoderConfiguration {
457 fn from(options: Bzip2Options) -> Self {
458 Self::new(crate::EncoderMethod::BZIP2).with_options(EncoderOptions::Bzip2(options))
459 }
460}
461
462#[cfg(feature = "brotli")]
463impl From<BrotliOptions> for EncoderConfiguration {
464 fn from(options: BrotliOptions) -> Self {
465 Self::new(crate::EncoderMethod::BROTLI).with_options(EncoderOptions::Brotli(options))
466 }
467}
468
469#[cfg(feature = "deflate")]
470impl From<DeflateOptions> for EncoderConfiguration {
471 fn from(options: DeflateOptions) -> Self {
472 Self::new(crate::EncoderMethod::DEFLATE).with_options(EncoderOptions::Deflate(options))
473 }
474}
475
476#[cfg(feature = "lz4")]
477impl From<Lz4Options> for EncoderConfiguration {
478 fn from(options: Lz4Options) -> Self {
479 Self::new(crate::EncoderMethod::LZ4).with_options(EncoderOptions::Lz4(options))
480 }
481}
482
483#[cfg(feature = "ppmd")]
484impl From<PpmdOptions> for EncoderConfiguration {
485 fn from(options: PpmdOptions) -> Self {
486 Self::new(crate::EncoderMethod::PPMD).with_options(EncoderOptions::Ppmd(options))
487 }
488}
489
490#[cfg(feature = "zstd")]
491impl From<ZstandardOptions> for EncoderConfiguration {
492 fn from(options: ZstandardOptions) -> Self {
493 Self::new(crate::EncoderMethod::ZSTD).with_options(EncoderOptions::Zstd(options))
494 }
495}
496
497#[cfg(feature = "compress")]
498impl From<DeltaOptions> for EncoderOptions {
499 fn from(o: DeltaOptions) -> Self {
500 Self::Delta(o)
501 }
502}
503
504#[cfg(feature = "compress")]
505impl From<Lzma2Options> for EncoderOptions {
506 fn from(o: Lzma2Options) -> Self {
507 Self::Lzma2(o)
508 }
509}
510
511#[cfg(feature = "bzip2")]
512impl From<Bzip2Options> for EncoderOptions {
513 fn from(o: Bzip2Options) -> Self {
514 Self::Bzip2(o)
515 }
516}
517
518#[cfg(feature = "brotli")]
519impl From<BrotliOptions> for EncoderOptions {
520 fn from(o: BrotliOptions) -> Self {
521 Self::Brotli(o)
522 }
523}
524
525#[cfg(feature = "deflate")]
526impl From<DeflateOptions> for EncoderOptions {
527 fn from(o: DeflateOptions) -> Self {
528 Self::Deflate(o)
529 }
530}
531
532#[cfg(feature = "lz4")]
533impl From<Lz4Options> for EncoderOptions {
534 fn from(o: Lz4Options) -> Self {
535 Self::Lz4(o)
536 }
537}
538
539#[cfg(feature = "ppmd")]
540impl From<PpmdOptions> for EncoderOptions {
541 fn from(o: PpmdOptions) -> Self {
542 Self::Ppmd(o)
543 }
544}
545
546#[cfg(feature = "zstd")]
547impl From<ZstandardOptions> for EncoderOptions {
548 fn from(o: ZstandardOptions) -> Self {
549 Self::Zstd(o)
550 }
551}
552
553impl EncoderOptions {
554 pub fn get_lzma_dict_size(&self) -> u32 {
558 match self {
559 #[cfg(feature = "compress")]
560 EncoderOptions::Lzma(o) => o.0.dict_size,
561 #[cfg(feature = "compress")]
562 EncoderOptions::Lzma2(o) => o.options.lzma_options.dict_size,
563 #[allow(unused)]
564 _ => 0,
565 }
566 }
567}