Skip to main content

zstd/stream/read/
mod.rs

1//! Implement pull-based [`Read`] trait for both compressing and decompressing.
2use std::io::{self, BufRead, BufReader, Read};
3
4use crate::dict::{DecoderDictionary, EncoderDictionary};
5use crate::stream::{raw, zio};
6use zstd_safe;
7
8#[cfg(test)]
9mod tests;
10
11/// A decoder that decompress input data from another `Read`.
12///
13/// This allows to read a stream of compressed data
14/// (good for files or heavy network stream).
15pub struct Decoder<'a, R> {
16    reader: zio::Reader<R, raw::Decoder<'a>>,
17}
18
19/// An encoder that compress input data from another `Read`.
20pub struct Encoder<'a, R> {
21    reader: zio::Reader<R, raw::Encoder<'a>>,
22}
23
24impl<R: Read> Decoder<'static, BufReader<R>> {
25    /// Creates a new decoder.
26    ///
27    /// This wraps `reader` in a `BufReader` sized the way zstd likes, so there
28    /// is no need to do that yourself. If what you have already implements
29    /// `BufRead` - a `&[u8]`, say - use [`Decoder::with_buffer()`] instead and
30    /// save the second layer of buffering.
31    ///
32    /// Use [`Self::try_new()`] to recover the reader if initialization fails.
33    pub fn new(reader: R) -> io::Result<Self> {
34        Self::try_new(reader).map_err(|(_, error)| error)
35    }
36
37    /// Creates a new decoder, returning the original reader on error.
38    ///
39    /// Like [`Self::new()`], this wraps the reader in a `BufReader` on
40    /// success. On error, it returns the original `R`, without buffering.
41    /// Construction does not read from or consume the reader.
42    pub fn try_new(reader: R) -> Result<Self, (R, io::Error)> {
43        let decoder = match raw::Decoder::new() {
44            Ok(decoder) => decoder,
45            Err(error) => return Err((reader, error)),
46        };
47        let reader =
48            BufReader::with_capacity(zstd_safe::DCtx::in_size(), reader);
49        Ok(Self {
50            reader: zio::Reader::new(reader, decoder),
51        })
52    }
53}
54
55impl<R: BufRead> Decoder<'static, R> {
56    /// Creates a new decoder around a `BufRead`.
57    ///
58    /// Unlike [`Decoder::new()`], this adds no buffering of its own, so give
59    /// it something with a reasonable buffer already - `new` uses zstd's
60    /// preferred input size for exactly that reason.
61    ///
62    /// Use [`Self::try_with_buffer()`] to recover the reader if initialization
63    /// fails.
64    pub fn with_buffer(reader: R) -> io::Result<Self> {
65        Self::try_with_buffer(reader).map_err(|(_, error)| error)
66    }
67
68    /// Creates a decoder around a `BufRead`, returning the reader on error.
69    ///
70    /// Like [`Self::with_buffer()`], this adds no buffering of its own.
71    /// Construction does not read from or consume the reader.
72    pub fn try_with_buffer(reader: R) -> Result<Self, (R, io::Error)> {
73        Self::try_with_dictionary(reader, &[])
74    }
75
76    /// Creates a new decoder, using an existing dictionary.
77    ///
78    /// The dictionary must be the same as the one used during compression.
79    ///
80    /// Use [`Self::try_with_dictionary()`] to recover the reader if
81    /// initialization fails.
82    pub fn with_dictionary(reader: R, dictionary: &[u8]) -> io::Result<Self> {
83        Self::try_with_dictionary(reader, dictionary)
84            .map_err(|(_, error)| error)
85    }
86
87    /// Creates a decoder using a dictionary, returning the reader on error.
88    ///
89    /// The dictionary must be the same as the one used during compression.
90    /// Construction does not read from or consume the reader.
91    pub fn try_with_dictionary(
92        reader: R,
93        dictionary: &[u8],
94    ) -> Result<Self, (R, io::Error)> {
95        let decoder = match raw::Decoder::with_dictionary(dictionary) {
96            Ok(decoder) => decoder,
97            Err(error) => return Err((reader, error)),
98        };
99        let reader = zio::Reader::new(reader, decoder);
100
101        Ok(Decoder { reader })
102    }
103}
104impl<'a, R: BufRead> Decoder<'a, R> {
105    /// Creates a new decoder which employs the provided context for deserialization.
106    pub fn with_context(
107        reader: R,
108        context: &'a mut zstd_safe::DCtx<'static>,
109    ) -> Self {
110        Self {
111            reader: zio::Reader::new(
112                reader,
113                raw::Decoder::with_context(context),
114            ),
115        }
116    }
117
118    /// Sets this `Decoder` to stop after the first frame.
119    ///
120    /// By default, it keeps concatenating frames until EOF is reached.
121    #[must_use]
122    pub fn single_frame(mut self) -> Self {
123        self.reader.set_single_frame();
124        self
125    }
126
127    /// Creates a new decoder, using an existing `DecoderDictionary`.
128    ///
129    /// The dictionary must be the same as the one used during compression.
130    ///
131    /// Use [`Self::try_with_prepared_dictionary()`] to recover the reader if
132    /// initialization fails.
133    pub fn with_prepared_dictionary<'b>(
134        reader: R,
135        dictionary: &'a DecoderDictionary<'b>,
136    ) -> io::Result<Self>
137    where
138        'b: 'a,
139    {
140        Self::try_with_prepared_dictionary(reader, dictionary)
141            .map_err(|(_, error)| error)
142    }
143
144    /// Creates a decoder using a prepared dictionary, returning the reader
145    /// on error.
146    ///
147    /// The dictionary must be the same as the one used during compression.
148    /// Construction does not read from or consume the reader.
149    pub fn try_with_prepared_dictionary<'b>(
150        reader: R,
151        dictionary: &'a DecoderDictionary<'b>,
152    ) -> Result<Self, (R, io::Error)>
153    where
154        'b: 'a,
155    {
156        let decoder = match raw::Decoder::with_prepared_dictionary(dictionary)
157        {
158            Ok(decoder) => decoder,
159            Err(error) => return Err((reader, error)),
160        };
161        let reader = zio::Reader::new(reader, decoder);
162
163        Ok(Decoder { reader })
164    }
165
166    /// Creates a new decoder, using a ref prefix.
167    ///
168    /// The prefix must be the same as the one used during compression.
169    ///
170    /// Use [`Self::try_with_ref_prefix()`] to recover the reader if
171    /// initialization fails.
172    pub fn with_ref_prefix<'b>(
173        reader: R,
174        ref_prefix: &'b [u8],
175    ) -> io::Result<Self>
176    where
177        'b: 'a,
178    {
179        Self::try_with_ref_prefix(reader, ref_prefix)
180            .map_err(|(_, error)| error)
181    }
182
183    /// Creates a decoder using a reference prefix, returning the reader on
184    /// error.
185    ///
186    /// The prefix must be the same as the one used during compression.
187    /// Construction does not read from or consume the reader.
188    pub fn try_with_ref_prefix<'b>(
189        reader: R,
190        ref_prefix: &'b [u8],
191    ) -> Result<Self, (R, io::Error)>
192    where
193        'b: 'a,
194    {
195        let decoder = match raw::Decoder::with_ref_prefix(ref_prefix) {
196            Ok(decoder) => decoder,
197            Err(error) => return Err((reader, error)),
198        };
199        let reader = zio::Reader::new(reader, decoder);
200
201        Ok(Decoder { reader })
202    }
203
204    /// Recommendation for the size of the output buffer.
205    pub fn recommended_output_size() -> usize {
206        zstd_safe::DCtx::out_size()
207    }
208
209    /// Acquire a reference to the underlying reader.
210    pub fn get_ref(&self) -> &R {
211        self.reader.reader()
212    }
213
214    /// Acquire a mutable reference to the underlying reader.
215    ///
216    /// Note that mutation of the reader may result in surprising results if
217    /// this decoder is continued to be used.
218    pub fn get_mut(&mut self) -> &mut R {
219        self.reader.reader_mut()
220    }
221
222    /// Return the inner reader without consuming additional input.
223    ///
224    /// This does not read from the underlying reader or try to finish the
225    /// current frame. Any buffered decoded data is discarded, and the reader
226    /// is returned at its current position.
227    ///
228    /// Use [`Self::finish()`] to try to consume any remaining frame input
229    /// before returning the reader.
230    pub fn into_inner(self) -> R {
231        self.reader.into_inner()
232    }
233
234    /// Try to consume the remaining input from the current frame.
235    ///
236    /// zstd can hand out the last of the decoded data before it has read the
237    /// frame epilogue, so a reader that stops as soon as it has the bytes it
238    /// wanted leaves the input somewhere inside the frame. Call this to line
239    /// the reader back up with the end of the frame - for instance to carry on
240    /// reading whatever follows the compressed section.
241    ///
242    /// This does not discard unread decoded data. If there is still output
243    /// to read, it may stop before reaching the end of the frame.
244    ///
245    /// This does not touch the underlying reader if the frame is already
246    /// complete or if nothing has been read from this decoder yet, and never
247    /// starts decoding the next frame.
248    pub fn finish_frame(&mut self) -> io::Result<()> {
249        self.reader.finish_frame()
250    }
251
252    /// Return the inner `Read`.
253    ///
254    /// Calling `finish()` is not *required* after reading a stream -
255    /// just use it if you need to get the `Read` back.
256    ///
257    /// This tries to consume any remaining input from the current frame
258    /// first - see [`Self::finish_frame()`]. That may read from the underlying
259    /// reader, and any error doing so is ignored; call `finish_frame()`
260    /// directly if you need to see it.
261    ///
262    /// To return the reader without consuming additional input, use
263    /// [`Self::into_inner()`].
264    pub fn finish(mut self) -> R {
265        let _ = self.finish_frame();
266        self.into_inner()
267    }
268
269    crate::decoder_common!(reader);
270}
271
272impl<R: BufRead> Read for Decoder<'_, R> {
273    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
274        self.reader.read(buf)
275    }
276
277    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
278        self.reader.read_to_end(buf)
279    }
280}
281
282impl<R: Read> Encoder<'static, BufReader<R>> {
283    /// Creates a new encoder.
284    pub fn new(reader: R, level: i32) -> io::Result<Self> {
285        let buffer_size = zstd_safe::CCtx::in_size();
286
287        Self::with_buffer(BufReader::with_capacity(buffer_size, reader), level)
288    }
289}
290
291impl<R: BufRead> Encoder<'static, R> {
292    /// Creates a new encoder around a `BufRead`.
293    pub fn with_buffer(reader: R, level: i32) -> io::Result<Self> {
294        Self::with_dictionary(reader, level, &[])
295    }
296
297    /// Creates a new encoder, using an existing dictionary.
298    ///
299    /// The dictionary must be the same as the one used during compression.
300    pub fn with_dictionary(
301        reader: R,
302        level: i32,
303        dictionary: &[u8],
304    ) -> io::Result<Self> {
305        let encoder = raw::Encoder::with_dictionary(level, dictionary)?;
306        let reader = zio::Reader::new(reader, encoder);
307
308        Ok(Encoder { reader })
309    }
310}
311
312impl<'a, R: BufRead> Encoder<'a, R> {
313    /// Creates a new encoder which employs the provided context for serialization.
314    pub fn with_context(
315        reader: R,
316        context: &'a mut zstd_safe::CCtx<'static>,
317    ) -> Self {
318        Self {
319            reader: zio::Reader::new(
320                reader,
321                raw::Encoder::with_context(context),
322            ),
323        }
324    }
325
326    /// Creates a new encoder, using an existing `EncoderDictionary`.
327    ///
328    /// The dictionary must be the same as the one used during compression.
329    pub fn with_prepared_dictionary<'b>(
330        reader: R,
331        dictionary: &'a EncoderDictionary<'b>,
332    ) -> io::Result<Self>
333    where
334        'b: 'a,
335    {
336        let encoder = raw::Encoder::with_prepared_dictionary(dictionary)?;
337        let reader = zio::Reader::new(reader, encoder);
338
339        Ok(Encoder { reader })
340    }
341
342    /// Recommendation for the size of the output buffer.
343    pub fn recommended_output_size() -> usize {
344        zstd_safe::CCtx::out_size()
345    }
346
347    /// Acquire a reference to the underlying reader.
348    pub fn get_ref(&self) -> &R {
349        self.reader.reader()
350    }
351
352    /// Acquire a mutable reference to the underlying reader.
353    ///
354    /// Note that mutation of the reader may result in surprising results if
355    /// this encoder is continued to be used.
356    pub fn get_mut(&mut self) -> &mut R {
357        self.reader.reader_mut()
358    }
359
360    /// Flush any internal buffer.
361    ///
362    /// This ensures all input consumed so far is compressed.
363    ///
364    /// Since it prevents bundling currently buffered data with future input,
365    /// it may affect compression ratio.
366    ///
367    /// * Returns the number of bytes written to `out`.
368    /// * Returns `Ok(0)` when everything has been flushed.
369    pub fn flush(&mut self, out: &mut [u8]) -> io::Result<usize> {
370        self.reader.flush(out)
371    }
372
373    /// Return the inner `Read`.
374    ///
375    /// Calling `finish()` is not *required* after reading a stream -
376    /// just use it if you need to get the `Read` back.
377    pub fn finish(self) -> R {
378        self.reader.into_inner()
379    }
380
381    crate::encoder_common!(reader);
382}
383
384impl<R: BufRead> Read for Encoder<'_, R> {
385    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
386        self.reader.read(buf)
387    }
388}
389
390fn _assert_traits() {
391    use std::io::Cursor;
392
393    fn _assert_send<T: Send>(_: T) {}
394
395    _assert_send(Decoder::new(Cursor::new(Vec::new())));
396    _assert_send(Encoder::new(Cursor::new(Vec::new()), 1));
397}