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}