async_compression/codec/xz2/
encoder.rs

1use std::{fmt, io};
2
3use xz2::stream::{Action, Check, LzmaOptions, Status, Stream};
4
5use crate::{
6    codec::{Encode, Xz2FileFormat},
7    util::PartialBuffer,
8};
9
10pub struct Xz2Encoder {
11    stream: Stream,
12}
13
14impl fmt::Debug for Xz2Encoder {
15    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16        f.debug_struct("Xz2Encoder").finish_non_exhaustive()
17    }
18}
19
20impl Xz2Encoder {
21    pub fn new(format: Xz2FileFormat, level: u32) -> Self {
22        let stream = match format {
23            Xz2FileFormat::Xz => Stream::new_easy_encoder(level, Check::Crc64).unwrap(),
24            Xz2FileFormat::Lzma => {
25                Stream::new_lzma_encoder(&LzmaOptions::new_preset(level).unwrap()).unwrap()
26            }
27        };
28
29        Self { stream }
30    }
31}
32
33impl Encode for Xz2Encoder {
34    fn encode(
35        &mut self,
36        input: &mut PartialBuffer<impl AsRef<[u8]>>,
37        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
38    ) -> io::Result<()> {
39        let previous_in = self.stream.total_in() as usize;
40        let previous_out = self.stream.total_out() as usize;
41
42        let status = self
43            .stream
44            .process(input.unwritten(), output.unwritten_mut(), Action::Run)?;
45
46        input.advance(self.stream.total_in() as usize - previous_in);
47        output.advance(self.stream.total_out() as usize - previous_out);
48
49        match status {
50            Status::Ok | Status::StreamEnd => Ok(()),
51            Status::GetCheck => Err(io::Error::new(
52                io::ErrorKind::Other,
53                "Unexpected lzma integrity check",
54            )),
55            Status::MemNeeded => Err(io::Error::new(io::ErrorKind::Other, "out of memory")),
56        }
57    }
58
59    fn flush(
60        &mut self,
61        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
62    ) -> io::Result<bool> {
63        let previous_out = self.stream.total_out() as usize;
64
65        let status = self
66            .stream
67            .process(&[], output.unwritten_mut(), Action::SyncFlush)?;
68
69        output.advance(self.stream.total_out() as usize - previous_out);
70
71        match status {
72            Status::Ok => Ok(false),
73            Status::StreamEnd => Ok(true),
74            Status::GetCheck => Err(io::Error::new(
75                io::ErrorKind::Other,
76                "Unexpected lzma integrity check",
77            )),
78            Status::MemNeeded => Err(io::Error::new(io::ErrorKind::Other, "out of memory")),
79        }
80    }
81
82    fn finish(
83        &mut self,
84        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
85    ) -> io::Result<bool> {
86        let previous_out = self.stream.total_out() as usize;
87
88        let status = self
89            .stream
90            .process(&[], output.unwritten_mut(), Action::Finish)?;
91
92        output.advance(self.stream.total_out() as usize - previous_out);
93
94        match status {
95            Status::Ok => Ok(false),
96            Status::StreamEnd => Ok(true),
97            Status::GetCheck => Err(io::Error::new(
98                io::ErrorKind::Other,
99                "Unexpected lzma integrity check",
100            )),
101            Status::MemNeeded => Err(io::Error::new(io::ErrorKind::Other, "out of memory")),
102        }
103    }
104}