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(input.unwritten(), output.initialize_unwritten())
47 .map_err(io::Error::other);
48
49 input.advance((self.decompress.total_in() - prior_in) as usize);
50 output.advance((self.decompress.total_out() - prior_out) as usize);
51
52 if matches!(result, Ok(Status::StreamEnd)) {
54 self.stream_ended = true;
55 }
56
57 result
58 }
59}
60
61impl DecodeV2 for BzDecoder {
62 fn reinit(&mut self) -> io::Result<()> {
63 self.decompress = Decompress::new(false);
64 self.stream_ended = false;
65 Ok(())
66 }
67
68 fn decode(
69 &mut self,
70 input: &mut PartialBuffer<&[u8]>,
71 output: &mut WriteBuffer<'_>,
72 ) -> io::Result<bool> {
73 match self.decode(input, output)? {
74 Status::Ok => Ok(false),
76
77 Status::FlushOk => unreachable!(),
79
80 Status::RunOk => unreachable!(),
82
83 Status::FinishOk => unreachable!(),
85
86 Status::StreamEnd => Ok(true),
88
89 Status::MemNeeded => Err(io::ErrorKind::OutOfMemory.into()),
92 }
93 }
94
95 fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
96 self.decode(&mut PartialBuffer::new(&[][..]), output)?;
97
98 loop {
99 let old_len = output.written_len();
100 self.decode(&mut PartialBuffer::new(&[][..]), output)?;
101 if output.written_len() == old_len {
102 break;
103 }
104 }
105
106 Ok(!output.has_no_spare_space())
107 }
108
109 fn finish(&mut self, _output: &mut WriteBuffer<'_>) -> io::Result<bool> {
110 if self.stream_ended {
111 Ok(true)
112 } else {
113 Err(io::Error::new(
114 io::ErrorKind::UnexpectedEof,
115 "bzip2 stream did not finish",
116 ))
117 }
118 }
119}