isal/
read.rs

1//! Encoder and Decoder implementing `std::io::Read`
2use crate::*;
3use std::io;
4
5/// Streaming compression for input streams implementing `std::io::Read`.
6///
7/// Notes
8/// -----
9/// One should consider using `crate::compress` or `crate::compress_into` if possible.
10/// In that context, we do not need to hold and maintain intermediate buffers for reading and writing.
11///
12/// Example
13/// -------
14/// ```
15/// use std::{io, io::Read};
16/// use isal::{read::Encoder, CompressionLevel, decompress, Codec};
17/// let data = b"Hello, World!".to_vec();
18///
19/// let mut encoder = Encoder::new(data.as_slice(), CompressionLevel::Three, Codec::Gzip);
20/// let mut compressed = vec![];
21///
22/// // Number of compressed bytes written to `output`
23/// let n = io::copy(&mut encoder, &mut compressed).unwrap();
24/// assert_eq!(n as usize, compressed.len());
25///
26/// let decompressed = decompress(compressed.as_slice(), Codec::Gzip).unwrap();
27/// assert_eq!(decompressed.as_slice(), data);
28/// ```
29pub struct Encoder<R: io::Read> {
30    inner: R,
31    stream: ZStream,
32    in_buf: [u8; BUF_SIZE],
33}
34
35impl<R: io::Read> Encoder<R> {
36    /// Create a new `Encoder` which implements the `std::io::Read` trait.
37    pub fn new(reader: R, level: CompressionLevel, codec: Codec) -> Encoder<R> {
38        let in_buf = [0_u8; BUF_SIZE];
39
40        let mut zstream = ZStream::new(level, ZStreamKind::Stateful);
41        zstream.stream.end_of_stream = 0;
42        zstream.stream.flush = FlushFlags::NoFlush as _;
43        zstream.stream.gzip_flag = codec as _;
44
45        Self {
46            inner: reader,
47            stream: zstream,
48            in_buf,
49        }
50    }
51
52    /// Mutable reference to underlying reader, not advisable to modify during reading.
53    pub fn get_ref_mut(&mut self) -> &mut R {
54        &mut self.inner
55    }
56
57    // Reference to underlying reader
58    pub fn get_ref(&self) -> &R {
59        &self.inner
60    }
61}
62
63impl<R: io::Read> io::Read for Encoder<R> {
64    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
65        self.stream.stream.avail_out = buf.len() as _;
66        self.stream.stream.next_out = buf.as_mut_ptr();
67
68        // If we have an intermediate compressed format (ICF) buffer full, we just need
69        // to provide more output and return
70        if self.stream.stream.internal_state.state
71            == isal::isal_zstate_state_ZSTATE_TMP_FLUSH_ICF_BUFFER
72        {
73            self.stream.deflate()?;
74            return Ok(buf.len() - self.stream.stream.avail_out as usize);
75        }
76
77        let mut nbytes = 0;
78        while self.stream.stream.avail_out > 0 {
79            // Read out next buf len worth to compress; filling intermediate out_buf
80            // Check if current next_in ptr is valid; pointing to somewhere in the in buffer
81            // it may not be after a reset. If not, just read into in_buf and update
82            // otherwise we can shift it to the front and read more w/o reallocation
83            let next_in_ptr = self.stream.stream.next_in;
84            let base_ptr = self.in_buf.as_mut_ptr();
85            if next_in_ptr.is_null()
86                || next_in_ptr < base_ptr
87                || next_in_ptr > unsafe { base_ptr.add(self.in_buf.len()) }
88            {
89                self.stream.stream.avail_in = self.inner.read(&mut self.in_buf)? as _;
90                self.stream.stream.next_in = self.in_buf.as_mut_ptr();
91                self.stream.stream.end_of_stream = (self.stream.stream.avail_in == 0) as _;
92            } else {
93                let idx = unsafe { next_in_ptr.offset_from(base_ptr) };
94
95                // Extra sanity check - this probably / should never happen after ptr check above.
96                if idx < 0
97                    || idx + self.stream.stream.avail_in as isize > self.in_buf.len() as isize
98                {
99                    let msg = format!(
100                            "Compression error refilling in buffer, index is probably wrong: {}, avail_in: {}, avail_out: {}",
101                            idx, self.stream.stream.avail_in, self.stream.stream.avail_out
102                        );
103                    let err = Error::Other((None, msg));
104                    return Err(io::Error::new(io::ErrorKind::Other, err));
105                }
106
107                // Can safely shift next input to the front and read more into tail of in buf
108                let idx = idx as usize;
109                self.in_buf
110                    .copy_within(idx..idx + self.stream.stream.avail_in as usize, 0);
111                let avail_in = self
112                    .inner
113                    .read(&mut self.in_buf[self.stream.stream.avail_in as usize..])?
114                    as usize;
115                self.stream.stream.avail_in += avail_in as u32;
116                self.stream.stream.end_of_stream = (avail_in == 0) as _;
117                self.stream.stream.next_in = self.in_buf[0..].as_mut_ptr();
118            }
119
120            self.stream.deflate()?;
121            nbytes = buf.len() - self.stream.stream.avail_out as usize;
122
123            if self.stream.stream.internal_state.state == isal::isal_zstate_state_ZSTATE_END {
124                break;
125            }
126        }
127
128        Ok(nbytes)
129    }
130}
131
132/// Streaming compression for input streams implementing `std::io::Read`.
133///
134/// Notes
135/// -----
136/// One should consider using `crate::decompress` or `crate::decompress_into` if possible.
137/// In that context, we do not need to hold and maintain intermediate buffers for reading and writing.
138///
139/// Example
140/// -------
141/// ```
142/// use std::{io, io::Read};
143/// use isal::{read::Decoder, CompressionLevel, compress, Codec};
144/// let data = b"Hello, World!".to_vec();
145///
146/// let compressed = compress(data.as_slice(), CompressionLevel::Three, Codec::Gzip).unwrap();
147/// let mut decoder = Decoder::new(compressed.as_slice(), Codec::Gzip);
148/// let mut decompressed = vec![];
149///
150/// // Numbeer of compressed bytes written to `output`
151/// let n = io::copy(&mut decoder, &mut decompressed).unwrap();
152/// assert_eq!(n as usize, data.len());
153/// assert_eq!(decompressed.as_slice(), data);
154/// ```
155pub struct Decoder<R: io::Read> {
156    inner: R,
157    zst: InflateState,
158    in_buf: [u8; BUF_SIZE],
159    #[allow(dead_code)]
160    codec: Codec,
161}
162
163impl<R: io::Read> Decoder<R> {
164    pub fn new(reader: R, codec: Codec) -> Decoder<R> {
165        let zst = InflateState::new(codec);
166
167        Self {
168            inner: reader,
169            zst,
170            in_buf: [0u8; BUF_SIZE],
171            codec,
172        }
173    }
174
175    /// Mutable reference to underlying reader, not advisable to modify during reading.
176    pub fn get_ref_mut(&mut self) -> &mut R {
177        &mut self.inner
178    }
179
180    /// Reference to underlying reader
181    pub fn get_ref(&self) -> &R {
182        &self.inner
183    }
184}
185
186impl<R: io::Read> io::Read for Decoder<R> {
187    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
188        self.zst.state.next_out = buf.as_mut_ptr();
189        self.zst.state.avail_out = buf.len() as _;
190
191        // keep writing as much as possible to the output buf
192        let mut n_bytes = 0;
193        while self.zst.state.avail_out > 0 {
194            // Keep in_buf full for avail_in
195            if self.zst.state.avail_in < self.in_buf.len() as _ {
196                // if null, it's our first assignment of compressed data in
197                if self.zst.state.next_in.is_null() {
198                    self.zst.state.avail_in = self.inner.read(&mut self.in_buf)? as u32;
199                    self.zst.state.next_in = self.in_buf.as_mut_ptr();
200
201                // Otherwise shift current available in section to the front and read more
202                } else {
203                    let idx = unsafe {
204                        self.zst.state.next_in.offset_from(self.in_buf.as_ptr()) as usize
205                    };
206                    self.in_buf
207                        .copy_within(idx..idx + self.zst.state.avail_in as usize, 0);
208                    self.zst.state.next_in = self.in_buf.as_mut_ptr();
209
210                    // read some more and update avail_in
211                    let n = self
212                        .inner
213                        .read(&mut self.in_buf[self.zst.state.avail_in as usize..])?;
214                    self.zst.state.avail_in += n as u32;
215                };
216            }
217            // Block finished, reset if we have more compressed data, otherwise exit
218            if self.zst.block_state() == isal::isal_block_state_ISAL_BLOCK_FINISH {
219                if self.zst.state.avail_in == 0 {
220                    break;
221                }
222                self.zst.reset();
223            }
224
225            self.zst.step_inflate()?;
226            n_bytes = buf.len() - self.zst.state.avail_out as usize;
227        }
228
229        Ok(n_bytes)
230    }
231}
232
233/// Deflate decompression
234/// Basically a wrapper to `Encoder` which sets the codec for you.
235pub struct DeflateEncoder<R: io::Read> {
236    inner: Encoder<R>,
237}
238
239impl<R: io::Read> DeflateEncoder<R> {
240    pub fn new(reader: R, level: CompressionLevel) -> Self {
241        Self {
242            inner: Encoder::new(reader, level, Codec::Deflate),
243        }
244    }
245    /// Mutable reference to underlying reader, not advisable to modify during reading.
246    pub fn get_ref_mut(&mut self) -> &mut R {
247        &mut self.inner.inner
248    }
249
250    // Reference to underlying reader
251    pub fn get_ref(&self) -> &R {
252        &self.inner.inner
253    }
254}
255
256impl<R: io::Read> io::Read for DeflateEncoder<R> {
257    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
258        self.inner.read(buf)
259    }
260}
261
262/// Deflate decompression
263/// Basically a wrapper to `Decoder` which sets the codec for you.
264pub struct DeflateDecoder<R: io::Read> {
265    inner: Decoder<R>,
266}
267
268impl<R: io::Read> DeflateDecoder<R> {
269    pub fn new(reader: R) -> Self {
270        Self {
271            inner: Decoder::new(reader, Codec::Deflate),
272        }
273    }
274    /// Mutable reference to underlying reader, not advisable to modify during reading.
275    pub fn get_ref_mut(&mut self) -> &mut R {
276        &mut self.inner.inner
277    }
278
279    // Reference to underlying reader
280    pub fn get_ref(&self) -> &R {
281        &self.inner.inner
282    }
283}
284
285impl<R: io::Read> io::Read for DeflateDecoder<R> {
286    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
287        self.inner.read(buf)
288    }
289}
290/// Zlib decompression
291/// Basically a wrapper to `Encoder` which sets the codec for you.
292pub struct ZlibEncoder<R: io::Read> {
293    inner: Encoder<R>,
294}
295
296impl<R: io::Read> ZlibEncoder<R> {
297    pub fn new(reader: R, level: CompressionLevel) -> Self {
298        Self {
299            inner: Encoder::new(reader, level, Codec::Zlib),
300        }
301    }
302    /// Mutable reference to underlying reader, not advisable to modify during reading.
303    pub fn get_ref_mut(&mut self) -> &mut R {
304        &mut self.inner.inner
305    }
306
307    // Reference to underlying reader
308    pub fn get_ref(&self) -> &R {
309        &self.inner.inner
310    }
311}
312
313impl<R: io::Read> io::Read for ZlibEncoder<R> {
314    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
315        self.inner.read(buf)
316    }
317}
318
319/// Zlib decompression
320/// Basically a wrapper to `Decoder` which sets the codec for you.
321pub struct ZlibDecoder<R: io::Read> {
322    inner: Decoder<R>,
323}
324
325impl<R: io::Read> ZlibDecoder<R> {
326    pub fn new(reader: R) -> Self {
327        Self {
328            inner: Decoder::new(reader, Codec::Zlib),
329        }
330    }
331    /// Mutable reference to underlying reader, not advisable to modify during reading.
332    pub fn get_ref_mut(&mut self) -> &mut R {
333        &mut self.inner.inner
334    }
335
336    // Reference to underlying reader
337    pub fn get_ref(&self) -> &R {
338        &self.inner.inner
339    }
340}
341
342impl<R: io::Read> io::Read for ZlibDecoder<R> {
343    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
344        self.inner.read(buf)
345    }
346}
347/// Gzip decompression
348/// Basically a wrapper to `Encoder` which sets the codec for you.
349pub struct GzipEncoder<R: io::Read> {
350    inner: Encoder<R>,
351}
352
353impl<R: io::Read> GzipEncoder<R> {
354    pub fn new(reader: R, level: CompressionLevel) -> Self {
355        Self {
356            inner: Encoder::new(reader, level, Codec::Gzip),
357        }
358    }
359    /// Mutable reference to underlying reader, not advisable to modify during reading.
360    pub fn get_ref_mut(&mut self) -> &mut R {
361        &mut self.inner.inner
362    }
363
364    // Reference to underlying reader
365    pub fn get_ref(&self) -> &R {
366        &self.inner.inner
367    }
368}
369
370impl<R: io::Read> io::Read for GzipEncoder<R> {
371    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
372        self.inner.read(buf)
373    }
374}
375
376/// Gzip decompression
377/// Basically a wrapper to `Decoder` which sets the codec for you.
378pub struct GzipDecoder<R: io::Read> {
379    inner: Decoder<R>,
380}
381
382impl<R: io::Read> GzipDecoder<R> {
383    pub fn new(reader: R) -> Self {
384        Self {
385            inner: Decoder::new(reader, Codec::Gzip),
386        }
387    }
388    /// Mutable reference to underlying reader, not advisable to modify during reading.
389    pub fn get_ref_mut(&mut self) -> &mut R {
390        &mut self.inner.inner
391    }
392
393    // Reference to underlying reader
394    pub fn get_ref(&self) -> &R {
395        &self.inner.inner
396    }
397}
398
399impl<R: io::Read> io::Read for GzipDecoder<R> {
400    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
401        self.inner.read(buf)
402    }
403}