1use std::fmt::Debug;
2
3#[cfg(feature = "compress")]
4pub use lzma_rust2::LZMA2Options;
5#[cfg(feature = "ppmd")]
6use ppmd_rust::{PPMD7_MAX_MEM_SIZE, PPMD7_MAX_ORDER, PPMD7_MIN_MEM_SIZE, PPMD7_MIN_ORDER};
7
8#[cfg(feature = "compress")]
9use crate::EncoderConfiguration;
10#[cfg(feature = "aes256")]
11use crate::Password;
12
13#[cfg(feature = "bzip2")]
14#[cfg_attr(docsrs, doc(cfg(feature = "bzip2")))]
15#[derive(Debug, Copy, Clone)]
16pub struct Bzip2Options(pub(crate) u32);
17
18#[cfg(feature = "bzip2")]
19impl Bzip2Options {
20 pub const fn from_level(level: u32) -> Self {
21 Self(level)
22 }
23}
24
25#[cfg(feature = "bzip2")]
26impl Default for Bzip2Options {
27 fn default() -> Self {
28 Self(6)
29 }
30}
31
32#[cfg(any(feature = "brotli", feature = "lz4"))]
33const MINIMAL_SKIPPABLE_FRAME_SIZE: u32 = 64 * 1024;
34#[cfg(feature = "brotli")]
35const DEFAULT_SKIPPABLE_FRAME_SIZE: u32 = 128 * 1024;
36
37#[cfg(feature = "brotli")]
38#[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
39#[derive(Debug, Copy, Clone)]
40pub struct BrotliOptions {
41 pub(crate) quality: u32,
42 pub(crate) window: u32,
43 pub(crate) skippable_frame_size: u32,
44}
45
46#[cfg(feature = "brotli")]
47impl BrotliOptions {
48 pub const fn from_quality_window(quality: u32, window: u32) -> Self {
49 let quality = if quality > 11 { 11 } else { quality };
50 let window = if window > 24 { 24 } else { window };
51 Self {
52 quality,
53 window,
54 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
55 }
56 }
57
58 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
66 if skippable_frame_size == 0 {
67 self.skippable_frame_size = 0;
68 } else {
69 self.skippable_frame_size =
70 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
71 }
72
73 self
74 }
75}
76
77#[cfg(feature = "brotli")]
78impl Default for BrotliOptions {
79 fn default() -> Self {
80 Self {
81 quality: 11,
82 window: 22,
83 skippable_frame_size: DEFAULT_SKIPPABLE_FRAME_SIZE,
84 }
85 }
86}
87
88#[cfg(feature = "compress")]
89#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
90#[derive(Debug, Copy, Clone)]
91pub struct DeltaOptions(pub(crate) u32);
92
93#[cfg(feature = "compress")]
94impl DeltaOptions {
95 pub const fn from_distance(distance: u32) -> Self {
96 let distance = if distance == 0 {
97 1
98 } else if distance > 256 {
99 256
100 } else {
101 distance
102 };
103 Self(distance)
104 }
105}
106
107#[cfg(feature = "compress")]
108impl Default for DeltaOptions {
109 fn default() -> Self {
110 Self(1)
111 }
112}
113
114#[cfg(feature = "deflate")]
115#[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
116#[derive(Debug, Copy, Clone)]
117pub struct DeflateOptions(pub(crate) u32);
118
119#[cfg(feature = "deflate")]
120impl DeflateOptions {
121 pub const fn from_level(level: u32) -> Self {
122 let level = if level > 9 { 9 } else { level };
123 Self(level)
124 }
125}
126
127#[cfg(feature = "deflate")]
128impl Default for DeflateOptions {
129 fn default() -> Self {
130 Self(6)
131 }
132}
133
134#[cfg(feature = "lz4")]
135#[cfg_attr(docsrs, doc(cfg(feature = "lz4")))]
136#[derive(Debug, Copy, Clone, Default)]
137pub struct LZ4Options {
138 pub(crate) skippable_frame_size: u32,
139}
140
141#[cfg(feature = "lz4")]
142impl LZ4Options {
143 pub fn with_skippable_frame_size(mut self, skippable_frame_size: u32) -> Self {
154 if skippable_frame_size == 0 {
155 self.skippable_frame_size = 0;
156 } else {
157 self.skippable_frame_size =
158 u32::max(skippable_frame_size, MINIMAL_SKIPPABLE_FRAME_SIZE);
159 }
160
161 self
162 }
163}
164
165#[cfg(feature = "ppmd")]
166#[cfg_attr(docsrs, doc(cfg(feature = "ppmd")))]
167#[derive(Debug, Copy, Clone)]
168pub struct PPMDOptions {
169 pub(crate) order: u32,
170 pub(crate) memory_size: u32,
171}
172
173#[cfg(feature = "ppmd")]
174impl PPMDOptions {
175 pub const fn from_level(level: u32) -> Self {
176 const ORDERS: [u32; 10] = [3, 4, 4, 5, 5, 6, 8, 16, 24, 32];
177
178 let level = if level > 9 { 9 } else { level };
179 let order = ORDERS[level as usize];
180 let memory_size = 1 << (level + 19);
181
182 Self { order, memory_size }
183 }
184
185 pub const fn from_order_memory_size(order: u32, memory_size: u32) -> Self {
186 let order = if order > PPMD7_MAX_ORDER {
187 PPMD7_MAX_ORDER
188 } else if order < PPMD7_MIN_ORDER {
189 PPMD7_MIN_ORDER
190 } else {
191 order
192 };
193 let memory_size = if memory_size > PPMD7_MAX_MEM_SIZE {
194 PPMD7_MAX_MEM_SIZE
195 } else if memory_size < PPMD7_MIN_MEM_SIZE {
196 PPMD7_MIN_MEM_SIZE
197 } else {
198 memory_size
199 };
200 Self { order, memory_size }
201 }
202}
203
204#[cfg(feature = "ppmd")]
205impl Default for PPMDOptions {
206 fn default() -> Self {
207 Self::from_level(6)
208 }
209}
210
211#[cfg(feature = "zstd")]
212#[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
213#[derive(Debug, Copy, Clone)]
214pub struct ZStandardOptions(pub(crate) u32);
215
216#[cfg(feature = "zstd")]
217impl ZStandardOptions {
218 pub const fn from_level(level: u32) -> Self {
219 let level = if level > 22 { 22 } else { level };
220 Self(level)
221 }
222}
223
224#[cfg(feature = "zstd")]
225impl Default for ZStandardOptions {
226 fn default() -> Self {
227 Self(3)
228 }
229}
230
231#[cfg_attr(docsrs, doc(cfg(feature = "aes256")))]
232#[cfg(feature = "aes256")]
233#[derive(Debug, Clone)]
234pub struct AesEncoderOptions {
235 pub password: Password,
236 pub iv: [u8; 16],
237 pub salt: [u8; 16],
238 pub num_cycles_power: u8,
239}
240
241#[cfg(feature = "aes256")]
242impl AesEncoderOptions {
243 pub fn new(password: Password) -> Self {
244 let mut iv = [0; 16];
245 getrandom::fill(&mut iv).expect("Can't generate IV");
246
247 let mut salt = [0; 16];
248 getrandom::fill(&mut salt).expect("Can't generate salt");
249
250 Self {
251 password,
252 iv,
253 salt,
254 num_cycles_power: 8,
255 }
256 }
257
258 pub(crate) fn properties(&self) -> [u8; 34] {
259 let mut props = [0u8; 34];
260 self.write_properties(&mut props);
261 props
262 }
263
264 #[inline]
265 pub(crate) fn write_properties(&self, props: &mut [u8]) {
266 assert!(props.len() >= 34);
267 props[0] = (self.num_cycles_power & 0x3F) | 0xC0;
268 props[1] = 0xFF;
269 props[2..18].copy_from_slice(&self.salt);
270 props[18..34].copy_from_slice(&self.iv);
271 }
272}
273
274#[derive(Debug, Clone)]
275pub enum EncoderOptions {
276 Num(u32),
277 #[cfg(feature = "compress")]
278 #[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
279 Delta(DeltaOptions),
280 #[cfg(feature = "compress")]
281 #[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
282 LZMA2(LZMA2Options),
283 #[cfg(feature = "brotli")]
284 #[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
285 BROTLI(BrotliOptions),
286 #[cfg(feature = "bzip2")]
287 #[cfg_attr(docsrs, doc(cfg(feature = "bzip2")))]
288 BZIP2(Bzip2Options),
289 #[cfg(feature = "deflate")]
290 #[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
291 DEFLATE(DeflateOptions),
292 #[cfg(feature = "lz4")]
293 #[cfg_attr(docsrs, doc(cfg(feature = "lz4")))]
294 LZ4(LZ4Options),
295 #[cfg(feature = "ppmd")]
296 #[cfg_attr(docsrs, doc(cfg(feature = "ppmd")))]
297 PPMD(PPMDOptions),
298 #[cfg(feature = "zstd")]
299 #[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
300 ZSTD(ZStandardOptions),
301 #[cfg(feature = "aes256")]
302 #[cfg_attr(docsrs, doc(cfg(feature = "aes256")))]
303 Aes(AesEncoderOptions),
304}
305
306#[cfg(feature = "aes256")]
307impl From<AesEncoderOptions> for EncoderOptions {
308 fn from(value: AesEncoderOptions) -> Self {
309 Self::Aes(value)
310 }
311}
312
313#[cfg(all(feature = "aes256", feature = "compress"))]
314impl From<AesEncoderOptions> for EncoderConfiguration {
315 fn from(value: AesEncoderOptions) -> Self {
316 Self::new(crate::EncoderMethod::AES256SHA256).with_options(EncoderOptions::Aes(value))
317 }
318}
319
320#[cfg(feature = "compress")]
321impl From<DeltaOptions> for EncoderConfiguration {
322 fn from(options: DeltaOptions) -> Self {
323 Self::new(crate::EncoderMethod::DELTA_FILTER).with_options(EncoderOptions::Delta(options))
324 }
325}
326
327#[cfg(feature = "compress")]
328impl From<LZMA2Options> for EncoderConfiguration {
329 fn from(options: LZMA2Options) -> Self {
330 Self::new(crate::EncoderMethod::LZMA2).with_options(EncoderOptions::LZMA2(options))
331 }
332}
333
334#[cfg(feature = "bzip2")]
335impl From<Bzip2Options> for EncoderConfiguration {
336 fn from(options: Bzip2Options) -> Self {
337 Self::new(crate::EncoderMethod::BZIP2).with_options(EncoderOptions::BZIP2(options))
338 }
339}
340
341#[cfg(feature = "brotli")]
342impl From<BrotliOptions> for EncoderConfiguration {
343 fn from(options: BrotliOptions) -> Self {
344 Self::new(crate::EncoderMethod::BROTLI).with_options(EncoderOptions::BROTLI(options))
345 }
346}
347
348#[cfg(feature = "deflate")]
349impl From<DeflateOptions> for EncoderConfiguration {
350 fn from(options: DeflateOptions) -> Self {
351 Self::new(crate::EncoderMethod::DEFLATE).with_options(EncoderOptions::DEFLATE(options))
352 }
353}
354
355#[cfg(feature = "lz4")]
356impl From<LZ4Options> for EncoderConfiguration {
357 fn from(options: LZ4Options) -> Self {
358 Self::new(crate::EncoderMethod::LZ4).with_options(EncoderOptions::LZ4(options))
359 }
360}
361
362#[cfg(feature = "ppmd")]
363impl From<PPMDOptions> for EncoderConfiguration {
364 fn from(options: PPMDOptions) -> Self {
365 Self::new(crate::EncoderMethod::PPMD).with_options(EncoderOptions::PPMD(options))
366 }
367}
368
369#[cfg(feature = "zstd")]
370impl From<ZStandardOptions> for EncoderConfiguration {
371 fn from(options: ZStandardOptions) -> Self {
372 Self::new(crate::EncoderMethod::ZSTD).with_options(EncoderOptions::ZSTD(options))
373 }
374}
375
376impl From<u32> for EncoderOptions {
377 fn from(n: u32) -> Self {
378 Self::Num(n)
379 }
380}
381
382#[cfg(feature = "compress")]
383impl From<DeltaOptions> for EncoderOptions {
384 fn from(o: DeltaOptions) -> Self {
385 Self::Delta(o)
386 }
387}
388
389#[cfg(feature = "compress")]
390impl From<LZMA2Options> for EncoderOptions {
391 fn from(o: LZMA2Options) -> Self {
392 Self::LZMA2(o)
393 }
394}
395
396#[cfg(feature = "bzip2")]
397impl From<Bzip2Options> for EncoderOptions {
398 fn from(o: Bzip2Options) -> Self {
399 Self::BZIP2(o)
400 }
401}
402
403#[cfg(feature = "brotli")]
404impl From<BrotliOptions> for EncoderOptions {
405 fn from(o: BrotliOptions) -> Self {
406 Self::BROTLI(o)
407 }
408}
409
410#[cfg(feature = "deflate")]
411impl From<DeflateOptions> for EncoderOptions {
412 fn from(o: DeflateOptions) -> Self {
413 Self::DEFLATE(o)
414 }
415}
416
417#[cfg(feature = "lz4")]
418impl From<LZ4Options> for EncoderOptions {
419 fn from(o: LZ4Options) -> Self {
420 Self::LZ4(o)
421 }
422}
423
424#[cfg(feature = "ppmd")]
425impl From<PPMDOptions> for EncoderOptions {
426 fn from(o: PPMDOptions) -> Self {
427 Self::PPMD(o)
428 }
429}
430
431#[cfg(feature = "zstd")]
432impl From<ZStandardOptions> for EncoderOptions {
433 fn from(o: ZStandardOptions) -> Self {
434 Self::ZSTD(o)
435 }
436}
437
438impl EncoderOptions {
439 pub fn get_lzma2_dict_size(&self) -> u32 {
440 match self {
441 EncoderOptions::Num(n) => *n,
442 #[cfg(feature = "compress")]
443 EncoderOptions::LZMA2(o) => o.dict_size,
444 #[allow(unused)]
445 _ => 0,
446 }
447 }
448}