compression_codecs/xz2/
decoder.rs1use crate::{lzma::params::LzmaDecoderParams, xz2::process_stream, DecodeV2, DecodedSize};
2use compression_core::util::{PartialBuffer, WriteBuffer};
3use liblzma::stream::{Action, Stream};
4use std::{
5 convert::TryFrom,
6 fmt,
7 io::{self, Cursor},
8};
9
10pub struct Xz2Decoder {
12 stream: Stream,
13 params: LzmaDecoderParams,
14}
15
16impl fmt::Debug for Xz2Decoder {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 f.debug_struct("Xz2Decoder").finish_non_exhaustive()
19 }
20}
21
22impl TryFrom<LzmaDecoderParams> for Xz2Decoder {
23 type Error = liblzma::stream::Error;
24
25 fn try_from(params: LzmaDecoderParams) -> Result<Self, Self::Error> {
26 let stream = Stream::try_from(¶ms)?;
27 Ok(Self { stream, params })
28 }
29}
30
31impl Xz2Decoder {
32 pub fn new(mem_limit: u64) -> Self {
33 let params = LzmaDecoderParams::Auto {
34 mem_limit,
35 flags: 0,
36 };
37 Self::try_from(params).unwrap()
38 }
39
40 #[cfg(feature = "xz-parallel")]
41 pub fn parallel(threads: std::num::NonZeroU32, mem_limit: u64) -> Self {
42 use crate::lzma::params::MtStreamBuilder;
43
44 let mut builder = MtStreamBuilder::default();
45
46 builder
47 .threads(threads)
48 .timeout_ms(300)
49 .mem_limit_stop(mem_limit);
50
51 let params = LzmaDecoderParams::MultiThread { builder };
52
53 Self::try_from(params).unwrap()
54 }
55}
56
57impl DecodeV2 for Xz2Decoder {
58 fn reinit(&mut self) -> io::Result<()> {
59 *self = Self::try_from(self.params.clone())?;
60 Ok(())
61 }
62
63 fn decode(
64 &mut self,
65 input: &mut PartialBuffer<&[u8]>,
66 output: &mut WriteBuffer<'_>,
67 ) -> io::Result<bool> {
68 process_stream(&mut self.stream, input, output, Action::Run)
69 }
70
71 fn flush(&mut self, _output: &mut WriteBuffer<'_>) -> io::Result<bool> {
72 Ok(true)
74 }
75
76 fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
77 process_stream(
78 &mut self.stream,
79 &mut PartialBuffer::new(&[]),
80 output,
81 Action::Finish,
82 )
83 }
84}
85
86impl DecodedSize for Xz2Decoder {
87 fn decoded_size(input: &[u8]) -> io::Result<u64> {
88 let cursor = Cursor::new(input);
89 liblzma::uncompressed_size(cursor)
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use std::convert::TryFrom;
96
97 use crate::{
98 lzma::params::{LzmaDecoderParams, LzmaFilter, LzmaFilters, LzmaOptions},
99 Xz2Decoder,
100 };
101
102 #[test]
103 fn test_lzma_decoder_from_params() {
104 let filters = LzmaFilters::default().add_filter(LzmaFilter::Lzma2(LzmaOptions::default()));
105 let params = LzmaDecoderParams::Raw { filters };
106 Xz2Decoder::try_from(params).unwrap();
107 }
108}