async_sevenz/
encoder_options.rs1use 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) skippable_frame_size: u32,
125}
126
127#[cfg(feature = "brotli")]
128impl BrotliOptions {
129 pub const fn from_quality(quality: u32) -> Self {
134 let quality = if quality > 11 { 11 } else { quality };
135 Self {
136 quality,
137 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
138 }
139 }
140
141 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
149 if skippable_frame_size == 0 {
150 self.skippable_frame_size = 0;
151 } else {
152 self.skippable_frame_size =
153 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
154 }
155
156 self
157 }
158}
159
160#[cfg(feature = "brotli")]
161impl Default for BrotliOptions {
162 fn default() -> Self {
163 Self {
164 quality: 11,
165 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
166 }
167 }
168}
169
170#[cfg(feature = "compress")]
171#[derive(Debug, Copy, Clone)]
172pub struct DeltaOptions(pub(crate) u32);
174
175#[cfg(feature = "compress")]
176impl DeltaOptions {
177 pub const fn from_distance(distance: u32) -> Self {
182 let distance = if distance == 0 {
183 1
184 } else if distance > 256 {
185 256
186 } else {
187 distance
188 };
189 Self(distance)
190 }
191}
192
193#[cfg(feature = "compress")]
194impl Default for DeltaOptions {
195 fn default() -> Self {
196 Self(1)
197 }
198}
199
200#[cfg(feature = "deflate")]
201#[derive(Debug, Copy, Clone)]
202pub struct DeflateOptions(pub(crate) u32);
204
205#[cfg(feature = "deflate")]
206impl DeflateOptions {
207 pub const fn from_level(level: u32) -> Self {
212 let level = if level > 9 { 9 } else { level };
213 Self(level)
214 }
215}
216
217#[cfg(feature = "deflate")]
218impl Default for DeflateOptions {
219 fn default() -> Self {
220 Self(6)
221 }
222}
223
224#[cfg(feature = "lz4")]
225#[derive(Debug, Copy, Clone, Default)]
226pub struct Lz4Options {
228 pub(crate) skippable_frame_size: u32,
229}
230
231#[cfg(feature = "lz4")]
232impl Lz4Options {
233 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
244 if skippable_frame_size == 0 {
245 self.skippable_frame_size = 0;
246 } else {
247 self.skippable_frame_size =
248 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
249 }
250
251 self
252 }
253}
254
255#[cfg(feature = "ppmd")]
256#[derive(Debug, Copy, Clone)]
257pub struct PpmdOptions {
259 pub(crate) order: u32,
260 pub(crate) memory_size: u32,
261}
262
263#[cfg(feature = "ppmd")]
264impl PpmdOptions {
265 pub const fn from_level(level: u32) -> Self {
270 const ORDERS: [u32; 10] = [3, 4, 4, 5, 5, 6, 8, 16, 24, 32];
271
272 let level = if level > 9 { 9 } else { level };
273 let order = ORDERS[level as usize];
274 let memory_size = 1 << (level + 19);
275
276 Self { order, memory_size }
277 }
278
279 pub const fn from_order_memory_size(order: u32, memory_size: u32) -> Self {
285 let order = if order > PPMD7_MAX_ORDER {
286 PPMD7_MAX_ORDER
287 } else if order < PPMD7_MIN_ORDER {
288 PPMD7_MIN_ORDER
289 } else {
290 order
291 };
292 let memory_size = if memory_size > PPMD7_MAX_MEM_SIZE {
293 PPMD7_MAX_MEM_SIZE
294 } else if memory_size < PPMD7_MIN_MEM_SIZE {
295 PPMD7_MIN_MEM_SIZE
296 } else {
297 memory_size
298 };
299 Self { order, memory_size }
300 }
301}
302
303#[cfg(feature = "ppmd")]
304impl Default for PpmdOptions {
305 fn default() -> Self {
306 Self::from_level(6)
307 }
308}
309
310#[cfg(feature = "zstd")]
311#[derive(Debug, Copy, Clone)]
312pub struct ZstandardOptions(pub(crate) u32);
314
315#[cfg(feature = "zstd")]
316impl ZstandardOptions {
317 pub const fn from_level(level: u32) -> Self {
322 let level = if level > 22 { 22 } else { level };
323 Self(level)
324 }
325}
326
327#[cfg(feature = "zstd")]
328impl Default for ZstandardOptions {
329 fn default() -> Self {
330 Self(3)
331 }
332}
333
334#[cfg(feature = "aes256")]
335#[derive(Debug, Clone)]
336pub struct AesEncoderOptions {
338 pub password: Password,
340 pub iv: [u8; 16],
342 pub salt: [u8; 16],
344 pub num_cycles_power: u8,
346}
347
348#[cfg(feature = "aes256")]
349impl AesEncoderOptions {
350 pub fn new(password: Password) -> Self {
357 let mut iv = [0; 16];
358 getrandom::fill(&mut iv).expect("Can't generate IV");
359
360 let mut salt = [0; 16];
361 getrandom::fill(&mut salt).expect("Can't generate salt");
362
363 Self {
364 password,
365 iv,
366 salt,
367 num_cycles_power: 8,
368 }
369 }
370
371 pub(crate) fn properties(&self) -> [u8; 34] {
372 let mut props = [0u8; 34];
373 self.write_properties(&mut props);
374 props
375 }
376
377 #[inline]
378 pub(crate) fn write_properties(&self, props: &mut [u8]) {
379 assert!(props.len() >= 34);
380 props[0] = (self.num_cycles_power & 0x3F) | 0xC0;
381 props[1] = 0xFF;
382 props[2..18].copy_from_slice(&self.salt);
383 props[18..34].copy_from_slice(&self.iv);
384 }
385}
386
387#[derive(Debug, Clone)]
389pub enum EncoderOptions {
390 #[cfg(feature = "compress")]
391 Delta(DeltaOptions),
393 #[cfg(feature = "compress")]
394 Lzma(LzmaOptions),
396 #[cfg(feature = "compress")]
397 Lzma2(Lzma2Options),
399 #[cfg(feature = "brotli")]
400 Brotli(BrotliOptions),
402 #[cfg(feature = "bzip2")]
403 Bzip2(Bzip2Options),
405 #[cfg(feature = "deflate")]
406 Deflate(DeflateOptions),
408 #[cfg(feature = "lz4")]
409 Lz4(Lz4Options),
411 #[cfg(feature = "ppmd")]
412 Ppmd(PpmdOptions),
414 #[cfg(feature = "zstd")]
415 Zstd(ZstandardOptions),
417 #[cfg(feature = "aes256")]
418 Aes(AesEncoderOptions),
420}
421
422#[cfg(feature = "aes256")]
423impl From<AesEncoderOptions> for EncoderOptions {
424 fn from(value: AesEncoderOptions) -> Self {
425 Self::Aes(value)
426 }
427}
428
429#[cfg(all(feature = "aes256", feature = "compress"))]
430impl From<AesEncoderOptions> for EncoderConfiguration {
431 fn from(value: AesEncoderOptions) -> Self {
432 Self::new(crate::EncoderMethod::AES256_SHA256).with_options(EncoderOptions::Aes(value))
433 }
434}
435
436#[cfg(feature = "compress")]
437impl From<DeltaOptions> for EncoderConfiguration {
438 fn from(options: DeltaOptions) -> Self {
439 Self::new(crate::EncoderMethod::DELTA_FILTER).with_options(EncoderOptions::Delta(options))
440 }
441}
442
443#[cfg(feature = "compress")]
444impl From<Lzma2Options> for EncoderConfiguration {
445 fn from(options: Lzma2Options) -> Self {
446 Self::new(crate::EncoderMethod::LZMA2).with_options(EncoderOptions::Lzma2(options))
447 }
448}
449
450#[cfg(feature = "bzip2")]
451impl From<Bzip2Options> for EncoderConfiguration {
452 fn from(options: Bzip2Options) -> Self {
453 Self::new(crate::EncoderMethod::BZIP2).with_options(EncoderOptions::Bzip2(options))
454 }
455}
456
457#[cfg(feature = "brotli")]
458impl From<BrotliOptions> for EncoderConfiguration {
459 fn from(options: BrotliOptions) -> Self {
460 Self::new(crate::EncoderMethod::BROTLI).with_options(EncoderOptions::Brotli(options))
461 }
462}
463
464#[cfg(feature = "deflate")]
465impl From<DeflateOptions> for EncoderConfiguration {
466 fn from(options: DeflateOptions) -> Self {
467 Self::new(crate::EncoderMethod::DEFLATE).with_options(EncoderOptions::Deflate(options))
468 }
469}
470
471#[cfg(feature = "lz4")]
472impl From<Lz4Options> for EncoderConfiguration {
473 fn from(options: Lz4Options) -> Self {
474 Self::new(crate::EncoderMethod::LZ4).with_options(EncoderOptions::Lz4(options))
475 }
476}
477
478#[cfg(feature = "ppmd")]
479impl From<PpmdOptions> for EncoderConfiguration {
480 fn from(options: PpmdOptions) -> Self {
481 Self::new(crate::EncoderMethod::PPMD).with_options(EncoderOptions::Ppmd(options))
482 }
483}
484
485#[cfg(feature = "zstd")]
486impl From<ZstandardOptions> for EncoderConfiguration {
487 fn from(options: ZstandardOptions) -> Self {
488 Self::new(crate::EncoderMethod::ZSTD).with_options(EncoderOptions::Zstd(options))
489 }
490}
491
492#[cfg(feature = "compress")]
493impl From<DeltaOptions> for EncoderOptions {
494 fn from(o: DeltaOptions) -> Self {
495 Self::Delta(o)
496 }
497}
498
499#[cfg(feature = "compress")]
500impl From<Lzma2Options> for EncoderOptions {
501 fn from(o: Lzma2Options) -> Self {
502 Self::Lzma2(o)
503 }
504}
505
506#[cfg(feature = "bzip2")]
507impl From<Bzip2Options> for EncoderOptions {
508 fn from(o: Bzip2Options) -> Self {
509 Self::Bzip2(o)
510 }
511}
512
513#[cfg(feature = "brotli")]
514impl From<BrotliOptions> for EncoderOptions {
515 fn from(o: BrotliOptions) -> Self {
516 Self::Brotli(o)
517 }
518}
519
520#[cfg(feature = "deflate")]
521impl From<DeflateOptions> for EncoderOptions {
522 fn from(o: DeflateOptions) -> Self {
523 Self::Deflate(o)
524 }
525}
526
527#[cfg(feature = "lz4")]
528impl From<Lz4Options> for EncoderOptions {
529 fn from(o: Lz4Options) -> Self {
530 Self::Lz4(o)
531 }
532}
533
534#[cfg(feature = "ppmd")]
535impl From<PpmdOptions> for EncoderOptions {
536 fn from(o: PpmdOptions) -> Self {
537 Self::Ppmd(o)
538 }
539}
540
541#[cfg(feature = "zstd")]
542impl From<ZstandardOptions> for EncoderOptions {
543 fn from(o: ZstandardOptions) -> Self {
544 Self::Zstd(o)
545 }
546}
547
548impl EncoderOptions {
549 pub fn get_lzma_dict_size(&self) -> u32 {
553 match self {
554 #[cfg(feature = "compress")]
555 EncoderOptions::Lzma(o) => o.0.dict_size,
556 #[cfg(feature = "compress")]
557 EncoderOptions::Lzma2(o) => o.options.lzma_options.dict_size,
558 _ => 0,
559 }
560 }
561}