Skip to main content

async_compression_issue_150_workaround/codec/xz2/
encoder.rs

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