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: BufRead> {
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: BufRead> {
21    reader: zio::Reader<R, raw::Encoder<'a>>,
22}
23
24impl<R: Read> Decoder<'static, BufReader<R>> {
25    /// Creates a new decoder.
26    pub fn new(reader: R) -> io::Result<Self> {
27        let buffer_size = zstd_safe::DCtx::in_size();
28
29        Self::with_buffer(BufReader::with_capacity(buffer_size, reader))
30    }
31}
32
33impl<R: BufRead> Decoder<'static, R> {
34    /// Creates a new decoder around a `BufRead`.
35    pub fn with_buffer(reader: R) -> io::Result<Self> {
36        Self::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.
41    pub fn with_dictionary(reader: R, dictionary: &[u8]) -> io::Result<Self> {
42        let decoder = raw::Decoder::with_dictionary(dictionary)?;
43        let reader = zio::Reader::new(reader, decoder);
44
45        Ok(Decoder { reader })
46    }
47}
48impl<'a, R: BufRead> Decoder<'a, R> {
49    /// Sets this `Decoder` to stop after the first frame.
50    ///
51    /// By default, it keeps concatenating frames until EOF is reached.
52    #[must_use]
53    pub fn single_frame(mut self) -> Self {
54        self.reader.set_single_frame();
55        self
56    }
57
58    /// Creates a new decoder, using an existing `DecoderDictionary`.
59    ///
60    /// The dictionary must be the same as the one used during compression.
61    pub fn with_prepared_dictionary<'b>(
62        reader: R,
63        dictionary: &DecoderDictionary<'b>,
64    ) -> io::Result<Self>
65    where
66        'b: 'a,
67    {
68        let decoder = raw::Decoder::with_prepared_dictionary(dictionary)?;
69        let reader = zio::Reader::new(reader, decoder);
70
71        Ok(Decoder { reader })
72    }
73
74    /// Recommendation for the size of the output buffer.
75    pub fn recommended_output_size() -> usize {
76        zstd_safe::DCtx::out_size()
77    }
78
79    /// Acquire a reference to the underlying reader.
80    pub fn get_ref(&self) -> &R {
81        self.reader.reader()
82    }
83
84    /// Acquire a mutable reference to the underlying reader.
85    ///
86    /// Note that mutation of the reader may result in surprising results if
87    /// this decoder is continued to be used.
88    pub fn get_mut(&mut self) -> &mut R {
89        self.reader.reader_mut()
90    }
91
92    /// Return the inner `Read`.
93    ///
94    /// Calling `finish()` is not *required* after reading a stream -
95    /// just use it if you need to get the `Read` back.
96    pub fn finish(self) -> R {
97        self.reader.into_inner()
98    }
99
100    crate::decoder_common!(reader);
101}
102
103impl<R: BufRead> Read for Decoder<'_, R> {
104    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
105        self.reader.read(buf)
106    }
107}
108
109impl<R: Read> Encoder<'static, BufReader<R>> {
110    /// Creates a new encoder.
111    pub fn new(reader: R, level: i32) -> io::Result<Self> {
112        let buffer_size = zstd_safe::CCtx::in_size();
113
114        Self::with_buffer(BufReader::with_capacity(buffer_size, reader), level)
115    }
116}
117
118impl<R: BufRead> Encoder<'static, R> {
119    /// Creates a new encoder around a `BufRead`.
120    pub fn with_buffer(reader: R, level: i32) -> io::Result<Self> {
121        Self::with_dictionary(reader, level, &[])
122    }
123
124    /// Creates a new encoder, using an existing dictionary.
125    ///
126    /// The dictionary must be the same as the one used during compression.
127    pub fn with_dictionary(
128        reader: R,
129        level: i32,
130        dictionary: &[u8],
131    ) -> io::Result<Self> {
132        let encoder = raw::Encoder::with_dictionary(level, dictionary)?;
133        let reader = zio::Reader::new(reader, encoder);
134
135        Ok(Encoder { reader })
136    }
137}
138
139impl<'a, R: BufRead> Encoder<'a, R> {
140    /// Creates a new encoder, using an existing `EncoderDictionary`.
141    ///
142    /// The dictionary must be the same as the one used during compression.
143    pub fn with_prepared_dictionary<'b>(
144        reader: R,
145        dictionary: &EncoderDictionary<'b>,
146    ) -> io::Result<Self>
147    where
148        'b: 'a,
149    {
150        let encoder = raw::Encoder::with_prepared_dictionary(dictionary)?;
151        let reader = zio::Reader::new(reader, encoder);
152
153        Ok(Encoder { reader })
154    }
155
156    /// Recommendation for the size of the output buffer.
157    pub fn recommended_output_size() -> usize {
158        zstd_safe::CCtx::out_size()
159    }
160
161    /// Acquire a reference to the underlying reader.
162    pub fn get_ref(&self) -> &R {
163        self.reader.reader()
164    }
165
166    /// Acquire a mutable reference to the underlying reader.
167    ///
168    /// Note that mutation of the reader may result in surprising results if
169    /// this encoder is continued to be used.
170    pub fn get_mut(&mut self) -> &mut R {
171        self.reader.reader_mut()
172    }
173
174    /// Return the inner `Read`.
175    ///
176    /// Calling `finish()` is not *required* after reading a stream -
177    /// just use it if you need to get the `Read` back.
178    pub fn finish(self) -> R {
179        self.reader.into_inner()
180    }
181
182    crate::encoder_common!(reader);
183}
184
185impl<R: BufRead> Read for Encoder<'_, R> {
186    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
187        self.reader.read(buf)
188    }
189}
190
191fn _assert_traits() {
192    use std::io::Cursor;
193
194    fn _assert_send<T: Send>(_: T) {}
195
196    _assert_send(Decoder::new(Cursor::new(Vec::new())));
197    _assert_send(Encoder::new(Cursor::new(Vec::new()), 1));
198}