compression_codecs/xz/
decoder.rs1use crate::{Decode, Xz2Decoder};
2use compression_core::util::PartialBuffer;
3use std::{
4 convert::TryInto,
5 io::{Error, ErrorKind, Result},
6};
7
8#[derive(Debug)]
10pub struct XzDecoder {
11 inner: Xz2Decoder,
12 skip_padding: Option<u8>,
13}
14
15impl Default for XzDecoder {
16 fn default() -> Self {
17 Self {
18 inner: Xz2Decoder::new(usize::MAX.try_into().unwrap()),
19 skip_padding: None,
20 }
21 }
22}
23
24impl XzDecoder {
25 pub fn new() -> Self {
26 Self::default()
27 }
28
29 pub fn with_memlimit(memlimit: u64) -> Self {
30 Self {
31 inner: Xz2Decoder::new(memlimit),
32 skip_padding: None,
33 }
34 }
35
36 #[cfg(feature = "xz-parallel")]
37 pub fn parallel(threads: std::num::NonZeroU32, memlimit: u64) -> Self {
38 Self {
39 inner: Xz2Decoder::parallel(threads, memlimit),
40 skip_padding: None,
41 }
42 }
43}
44
45impl Decode for XzDecoder {
46 fn reinit(&mut self) -> Result<()> {
47 self.skip_padding = Some(4);
48 self.inner.reinit()
49 }
50
51 fn decode(
52 &mut self,
53 input: &mut PartialBuffer<impl AsRef<[u8]>>,
54 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
55 ) -> Result<bool> {
56 if let Some(ref mut count) = self.skip_padding {
57 while input.unwritten().first() == Some(&0) {
58 input.advance(1);
59 *count -= 1;
60 if *count == 0 {
61 *count = 4;
62 }
63 }
64 if input.unwritten().is_empty() {
65 return Ok(true);
66 }
67 if *count != 4 {
70 return Err(Error::new(
71 ErrorKind::InvalidData,
72 "stream padding was not a multiple of 4 bytes",
73 ));
74 }
75 self.skip_padding = None;
76 }
77 self.inner.decode(input, output)
78 }
79
80 fn flush(
81 &mut self,
82 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
83 ) -> Result<bool> {
84 if self.skip_padding.is_some() {
85 return Ok(true);
86 }
87 self.inner.flush(output)
88 }
89
90 fn finish(
91 &mut self,
92 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
93 ) -> Result<bool> {
94 if self.skip_padding.is_some() {
95 return Ok(true);
96 }
97 self.inner.finish(output)
98 }
99}