compression_codecs/bzip2/
decoder.rs1use crate::DecodeV2;
2use bzip2::{Decompress, Status};
3use compression_core::util::{PartialBuffer, WriteBuffer};
4use std::{fmt, io};
5
6pub struct BzDecoder {
7 decompress: Decompress,
8 stream_ended: bool,
9}
10
11impl fmt::Debug for BzDecoder {
12 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13 write!(
14 f,
15 "BzDecoder {{total_in: {}, total_out: {}}}",
16 self.decompress.total_in(),
17 self.decompress.total_out()
18 )
19 }
20}
21
22impl Default for BzDecoder {
23 fn default() -> Self {
24 Self {
25 decompress: Decompress::new(false),
26 stream_ended: false,
27 }
28 }
29}
30
31impl BzDecoder {
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 fn decode(
37 &mut self,
38 input: &mut PartialBuffer<&[u8]>,
39 output: &mut WriteBuffer<'_>,
40 ) -> io::Result<Status> {
41 let prior_in = self.decompress.total_in();
42 let prior_out = self.decompress.total_out();
43
44 let result = self
45 .decompress
46 .decompress_uninit(input.unwritten(), unsafe { output.unwritten_mut() })
48 .map_err(io::Error::other);
49
50 input.advance((self.decompress.total_in() - prior_in) as usize);
51 unsafe {
53 output.assume_init_and_advance((self.decompress.total_out() - prior_out) as usize)
54 };
55
56 if matches!(result, Ok(Status::StreamEnd)) {
58 self.stream_ended = true;
59 }
60
61 result
62 }
63}
64
65impl DecodeV2 for BzDecoder {
66 fn reinit(&mut self) -> io::Result<()> {
67 self.decompress = Decompress::new(false);
68 self.stream_ended = false;
69 Ok(())
70 }
71
72 fn decode(
73 &mut self,
74 input: &mut PartialBuffer<&[u8]>,
75 output: &mut WriteBuffer<'_>,
76 ) -> io::Result<bool> {
77 match self.decode(input, output)? {
78 Status::Ok => Ok(false),
80
81 Status::FlushOk => unreachable!(),
83
84 Status::RunOk => unreachable!(),
86
87 Status::FinishOk => unreachable!(),
89
90 Status::StreamEnd => Ok(true),
92
93 Status::MemNeeded => Err(io::ErrorKind::OutOfMemory.into()),
96 }
97 }
98
99 fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
100 self.decode(&mut PartialBuffer::new(&[][..]), output)?;
101
102 loop {
103 let old_len = output.written_len();
104 self.decode(&mut PartialBuffer::new(&[][..]), output)?;
105 if output.written_len() == old_len {
106 break;
107 }
108 }
109
110 Ok(!output.has_no_spare_space())
111 }
112
113 fn finish(&mut self, _output: &mut WriteBuffer<'_>) -> io::Result<bool> {
114 if self.stream_ended {
115 Ok(true)
116 } else {
117 Err(io::Error::new(
118 io::ErrorKind::UnexpectedEof,
119 "bzip2 stream did not finish",
120 ))
121 }
122 }
123}