zstd/stream/zio/reader.rs
1use std::io::{self, BufRead, Read};
2
3use crate::stream::raw::{InBuffer, Operation, OutBuffer};
4
5// [ reader -> zstd ] -> output
6/// Implements the [`Read`] API around an [`Operation`].
7///
8/// This can be used to wrap a raw in-memory operation in a read-focused API.
9///
10/// It can wrap either a compression or decompression operation, and pulls
11/// input data from a wrapped `Read`.
12pub struct Reader<R, D> {
13 reader: R,
14 operation: D,
15
16 state: State,
17
18 single_frame: bool,
19 finished_frame: bool,
20}
21
22enum State {
23 // Still actively reading from the inner `Read`
24 Reading,
25 // We reached EOF from the inner `Read`, now flushing.
26 PastEof,
27 // We are fully done, nothing can be read.
28 Finished,
29}
30
31impl<R, D> Reader<R, D> {
32 /// Creates a new `Reader`.
33 ///
34 /// `reader` will be used to pull input data for the given operation.
35 pub fn new(reader: R, operation: D) -> Self {
36 Reader {
37 reader,
38 operation,
39 state: State::Reading,
40 single_frame: false,
41 finished_frame: false,
42 }
43 }
44
45 /// Sets `self` to stop after the first decoded frame.
46 pub fn set_single_frame(&mut self) {
47 self.single_frame = true;
48 }
49
50 /// Returns a mutable reference to the underlying operation.
51 pub fn operation_mut(&mut self) -> &mut D {
52 &mut self.operation
53 }
54
55 /// Returns a mutable reference to the underlying reader.
56 pub fn reader_mut(&mut self) -> &mut R {
57 &mut self.reader
58 }
59
60 /// Returns a reference to the underlying reader.
61 pub fn reader(&self) -> &R {
62 &self.reader
63 }
64
65 /// Returns the inner reader.
66 pub fn into_inner(self) -> R {
67 self.reader
68 }
69
70 /// Flush any internal buffer.
71 ///
72 /// For encoders, this ensures all input consumed so far is compressed.
73 pub fn flush(&mut self, output: &mut [u8]) -> io::Result<usize>
74 where
75 D: Operation,
76 {
77 self.operation.flush(&mut OutBuffer::around(output))
78 }
79}
80
81impl<R, D> Reader<R, D>
82where
83 R: BufRead,
84 D: Operation,
85{
86 /// Consume the rest of the current frame from the underlying reader.
87 ///
88 /// Once all the decoded data has been read, zstd may still not have
89 /// consumed the tail of the frame: it can produce the last of the output
90 /// before reading the frame epilogue. The underlying reader is then left
91 /// pointing somewhere inside the frame rather than just after it.
92 ///
93 /// This feeds zstd the input it still needs, with no room for output, so
94 /// the reader ends up positioned exactly at the end of the frame.
95 ///
96 /// It stops there: it will not start decoding whatever follows, so a
97 /// stream of concatenated frames keeps its remaining frames, and trailing
98 /// non-zstd data is left untouched.
99 ///
100 /// This is a no-op if the current frame is already complete, so it will
101 /// not read from the underlying reader in that case.
102 pub fn finish_frame(&mut self) -> io::Result<()> {
103 // Only pull on the reader if zstd is actually waiting for the rest of
104 // a frame. Otherwise this could block on a stream - a socket, say -
105 // that has nothing more to give.
106 if self.finished_frame || !matches!(self.state, State::Reading) {
107 return Ok(());
108 }
109
110 loop {
111 let bytes_read = {
112 let input = fill_buf(&mut self.reader)?;
113 if input.is_empty() {
114 return Ok(());
115 }
116
117 let mut src = InBuffer::around(input);
118 // No output space: zstd will only consume the input backing
119 // the output it has already handed us, and stops at the end of
120 // the frame rather than starting the next one.
121 let mut dst = OutBuffer::around(&mut [][..]);
122
123 let hint = self.operation.run(&mut src, &mut dst)?;
124 if hint == 0 {
125 self.finished_frame = true;
126 }
127
128 src.pos()
129 };
130
131 self.reader.consume(bytes_read);
132
133 // Either we reached the end of the frame, or we cannot make any
134 // more progress without somewhere to put the output.
135 if self.finished_frame || bytes_read == 0 {
136 return Ok(());
137 }
138 }
139 }
140}
141// Read and retry on Interrupted errors.
142fn fill_buf<R>(reader: &mut R) -> io::Result<&[u8]>
143where
144 R: BufRead,
145{
146 // This doesn't work right now because of the borrow-checker.
147 // When it can be made to compile, it would allow Reader to automatically
148 // retry on `Interrupted` error.
149 /*
150 loop {
151 match reader.fill_buf() {
152 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
153 otherwise => return otherwise,
154 }
155 }
156 */
157
158 // Workaround for now
159 let res = reader.fill_buf()?;
160
161 // eprintln!("Filled buffer: {:?}", res);
162
163 Ok(res)
164}
165
166impl<R, D> Read for Reader<R, D>
167where
168 R: BufRead,
169 D: Operation,
170{
171 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
172 // `Read::read` is specified to return `Ok(0)` for an empty buffer.
173 // Without this, the loop below would keep asking the operation to write
174 // into no space at all, until zstd gives up with a "no progress" error.
175 if buf.is_empty() {
176 return Ok(0);
177 }
178
179 // Keep trying until _something_ has been written.
180 let mut first = true;
181 loop {
182 match self.state {
183 State::Reading => {
184 let (bytes_read, bytes_written) = {
185 // Start with a fresh pool of un-processed data.
186 // This is the only line that can return an interruption error.
187 let input = if first {
188 // eprintln!("First run, no input coming.");
189 b""
190 } else {
191 fill_buf(&mut self.reader)?
192 };
193
194 // eprintln!("Input = {:?}", input);
195
196 // It's possible we don't have any new data to read.
197 // (In this case we may still have zstd's own buffer to clear.)
198 if !first && input.is_empty() {
199 self.state = State::PastEof;
200 continue;
201 }
202 first = false;
203
204 let mut src = InBuffer::around(input);
205 let mut dst = OutBuffer::around(buf);
206
207 // We don't want empty input (from first=true) to cause a frame
208 // re-initialization.
209 if self.finished_frame && !input.is_empty() {
210 // eprintln!("!! Reigniting !!");
211 self.operation.reinit()?;
212 self.finished_frame = false;
213 }
214
215 // Phase 1: feed input to the operation
216 let hint = self.operation.run(&mut src, &mut dst)?;
217 // eprintln!(
218 // "Hint={} Just run our operation:\n In={:?}\n Out={:?}",
219 // hint, src, dst
220 // );
221
222 if hint == 0 {
223 // In practice this only happens when decoding, when we just finished
224 // reading a frame.
225 self.finished_frame = true;
226 if self.single_frame {
227 self.state = State::Finished;
228 }
229 }
230
231 // eprintln!("Output: {:?}", dst);
232
233 (src.pos(), dst.pos())
234 };
235
236 self.reader.consume(bytes_read);
237
238 if bytes_written > 0 {
239 return Ok(bytes_written);
240 }
241
242 // We need more data! Try again!
243 }
244 State::PastEof => {
245 let mut dst = OutBuffer::around(buf);
246
247 // We already sent all the input we could get to zstd. Time to flush out the
248 // buffer and be done with it.
249
250 // Phase 2: flush out the operation's buffer
251 // Keep calling `finish()` until the buffer is empty.
252 let hint = self
253 .operation
254 .finish(&mut dst, self.finished_frame)?;
255 // eprintln!("Hint: {} ; Output: {:?}", hint, dst);
256 if hint == 0 {
257 // This indicates that the footer is complete.
258 // This is the only way to terminate the stream cleanly.
259 self.state = State::Finished;
260 }
261
262 return Ok(dst.pos());
263 }
264 State::Finished => {
265 return Ok(0);
266 }
267 }
268 }
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::Reader;
275 use std::io::{Cursor, Read};
276
277 #[test]
278 fn test_noop() {
279 use crate::stream::raw::NoOp;
280
281 let input = b"AbcdefghAbcdefgh.";
282
283 // Test reader
284 let mut output = Vec::new();
285 {
286 let mut reader = Reader::new(Cursor::new(input), NoOp);
287 reader.read_to_end(&mut output).unwrap();
288 }
289 assert_eq!(&output, input);
290 }
291
292 #[test]
293 fn test_compress() {
294 use crate::stream::raw::Encoder;
295
296 let input = b"AbcdefghAbcdefgh.";
297
298 // Test reader
299 let mut output = Vec::new();
300 {
301 let mut reader =
302 Reader::new(Cursor::new(input), Encoder::new(1).unwrap());
303 reader.read_to_end(&mut output).unwrap();
304 }
305 // eprintln!("{:?}", output);
306 let decoded = crate::decode_all(&output[..]).unwrap();
307 assert_eq!(&decoded, input);
308 }
309}