compression_codecs/xz/
decoder.rs1use crate::{DecodeV2, DecodedSize, Xz2Decoder};
2use compression_core::util::{PartialBuffer, WriteBuffer};
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 DecodeV2 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<&[u8]>,
54 output: &mut WriteBuffer<'_>,
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(&mut self, output: &mut WriteBuffer<'_>) -> Result<bool> {
81 if self.skip_padding.is_some() {
82 return Ok(true);
83 }
84 self.inner.flush(output)
85 }
86
87 fn finish(&mut self, output: &mut WriteBuffer<'_>) -> Result<bool> {
88 if self.skip_padding.is_some() {
89 return Ok(true);
90 }
91 self.inner.finish(output)
92 }
93}
94
95impl DecodedSize for XzDecoder {
96 fn decoded_size(input: &[u8]) -> Result<u64> {
97 Xz2Decoder::decoded_size(input)
98 }
99}