1use std::io::{self};
2
3use crate::{Command, Error};
4
5pub struct Reader<T: std::io::Read> {
7 inner: T,
9 repeated: u8,
11 op: Command,
14 max_output: Option<u64>,
16 position: u64,
18}
19
20impl<T: io::Read> Reader<T> {
21 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 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 pub fn into_inner(self) -> T {
104 self.inner
105 }
106}
107
108impl<T: io::Read + io::Seek> Reader<T> {
109 #[inline]
110 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}