1use std::convert::TryFrom;
4#[cfg(feature = "xz-parallel")]
5use std::num::NonZeroU32;
6
7#[derive(Debug, Clone)]
9pub enum LzmaEncoderParams {
10 Easy {
11 preset: u32,
12 check: liblzma::stream::Check,
13 },
14 Lzma {
15 options: LzmaOptions,
16 },
17 Raw {
18 filters: LzmaFilters,
19 },
20 Stream {
21 filters: LzmaFilters,
22 check: liblzma::stream::Check,
23 },
24
25 #[cfg(feature = "xz-parallel")]
26 MultiThread {
27 builder: MtStreamBuilder,
28 },
29}
30
31impl TryFrom<&LzmaEncoderParams> for liblzma::stream::Stream {
32 type Error = liblzma::stream::Error;
33
34 fn try_from(value: &LzmaEncoderParams) -> Result<Self, Self::Error> {
35 let stream = match value {
36 LzmaEncoderParams::Easy { preset, check } => Self::new_easy_encoder(*preset, *check)?,
37 LzmaEncoderParams::Lzma { options } => {
38 let options = liblzma::stream::LzmaOptions::try_from(options)?;
39 Self::new_lzma_encoder(&options)?
40 }
41 LzmaEncoderParams::Raw { filters } => {
42 let filters = liblzma::stream::Filters::try_from(filters)?;
43 Self::new_raw_encoder(&filters)?
44 }
45 LzmaEncoderParams::Stream { filters, check } => {
46 let filters = liblzma::stream::Filters::try_from(filters)?;
47 Self::new_stream_encoder(&filters, *check)?
48 }
49
50 #[cfg(feature = "xz-parallel")]
51 LzmaEncoderParams::MultiThread { builder } => {
52 let builder = liblzma::stream::MtStreamBuilder::try_from(builder)?;
53 builder.encoder()?
54 }
55 };
56
57 Ok(stream)
58 }
59}
60
61#[derive(Clone, Debug)]
63pub enum LzmaDecoderParams {
64 Auto {
65 mem_limit: u64,
66 flags: u32,
67 },
68 Lzip {
69 mem_limit: u64,
70 flags: u32,
71 },
72 Lzma {
73 mem_limit: u64,
74 },
75 Raw {
76 filters: LzmaFilters,
77 },
78 Stream {
79 mem_limit: u64,
80 flags: u32,
81 },
82
83 #[cfg(feature = "xz-parallel")]
84 MultiThread {
85 builder: MtStreamBuilder,
86 },
87}
88
89impl TryFrom<&LzmaDecoderParams> for liblzma::stream::Stream {
90 type Error = liblzma::stream::Error;
91
92 fn try_from(value: &LzmaDecoderParams) -> Result<Self, Self::Error> {
93 let stream = match value {
94 LzmaDecoderParams::Auto { mem_limit, flags } => {
95 Self::new_auto_decoder(*mem_limit, *flags)?
96 }
97 LzmaDecoderParams::Lzip { mem_limit, flags } => {
98 Self::new_lzip_decoder(*mem_limit, *flags)?
99 }
100 LzmaDecoderParams::Lzma { mem_limit } => Self::new_lzma_decoder(*mem_limit)?,
101 LzmaDecoderParams::Stream { mem_limit, flags } => {
102 Self::new_stream_decoder(*mem_limit, *flags)?
103 }
104 LzmaDecoderParams::Raw { filters } => {
105 let filters = liblzma::stream::Filters::try_from(filters)?;
106 Self::new_raw_decoder(&filters)?
107 }
108 #[cfg(feature = "xz-parallel")]
109 LzmaDecoderParams::MultiThread { builder } => {
110 let builder = liblzma::stream::MtStreamBuilder::try_from(builder)?;
111 builder.decoder()?
112 }
113 };
114
115 Ok(stream)
116 }
117}
118
119#[derive(Default, Clone, Debug)]
121pub struct LzmaFilters {
122 filters: Vec<LzmaFilter>,
123}
124
125impl LzmaFilters {
126 pub fn add_filter(mut self, filter: LzmaFilter) -> Self {
128 self.filters.push(filter);
129 self
130 }
131}
132
133#[derive(Debug, Clone)]
135pub enum LzmaFilter {
136 Arm(Option<Vec<u8>>),
137 Arm64(Option<Vec<u8>>),
138 ArmThumb(Option<Vec<u8>>),
139 Delta(Option<Vec<u8>>),
140 Ia64(Option<Vec<u8>>),
141 Lzma1(LzmaOptions),
142 Lzma1Properties(Vec<u8>),
143 Lzma2(LzmaOptions),
144 Lzma2Properties(Vec<u8>),
145 PowerPc(Option<Vec<u8>>),
146 Sparc(Option<Vec<u8>>),
147 X86(Option<Vec<u8>>),
148}
149
150impl TryFrom<&LzmaFilters> for liblzma::stream::Filters {
151 type Error = liblzma::stream::Error;
152
153 fn try_from(value: &LzmaFilters) -> Result<Self, Self::Error> {
154 let mut filters = liblzma::stream::Filters::new();
155 for f in value.filters.iter() {
156 match f {
157 LzmaFilter::Arm(Some(p)) => filters.arm_properties(p)?,
158 LzmaFilter::Arm(None) => filters.arm(),
159 LzmaFilter::Arm64(Some(p)) => filters.arm64_properties(p)?,
160 LzmaFilter::Arm64(None) => filters.arm64(),
161 LzmaFilter::ArmThumb(Some(p)) => filters.arm_thumb_properties(p)?,
162 LzmaFilter::ArmThumb(None) => filters.arm_thumb(),
163 LzmaFilter::Delta(Some(p)) => filters.delta_properties(p)?,
164 LzmaFilter::Delta(None) => filters.delta(),
165 LzmaFilter::Ia64(Some(p)) => filters.ia64_properties(p)?,
166 LzmaFilter::Ia64(None) => filters.ia64(),
167 LzmaFilter::Lzma1(opts) => {
168 let opts = liblzma::stream::LzmaOptions::try_from(opts)?;
169 filters.lzma1(&opts)
170 }
171 LzmaFilter::Lzma1Properties(p) => filters.lzma1_properties(p)?,
172 LzmaFilter::Lzma2(opts) => {
173 let opts = liblzma::stream::LzmaOptions::try_from(opts)?;
174 filters.lzma2(&opts)
175 }
176 LzmaFilter::Lzma2Properties(p) => filters.lzma2_properties(p)?,
177 LzmaFilter::PowerPc(Some(p)) => filters.powerpc_properties(p)?,
178 LzmaFilter::PowerPc(None) => filters.powerpc(),
179 LzmaFilter::Sparc(Some(p)) => filters.sparc_properties(p)?,
180 LzmaFilter::Sparc(None) => filters.sparc(),
181 LzmaFilter::X86(Some(p)) => filters.x86_properties(p)?,
182 LzmaFilter::X86(None) => filters.x86(),
183 };
184 }
185
186 Ok(filters)
187 }
188}
189
190#[derive(Default, Clone)]
192pub struct LzmaOptions {
193 preset: Option<u32>,
194 depth: Option<u32>,
195 dict_size: Option<u32>,
196 literal_context_bits: Option<u32>,
197 literal_position_bits: Option<u32>,
198 match_finder: Option<liblzma::stream::MatchFinder>,
199 mode: Option<liblzma::stream::Mode>,
200 nice_len: Option<u32>,
201 position_bits: Option<u32>,
202}
203
204impl std::fmt::Debug for LzmaOptions {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 let match_finder = self.match_finder.map(|m| match m {
207 liblzma::stream::MatchFinder::HashChain3 => "HashChain3",
208 liblzma::stream::MatchFinder::HashChain4 => "HashChain4",
209 liblzma::stream::MatchFinder::BinaryTree2 => "BTree2",
210 liblzma::stream::MatchFinder::BinaryTree3 => "BTree3",
211 liblzma::stream::MatchFinder::BinaryTree4 => "BTree4",
212 });
213
214 let mode = self.mode.map(|m| match m {
215 liblzma::stream::Mode::Fast => "Fast",
216 liblzma::stream::Mode::Normal => "Normal",
217 });
218
219 f.debug_struct("LzmaOptions")
220 .field("preset", &self.preset)
221 .field("depth", &self.depth)
222 .field("dict_size", &self.dict_size)
223 .field("literal_context_bits", &self.literal_context_bits)
224 .field("literal_position_bits", &self.literal_position_bits)
225 .field("match_finder", &match_finder)
226 .field("mode", &mode)
227 .field("nice_len", &self.nice_len)
228 .field("position_bits", &self.position_bits)
229 .finish()
230 }
231}
232
233impl LzmaOptions {
234 pub fn preset(mut self, value: u32) -> Self {
235 self.preset = Some(value);
236 self
237 }
238 pub fn depth(mut self, value: u32) -> Self {
239 self.depth = Some(value);
240 self
241 }
242 pub fn dict_size(mut self, value: u32) -> Self {
243 self.dict_size = Some(value);
244 self
245 }
246 pub fn literal_context_bits(mut self, value: u32) -> Self {
247 self.literal_context_bits = Some(value);
248 self
249 }
250 pub fn literal_position_bits(mut self, value: u32) -> Self {
251 self.literal_position_bits = Some(value);
252 self
253 }
254 pub fn match_finder(mut self, value: liblzma::stream::MatchFinder) -> Self {
255 self.match_finder = Some(value);
256 self
257 }
258 pub fn mode(mut self, value: liblzma::stream::Mode) -> Self {
259 self.mode = Some(value);
260 self
261 }
262 pub fn nice_len(mut self, value: u32) -> Self {
263 self.nice_len = Some(value);
264 self
265 }
266 pub fn position_bits(mut self, value: u32) -> Self {
267 self.position_bits = Some(value);
268 self
269 }
270}
271
272impl TryFrom<&LzmaOptions> for liblzma::stream::LzmaOptions {
273 type Error = liblzma::stream::Error;
274
275 fn try_from(value: &LzmaOptions) -> Result<Self, Self::Error> {
276 let mut s = match value.preset {
277 Some(preset) => liblzma::stream::LzmaOptions::new_preset(preset)?,
278 None => liblzma::stream::LzmaOptions::new(),
279 };
280 if let Some(depth) = value.depth {
281 s.depth(depth);
282 }
283 if let Some(dict_size) = value.dict_size {
284 s.dict_size(dict_size);
285 }
286 if let Some(bits) = value.literal_context_bits {
287 s.literal_context_bits(bits);
288 }
289 if let Some(bits) = value.literal_position_bits {
290 s.literal_position_bits(bits);
291 }
292 if let Some(mf) = value.match_finder {
293 s.match_finder(mf);
294 }
295 if let Some(mode) = value.mode {
296 s.mode(mode);
297 }
298 if let Some(len) = value.nice_len {
299 s.nice_len(len);
300 }
301
302 if let Some(bits) = value.position_bits {
303 s.position_bits(bits);
304 }
305
306 Ok(s)
307 }
308}
309
310#[cfg(feature = "xz-parallel")]
311#[derive(Default, Clone)]
312pub struct MtStreamBuilder {
314 block_size: Option<u64>,
315 preset: Option<u32>,
316 check: Option<liblzma::stream::Check>,
317 filters: Option<LzmaFilters>,
318 mem_limit_stop: Option<u64>,
319 mem_limit_threading: Option<u64>,
320 threads: Option<NonZeroU32>,
321 timeout_ms: Option<u32>,
322}
323
324#[cfg(feature = "xz-parallel")]
325impl std::fmt::Debug for MtStreamBuilder {
326 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
327 let check = self.check.map(|s| match s {
328 liblzma::stream::Check::None => "None",
329 liblzma::stream::Check::Crc32 => "Crc32",
330 liblzma::stream::Check::Crc64 => "Crc64",
331 liblzma::stream::Check::Sha256 => "Sha256",
332 });
333 f.debug_struct("MtStreamBuilder")
334 .field("block_size", &self.block_size)
335 .field("preset", &self.preset)
336 .field("check", &check)
337 .field("filters", &self.filters)
338 .field("mem_limit_stop", &self.mem_limit_stop)
339 .field("mem_limit_threading", &self.mem_limit_threading)
340 .field("threads", &self.threads)
341 .field("timeout_ms", &self.timeout_ms)
342 .finish()
343 }
344}
345
346#[cfg(feature = "xz-parallel")]
347impl MtStreamBuilder {
348 pub fn block_size(&mut self, block_size: u64) -> &mut Self {
349 self.block_size = Some(block_size);
350 self
351 }
352 pub fn preset(&mut self, preset: u32) -> &mut Self {
353 self.preset = Some(preset);
354 self
355 }
356 pub fn check(&mut self, check: liblzma::stream::Check) -> &mut Self {
357 self.check = Some(check);
358 self
359 }
360
361 pub fn filters(&mut self, filters: LzmaFilters) -> &mut Self {
362 self.filters = Some(filters);
363 self
364 }
365 pub fn mem_limit_stop(&mut self, mem_limit_stop: u64) -> &mut Self {
366 self.mem_limit_stop = Some(mem_limit_stop);
367 self
368 }
369 pub fn mem_limit_threading(&mut self, mem_limit_threading: u64) -> &mut Self {
370 self.mem_limit_threading = Some(mem_limit_threading);
371 self
372 }
373 pub fn threads(&mut self, threads: NonZeroU32) -> &mut Self {
374 self.threads = Some(threads);
375 self
376 }
377 pub fn timeout_ms(&mut self, timeout_ms: u32) -> &mut Self {
378 self.timeout_ms = Some(timeout_ms);
379 self
380 }
381}
382
383#[cfg(feature = "xz-parallel")]
384impl TryFrom<&MtStreamBuilder> for liblzma::stream::MtStreamBuilder {
385 type Error = liblzma::stream::Error;
386
387 fn try_from(value: &MtStreamBuilder) -> Result<Self, Self::Error> {
388 let mut mt = liblzma::stream::MtStreamBuilder::new();
389 if let Some(block_size) = value.block_size {
390 mt.block_size(block_size);
391 }
392 if let Some(preset) = value.preset {
393 mt.preset(preset);
394 }
395 if let Some(check) = value.check {
396 mt.check(check);
397 }
398 if let Some(filters) = &value.filters {
399 let filters = liblzma::stream::Filters::try_from(filters)?;
400 mt.filters(filters);
401 }
402 if let Some(memlimit) = value.mem_limit_stop {
403 mt.memlimit_stop(memlimit);
404 }
405 if let Some(memlimit) = value.mem_limit_threading {
406 mt.memlimit_threading(memlimit);
407 }
408 if let Some(threads) = value.threads {
409 mt.threads(threads.get());
410 }
411 if let Some(timeout) = value.timeout_ms {
412 mt.timeout_ms(timeout);
413 }
414 Ok(mt)
415 }
416}