Skip to main content

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}