Skip to main content

packbits_rle/
reader.rs

1use std::io::{self};
2
3use crate::{Command, Error};
4
5/// Wraps an input stream to provide transparent access to unpacked _PackBit_ bytes
6pub struct Reader<T: std::io::Read> {
7    /// Underlying reader
8    inner: T,
9    /// The bytes that currently repeated
10    repeated: u8,
11    /// Next command, counting down literal bytes and remaining repeitions to implement reads one byte at a
12    /// time
13    op: Command,
14    /// Maximum number of bytes to produce
15    max_output: Option<u64>,
16    /// Number of bytes that have already been produced
17    position: u64,
18}
19
20impl<T: io::Read> Reader<T> {
21    /// Creates a new Reader by wrapping an existing one
22    pub fn new(inner: T) -> Self {
23        Self {
24            inner,
25            repeated: 0,
26            op: Command::Literal(0),
27            max_output: None,
28            position: 0,
29        }
30    }
31
32    /// Create new reader with a maximum output size
33    pub fn with_max_output(inner: T, max_output: u64) -> Self {
34        Self {
35            inner,
36            repeated: 0,
37            op: Command::Literal(0),
38            max_output: Some(max_output),
39            position: 0,
40        }
41    }
42
43    #[inline]
44    fn produce_next_byte(&mut self) -> Result<Option<u8>, Error> {
45        let mut buf = [0u8];
46        match self.op {
47            Command::Literal(0) | Command::Repeat(0) => match self.inner.read(&mut buf) {
48                Ok(0) => Ok(None),
49                Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => Ok(None),
50                Err(e) => Err(e)?,
51                Ok(_) => {
52                    self.op = buf[0].into();
53                    if let Command::Repeat(_) = self.op {
54                        match self.inner.read(&mut buf) {
55                            Ok(0) => return Err(Error::NotEnoughInputData),
56                            Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
57                                return Err(Error::NotEnoughInputData);
58                            }
59                            Err(e) => return Err(e)?,
60                            Ok(_) => {
61                                self.repeated = buf[0];
62                            }
63                        }
64                    }
65                    self.produce_next_byte()
66                }
67            },
68            Command::Escape => {
69                self.op = Command::Literal(0);
70
71                match self.inner.read(&mut buf) {
72                    Ok(0) => Err(Error::NotEnoughInputData),
73                    Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
74                        Err(Error::NotEnoughInputData)
75                    }
76                    Err(e) => Err(e)?,
77                    Ok(_) => Ok(Some(buf[0])),
78                }
79            }
80            Command::Literal(c) => {
81                self.op = Command::Literal(c - 1);
82
83                match self.inner.read(&mut buf) {
84                    Ok(0) => Err(Error::NotEnoughInputData),
85                    Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
86                        Err(Error::NotEnoughInputData)
87                    }
88                    Err(e) => Err(e)?,
89                    Ok(_) => Ok(Some(buf[0])),
90                }
91            }
92
93            Command::Repeat(count) => {
94                self.op = Command::Repeat(count - 1);
95                Ok(Some(self.repeated))
96            }
97        }
98    }
99
100    /// Unwrap the reader, destroying it's internal state and returning the original reader
101    ///
102    /// Note that the current position may have been changed since the reader was wrapped.
103    pub fn into_inner(self) -> T {
104        self.inner
105    }
106}
107
108impl<T: io::Read + io::Seek> Reader<T> {
109    #[inline]
110    /// Determine if the reader could possibly provide more data if read again
111    pub fn is_empty(&mut self) -> io::Result<bool> {
112        Ok(matches!(self.op, Command::Literal(0) | Command::Repeat(0))
113            && self.inner.stream_position()? >= self.inner.stream_len()?)
114    }
115}
116
117impl<T: io::Read> io::Read for Reader<T> {
118    #[inline]
119    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
120        let max_output = self.max_output.unwrap_or(u64::MAX);
121        for (idx, byte) in buf.iter_mut().enumerate() {
122            if self.position >= max_output {
123                return Ok(idx);
124            }
125
126            match self.produce_next_byte()? {
127                None => return Ok(idx),
128                Some(value) => {
129                    self.position += 1;
130                    *byte = value
131                }
132            }
133        }
134
135        Ok(buf.len())
136    }
137}
138
139impl<T: io::Read> io::Seek for Reader<T> {
140    fn seek(&mut self, _: io::SeekFrom) -> io::Result<u64> {
141        todo!()
142    }
143
144    #[inline]
145    fn stream_len(&mut self) -> io::Result<u64> {
146        if let Some(max_output) = self.max_output {
147            Ok(max_output)
148        } else {
149            Err(io::Error::other(
150                "Cannot determine stream length without max_output",
151            ))
152        }
153    }
154
155    #[inline]
156    fn stream_position(&mut self) -> io::Result<u64> {
157        Ok(self.position)
158    }
159}
160
161#[cfg(test)]
162mod test {
163    use std::io::{self, Read};
164
165    #[test]
166    fn reading_literals() {
167        let mut reader = crate::Reader::new(io::Cursor::new(b"\x01\xAB\xCD"));
168        let mut output = vec![0u8; 2];
169        let result = reader.read(&mut output);
170        assert!(matches!(result, Ok(2)));
171        assert_eq!(output, b"\xAB\xCD");
172    }
173
174    #[test]
175    fn reading_longer_values() {
176        let input = b"\xFE\xAA\x02\x80\x00\x2A\xFD\xAA\x03\x80\x00\x2A\x22\xF7\xAA";
177        let expectation = b"\xAA\xAA\xAA\x80\x00\x2A\xAA\xAA\xAA\xAA\x80\x00\x2A\x22\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
178
179        let inner = io::Cursor::new(input);
180        let mut reader = crate::Reader::new(inner);
181        let mut output = vec![0u8; 24];
182
183        let result = reader.read(&mut output);
184        assert!(matches!(result, Ok(24)));
185        assert_eq!(output, expectation);
186    }
187}