1//! Implement pull-based [`Read`] trait for both compressing and decompressing.
2use std::io::{self, BufRead, BufReader, Read};
34use crate::dict::{DecoderDictionary, EncoderDictionary};
5use crate::stream::{raw, zio};
6use zstd_safe;
78#[cfg(test)]
9mod tests;
1011/// 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}
1819/// An encoder that compress input data from another `Read`.
20pub struct Encoder<'a, R> {
21 reader: zio::Reader<R, raw::Encoder<'a>>,
22}
2324impl<R: Read> Decoder<'static, BufReader<R>> {
25/// Creates a new decoder.
26pub fn new(reader: R) -> io::Result<Self> {
27let buffer_size = zstd_safe::DCtx::in_size();
2829Self::with_buffer(BufReader::with_capacity(buffer_size, reader))
30 }
31}
3233impl<R: BufRead> Decoder<'static, R> {
34/// Creates a new decoder around a `BufRead`.
35pub fn with_buffer(reader: R) -> io::Result<Self> {
36Self::with_dictionary(reader, &[])
37 }
38/// Creates a new decoder, using an existing dictionary.
39 ///
40 /// The dictionary must be the same as the one used during compression.
41pub fn with_dictionary(reader: R, dictionary: &[u8]) -> io::Result<Self> {
42let decoder = raw::Decoder::with_dictionary(dictionary)?;
43let reader = zio::Reader::new(reader, decoder);
4445Ok(Decoder { reader })
46 }
47}
48impl<'a, R: BufRead> Decoder<'a, R> {
49/// Creates a new decoder which employs the provided context for deserialization.
50pub fn with_context(
51 reader: R,
52 context: &'a mut zstd_safe::DCtx<'static>,
53 ) -> Self {
54Self {
55 reader: zio::Reader::new(
56 reader,
57 raw::Decoder::with_context(context),
58 ),
59 }
60 }
6162/// Sets this `Decoder` to stop after the first frame.
63 ///
64 /// By default, it keeps concatenating frames until EOF is reached.
65#[must_use]
66pub fn single_frame(mut self) -> Self {
67self.reader.set_single_frame();
68self
69}
7071/// Creates a new decoder, using an existing `DecoderDictionary`.
72 ///
73 /// The dictionary must be the same as the one used during compression.
74pub fn with_prepared_dictionary<'b>(
75 reader: R,
76 dictionary: &DecoderDictionary<'b>,
77 ) -> io::Result<Self>
78where
79'b: 'a,
80 {
81let decoder = raw::Decoder::with_prepared_dictionary(dictionary)?;
82let reader = zio::Reader::new(reader, decoder);
8384Ok(Decoder { reader })
85 }
8687/// Creates a new decoder, using a ref prefix.
88 ///
89 /// The prefix must be the same as the one used during compression.
90pub fn with_ref_prefix<'b>(
91 reader: R,
92 ref_prefix: &'b [u8],
93 ) -> io::Result<Self>
94where
95'b: 'a,
96 {
97let decoder = raw::Decoder::with_ref_prefix(ref_prefix)?;
98let reader = zio::Reader::new(reader, decoder);
99100Ok(Decoder { reader })
101 }
102103/// Recommendation for the size of the output buffer.
104pub fn recommended_output_size() -> usize {
105 zstd_safe::DCtx::out_size()
106 }
107108/// Acquire a reference to the underlying reader.
109pub fn get_ref(&self) -> &R {
110self.reader.reader()
111 }
112113/// Acquire a mutable reference to the underlying reader.
114 ///
115 /// Note that mutation of the reader may result in surprising results if
116 /// this decoder is continued to be used.
117pub fn get_mut(&mut self) -> &mut R {
118self.reader.reader_mut()
119 }
120121/// Return the inner `Read`.
122 ///
123 /// Calling `finish()` is not *required* after reading a stream -
124 /// just use it if you need to get the `Read` back.
125pub fn finish(self) -> R {
126self.reader.into_inner()
127 }
128129crate::decoder_common!(reader);
130}
131132impl<R: BufRead> Read for Decoder<'_, R> {
133fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
134self.reader.read(buf)
135 }
136}
137138impl<R: Read> Encoder<'static, BufReader<R>> {
139/// Creates a new encoder.
140pub fn new(reader: R, level: i32) -> io::Result<Self> {
141let buffer_size = zstd_safe::CCtx::in_size();
142143Self::with_buffer(BufReader::with_capacity(buffer_size, reader), level)
144 }
145}
146147impl<R: BufRead> Encoder<'static, R> {
148/// Creates a new encoder around a `BufRead`.
149pub fn with_buffer(reader: R, level: i32) -> io::Result<Self> {
150Self::with_dictionary(reader, level, &[])
151 }
152153/// Creates a new encoder, using an existing dictionary.
154 ///
155 /// The dictionary must be the same as the one used during compression.
156pub fn with_dictionary(
157 reader: R,
158 level: i32,
159 dictionary: &[u8],
160 ) -> io::Result<Self> {
161let encoder = raw::Encoder::with_dictionary(level, dictionary)?;
162let reader = zio::Reader::new(reader, encoder);
163164Ok(Encoder { reader })
165 }
166}
167168impl<'a, R: BufRead> Encoder<'a, R> {
169/// Creates a new encoder, using an existing `EncoderDictionary`.
170 ///
171 /// The dictionary must be the same as the one used during compression.
172pub fn with_prepared_dictionary<'b>(
173 reader: R,
174 dictionary: &EncoderDictionary<'b>,
175 ) -> io::Result<Self>
176where
177'b: 'a,
178 {
179let encoder = raw::Encoder::with_prepared_dictionary(dictionary)?;
180let reader = zio::Reader::new(reader, encoder);
181182Ok(Encoder { reader })
183 }
184185/// Recommendation for the size of the output buffer.
186pub fn recommended_output_size() -> usize {
187 zstd_safe::CCtx::out_size()
188 }
189190/// Acquire a reference to the underlying reader.
191pub fn get_ref(&self) -> &R {
192self.reader.reader()
193 }
194195/// Acquire a mutable reference to the underlying reader.
196 ///
197 /// Note that mutation of the reader may result in surprising results if
198 /// this encoder is continued to be used.
199pub fn get_mut(&mut self) -> &mut R {
200self.reader.reader_mut()
201 }
202203/// Flush any internal buffer.
204 ///
205 /// This ensures all input consumed so far is compressed.
206 ///
207 /// Since it prevents bundling currently buffered data with future input,
208 /// it may affect compression ratio.
209 ///
210 /// * Returns the number of bytes written to `out`.
211 /// * Returns `Ok(0)` when everything has been flushed.
212pub fn flush(&mut self, out: &mut [u8]) -> io::Result<usize> {
213self.reader.flush(out)
214 }
215216/// Return the inner `Read`.
217 ///
218 /// Calling `finish()` is not *required* after reading a stream -
219 /// just use it if you need to get the `Read` back.
220pub fn finish(self) -> R {
221self.reader.into_inner()
222 }
223224crate::encoder_common!(reader);
225}
226227impl<R: BufRead> Read for Encoder<'_, R> {
228fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
229self.reader.read(buf)
230 }
231}
232233fn _assert_traits() {
234use std::io::Cursor;
235236fn _assert_send<T: Send>(_: T) {}
237238 _assert_send(Decoder::new(Cursor::new(Vec::new())));
239 _assert_send(Encoder::new(Cursor::new(Vec::new()), 1));
240}