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: BufRead> {
16 reader: zio::Reader<R, raw::Decoder<'a>>,
17}
1819/// An encoder that compress input data from another `Read`.
20pub struct Encoder<'a, R: BufRead> {
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/// Sets this `Decoder` to stop after the first frame.
50 ///
51 /// By default, it keeps concatenating frames until EOF is reached.
52#[must_use]
53pub fn single_frame(mut self) -> Self {
54self.reader.set_single_frame();
55self
56}
5758/// Creates a new decoder, using an existing `DecoderDictionary`.
59 ///
60 /// The dictionary must be the same as the one used during compression.
61pub fn with_prepared_dictionary<'b>(
62 reader: R,
63 dictionary: &DecoderDictionary<'b>,
64 ) -> io::Result<Self>
65where
66'b: 'a,
67 {
68let decoder = raw::Decoder::with_prepared_dictionary(dictionary)?;
69let reader = zio::Reader::new(reader, decoder);
7071Ok(Decoder { reader })
72 }
7374/// Recommendation for the size of the output buffer.
75pub fn recommended_output_size() -> usize {
76 zstd_safe::DCtx::out_size()
77 }
7879/// Acquire a reference to the underlying reader.
80pub fn get_ref(&self) -> &R {
81self.reader.reader()
82 }
8384/// 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.
88pub fn get_mut(&mut self) -> &mut R {
89self.reader.reader_mut()
90 }
9192/// 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.
96pub fn finish(self) -> R {
97self.reader.into_inner()
98 }
99100crate::decoder_common!(reader);
101}
102103impl<R: BufRead> Read for Decoder<'_, R> {
104fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
105self.reader.read(buf)
106 }
107}
108109impl<R: Read> Encoder<'static, BufReader<R>> {
110/// Creates a new encoder.
111pub fn new(reader: R, level: i32) -> io::Result<Self> {
112let buffer_size = zstd_safe::CCtx::in_size();
113114Self::with_buffer(BufReader::with_capacity(buffer_size, reader), level)
115 }
116}
117118impl<R: BufRead> Encoder<'static, R> {
119/// Creates a new encoder around a `BufRead`.
120pub fn with_buffer(reader: R, level: i32) -> io::Result<Self> {
121Self::with_dictionary(reader, level, &[])
122 }
123124/// Creates a new encoder, using an existing dictionary.
125 ///
126 /// The dictionary must be the same as the one used during compression.
127pub fn with_dictionary(
128 reader: R,
129 level: i32,
130 dictionary: &[u8],
131 ) -> io::Result<Self> {
132let encoder = raw::Encoder::with_dictionary(level, dictionary)?;
133let reader = zio::Reader::new(reader, encoder);
134135Ok(Encoder { reader })
136 }
137}
138139impl<'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.
143pub fn with_prepared_dictionary<'b>(
144 reader: R,
145 dictionary: &EncoderDictionary<'b>,
146 ) -> io::Result<Self>
147where
148'b: 'a,
149 {
150let encoder = raw::Encoder::with_prepared_dictionary(dictionary)?;
151let reader = zio::Reader::new(reader, encoder);
152153Ok(Encoder { reader })
154 }
155156/// Recommendation for the size of the output buffer.
157pub fn recommended_output_size() -> usize {
158 zstd_safe::CCtx::out_size()
159 }
160161/// Acquire a reference to the underlying reader.
162pub fn get_ref(&self) -> &R {
163self.reader.reader()
164 }
165166/// 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.
170pub fn get_mut(&mut self) -> &mut R {
171self.reader.reader_mut()
172 }
173174/// 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.
178pub fn finish(self) -> R {
179self.reader.into_inner()
180 }
181182crate::encoder_common!(reader);
183}
184185impl<R: BufRead> Read for Encoder<'_, R> {
186fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
187self.reader.read(buf)
188 }
189}
190191fn _assert_traits() {
192use std::io::Cursor;
193194fn _assert_send<T: Send>(_: T) {}
195196 _assert_send(Decoder::new(Cursor::new(Vec::new())));
197 _assert_send(Encoder::new(Cursor::new(Vec::new()), 1));
198}