async_compression/codec/xz/
decoder.rs
1use crate::{codec::Decode, util::PartialBuffer};
2
3use std::io::{Error, ErrorKind, Result};
4
5#[derive(Debug)]
6pub struct XzDecoder {
7 inner: crate::codec::Xz2Decoder,
8 skip_padding: Option<u8>,
9}
10
11impl XzDecoder {
12 pub fn new() -> Self {
13 Self {
14 inner: crate::codec::Xz2Decoder::new(u64::max_value()),
15 skip_padding: None,
16 }
17 }
18
19 pub fn with_memlimit(memlimit: u64) -> Self {
20 Self {
21 inner: crate::codec::Xz2Decoder::new(memlimit),
22 skip_padding: None,
23 }
24 }
25}
26
27impl Decode for XzDecoder {
28 fn reinit(&mut self) -> Result<()> {
29 self.skip_padding = Some(4);
30 self.inner.reinit()
31 }
32
33 fn decode(
34 &mut self,
35 input: &mut PartialBuffer<impl AsRef<[u8]>>,
36 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
37 ) -> Result<bool> {
38 if let Some(ref mut count) = self.skip_padding {
39 while input.unwritten().first() == Some(&0) {
40 input.advance(1);
41 *count -= 1;
42 if *count == 0 {
43 *count = 4;
44 }
45 }
46 if input.unwritten().is_empty() {
47 return Ok(true);
48 }
49 if *count != 4 {
52 return Err(Error::new(
53 ErrorKind::InvalidData,
54 "stream padding was not a multiple of 4 bytes",
55 ));
56 }
57 self.skip_padding = None;
58 }
59 self.inner.decode(input, output)
60 }
61
62 fn flush(
63 &mut self,
64 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
65 ) -> Result<bool> {
66 if self.skip_padding.is_some() {
67 return Ok(true);
68 }
69 self.inner.flush(output)
70 }
71
72 fn finish(
73 &mut self,
74 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
75 ) -> Result<bool> {
76 if self.skip_padding.is_some() {
77 return Ok(true);
78 }
79 self.inner.finish(output)
80 }
81}