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 // Whether the operation has consumed any input yet.
22 // Until then, `!finished_frame` does not mean we are inside a frame.
23 started: bool,
24}
25
26enum State {
27 // Still actively reading from the inner `Read`
28 Reading,
29 // We reached EOF from the inner `Read`, now flushing.
30 PastEof,
31 // We are fully done, nothing can be read.
32 Finished,
33}
34
35impl<R, D> Reader<R, D> {
36 /// Creates a new `Reader`.
37 ///
38 /// `reader` will be used to pull input data for the given operation.
39 pub fn new(reader: R, operation: D) -> Self {
40 Reader {
41 reader,
42 operation,
43 state: State::Reading,
44 single_frame: false,
45 finished_frame: false,
46 started: false,
47 }
48 }
49
50 /// Sets `self` to stop after the first decoded frame.
51 pub fn set_single_frame(&mut self) {
52 self.single_frame = true;
53 }
54
55 /// Returns a mutable reference to the underlying operation.
56 pub fn operation_mut(&mut self) -> &mut D {
57 &mut self.operation
58 }
59
60 /// Returns a mutable reference to the underlying reader.
61 pub fn reader_mut(&mut self) -> &mut R {
62 &mut self.reader
63 }
64
65 /// Returns a reference to the underlying reader.
66 pub fn reader(&self) -> &R {
67 &self.reader
68 }
69
70 /// Returns the inner reader.
71 pub fn into_inner(self) -> R {
72 self.reader
73 }
74
75 /// Flush any internal buffer.
76 ///
77 /// For encoders, this ensures all input consumed so far is compressed.
78 pub fn flush(&mut self, output: &mut [u8]) -> io::Result<usize>
79 where
80 D: Operation,
81 {
82 self.operation.flush(&mut OutBuffer::around(output))
83 }
84}
85
86impl<R, D> Reader<R, D>
87where
88 R: BufRead,
89 D: Operation,
90{
91 /// Consume the rest of the current frame from the underlying reader.
92 ///
93 /// Once all the decoded data has been read, zstd may still not have
94 /// consumed the tail of the frame: it can produce the last of the output
95 /// before reading the frame epilogue. The underlying reader is then left
96 /// pointing somewhere inside the frame rather than just after it.
97 ///
98 /// This feeds zstd the input it still needs, with no room for output, so
99 /// the reader ends up positioned exactly at the end of the frame.
100 ///
101 /// It stops there: it will not start decoding whatever follows, so a
102 /// stream of concatenated frames keeps its remaining frames, and trailing
103 /// non-zstd data is left untouched.
104 ///
105 /// This is a no-op if the current frame is already complete, or if no
106 /// frame has been started yet, so it will not read from the underlying
107 /// reader in those cases.
108 pub fn finish_frame(&mut self) -> io::Result<()> {
109 // Only pull on the reader if zstd is actually waiting for the rest of
110 // a frame. Otherwise this could block on a stream - a socket, say -
111 // that has nothing more to give.
112 if !self.started
113 || self.finished_frame
114 || !matches!(self.state, State::Reading)
115 {
116 return Ok(());
117 }
118
119 loop {
120 let bytes_read = {
121 let input = fill_buf(&mut self.reader)?;
122 if input.is_empty() {
123 return Ok(());
124 }
125
126 let mut src = InBuffer::around(input);
127 // No output space: zstd will only consume the input backing
128 // the output it has already handed us, and stops at the end of
129 // the frame rather than starting the next one.
130 let mut dst = OutBuffer::around(&mut [][..]);
131
132 let hint = self.operation.run(&mut src, &mut dst)?;
133 if hint == 0 {
134 self.finished_frame = true;
135 if self.single_frame {
136 self.state = State::Finished;
137 }
138 }
139
140 src.pos()
141 };
142
143 self.reader.consume(bytes_read);
144
145 // Either we reached the end of the frame, or we cannot make any
146 // more progress without somewhere to put the output.
147 if self.finished_frame || bytes_read == 0 {
148 return Ok(());
149 }
150 }
151 }
152}
153// Read and retry on Interrupted errors.
154fn fill_buf<R>(reader: &mut R) -> io::Result<&[u8]>
155where
156 R: BufRead,
157{
158 // This doesn't work right now because of the borrow-checker.
159 // When it can be made to compile, it would allow Reader to automatically
160 // retry on `Interrupted` error.
161 /*
162 loop {
163 match reader.fill_buf() {
164 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
165 otherwise => return otherwise,
166 }
167 }
168 */
169
170 // Workaround for now
171 let res = reader.fill_buf()?;
172
173 // eprintln!("Filled buffer: {:?}", res);
174
175 Ok(res)
176}
177
178impl<R, D> Read for Reader<R, D>
179where
180 R: BufRead,
181 D: Operation,
182{
183 /// Reads everything the operation produces into `buf`.
184 ///
185 /// The default implementation has an awkward ending: when the output
186 /// happens to fill the vector exactly, it doubles the capacity and
187 /// reallocates - copying everything decoded so far - then reads zero bytes
188 /// and truncates back. Probing with a small stack buffer first establishes
189 /// there is nothing left without paying for that. Whether the saving shows
190 /// up depends on the allocator: one that can grow a large block in place
191 /// makes it cheap, one that has to copy does not.
192 ///
193 /// This should be deleted once `Read::read_buf` is stable. std can then
194 /// fill spare capacity without initializing it first, which removes both
195 /// the reallocation and the zeroing this does by hand, and its version
196 /// will be the better one.
197 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
198 let start = buf.len();
199 let mut written = start;
200 loop {
201 let result = if written == buf.capacity() {
202 // Check for EOF before growing a full (or empty) vector.
203 let mut probe = [0; 32];
204 self.read(&mut probe).map(|n| {
205 buf.extend_from_slice(&probe[..n]);
206 n
207 })
208 } else {
209 // Initialize only one block of spare capacity at a time.
210 // Keep it initialized across short reads so we don't repeatedly
211 // zero the same space. Bounded slices retain streaming behavior.
212 if written == buf.len() {
213 let chunk = (buf.capacity() - written)
214 .min(zstd_safe::BLOCKSIZE_MAX as usize);
215 buf.resize(written + chunk, 0);
216 }
217 self.read(&mut buf[written..])
218 };
219 match result {
220 Ok(0) => {
221 buf.truncate(written);
222 return Ok(written - start);
223 }
224 Ok(n) => written += n,
225 Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
226 Err(e) => {
227 buf.truncate(written);
228 return Err(e);
229 }
230 }
231 }
232 }
233
234 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
235 // `Read::read` is specified to return `Ok(0)` for an empty buffer.
236 // Without this, the loop below would keep asking the operation to write
237 // into no space at all, until zstd gives up with a "no progress" error.
238 if buf.is_empty() {
239 return Ok(0);
240 }
241
242 // Keep trying until _something_ has been written.
243 let mut first = true;
244 loop {
245 match self.state {
246 State::Reading => {
247 let (bytes_read, bytes_written) = {
248 // Start with a fresh pool of un-processed data.
249 // This is the only line that can return an interruption error.
250 let input = if first {
251 // eprintln!("First run, no input coming.");
252 b""
253 } else {
254 fill_buf(&mut self.reader)?
255 };
256
257 // eprintln!("Input = {:?}", input);
258
259 // It's possible we don't have any new data to read.
260 // (In this case we may still have zstd's own buffer to clear.)
261 if !first && input.is_empty() {
262 self.state = State::PastEof;
263 continue;
264 }
265 first = false;
266
267 let mut src = InBuffer::around(input);
268 let mut dst = OutBuffer::around(buf);
269
270 // We don't want empty input (from first=true) to cause a frame
271 // re-initialization.
272 if self.finished_frame && !input.is_empty() {
273 // eprintln!("!! Reigniting !!");
274 self.operation.reinit()?;
275 self.finished_frame = false;
276 }
277
278 // Phase 1: feed input to the operation
279 let hint = self.operation.run(&mut src, &mut dst)?;
280 // eprintln!(
281 // "Hint={} Just run our operation:\n In={:?}\n Out={:?}",
282 // hint, src, dst
283 // );
284
285 if hint == 0 {
286 // In practice this only happens when decoding, when we just finished
287 // reading a frame.
288 self.finished_frame = true;
289 if self.single_frame {
290 self.state = State::Finished;
291 }
292 }
293
294 // eprintln!("Output: {:?}", dst);
295
296 (src.pos(), dst.pos())
297 };
298
299 self.reader.consume(bytes_read);
300 self.started |= bytes_read > 0;
301
302 if bytes_written > 0 {
303 return Ok(bytes_written);
304 }
305
306 // We need more data! Try again!
307 }
308 State::PastEof => {
309 let mut dst = OutBuffer::around(buf);
310
311 // We already sent all the input we could get to zstd. Time to flush out the
312 // buffer and be done with it.
313
314 // Phase 2: flush out the operation's buffer
315 // Keep calling `finish()` until the buffer is empty.
316 let hint = self
317 .operation
318 .finish(&mut dst, self.finished_frame)?;
319 // eprintln!("Hint: {} ; Output: {:?}", hint, dst);
320 if hint == 0 {
321 // This indicates that the footer is complete.
322 // This is the only way to terminate the stream cleanly.
323 self.state = State::Finished;
324 }
325
326 return Ok(dst.pos());
327 }
328 State::Finished => {
329 return Ok(0);
330 }
331 }
332 }
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::Reader;
339 use std::io::{Cursor, Read};
340
341 #[test]
342 fn test_noop() {
343 use crate::stream::raw::NoOp;
344
345 let input = b"AbcdefghAbcdefgh.";
346
347 // Test reader
348 let mut output = Vec::new();
349 {
350 let mut reader = Reader::new(Cursor::new(input), NoOp);
351 reader.read_to_end(&mut output).unwrap();
352 }
353 assert_eq!(&output, input);
354 }
355
356 #[test]
357 fn test_noop_read_to_end_appends_across_chunks() {
358 use crate::stream::raw::NoOp;
359
360 let input = vec![42; zstd_safe::BLOCKSIZE_MAX as usize + 17];
361 for spare in [0, 1, input.len(), input.len() + 1] {
362 let mut output = Vec::with_capacity(6 + spare);
363 output.extend_from_slice(b"prefix");
364 let mut reader = Reader::new(&input[..], NoOp);
365 assert_eq!(reader.read_to_end(&mut output).unwrap(), input.len());
366 assert_eq!(&output[..6], b"prefix");
367 assert_eq!(&output[6..], input);
368 assert_eq!(reader.read_to_end(&mut output).unwrap(), 0);
369 }
370 }
371
372 #[test]
373 fn test_compress() {
374 use crate::stream::raw::Encoder;
375
376 let input = b"AbcdefghAbcdefgh.";
377
378 // Test reader
379 let mut output = Vec::new();
380 {
381 let mut reader =
382 Reader::new(Cursor::new(input), Encoder::new(1).unwrap());
383 reader.read_to_end(&mut output).unwrap();
384 }
385 // eprintln!("{:?}", output);
386 let decoded = crate::decode_all(&output[..]).unwrap();
387 assert_eq!(&decoded, input);
388 }
389}