bzip2_rs/decoder/
reader.rs

1use std::io::{self, Read, Result};
2
3use super::{Decoder, ReadState, WriteState};
4
5/// A high-level decoder that wraps a [`Read`] and implements [`Read`], yielding decompressed bytes
6///
7/// ```rust
8/// use std::fs::File;
9/// use std::io;
10///
11/// use bzip2_rs::DecoderReader;
12///
13/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
14/// let mut compressed_file = File::open("tests/samplefiles/sample1.bz2")?;
15/// # fn no_run() -> Result<(), Box<dyn std::error::Error>> {
16/// let mut output = File::create("output.ref")?;
17/// # Ok(())
18/// # }
19/// # let mut output = Vec::new();
20///
21/// let mut reader = DecoderReader::new(compressed_file);
22/// io::copy(&mut reader, &mut output)?;
23/// #
24/// # let expected = std::fs::read("tests/samplefiles/sample1.ref")?;
25/// # assert_eq!(expected, output);
26/// #
27/// # Ok(())
28/// # }
29/// ```
30pub struct DecoderReader<R> {
31    decoder: Decoder,
32
33    reader: R,
34}
35
36impl<R> DecoderReader<R> {
37    /// Construct a new decoder from something implementing [`Read`]
38    pub fn new(reader: R) -> Self {
39        Self {
40            decoder: Decoder::new(),
41
42            reader,
43        }
44    }
45}
46
47impl<R: Read> Read for DecoderReader<R> {
48    /// Decompress bzip2 data from the underlying reader
49    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
50        let mut read_zero = false;
51        let mut tmp_buf = [0; 1024];
52
53        loop {
54            match self.decoder.read(buf)? {
55                ReadState::NeedsWrite(space) => {
56                    let read = self.reader.read(&mut tmp_buf[..space.min(1024)])?;
57
58                    if read_zero && self.decoder.header_block.is_none() {
59                        return Err(io::Error::new(
60                            io::ErrorKind::UnexpectedEof,
61                            "The reader is empty?",
62                        ));
63                    }
64                    read_zero = read == 0;
65
66                    match self.decoder.write(&tmp_buf[..read])? {
67                        WriteState::NeedsRead => unreachable!(),
68                        WriteState::Written(written) => assert_eq!(written, read),
69                    };
70                }
71                ReadState::Read(n) => return Ok(n),
72                ReadState::Eof => return Ok(0),
73            }
74        }
75    }
76}