Coverage Report

Created: 2026-09-02 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flate2-1.1.10/src/zlib/write.rs
Line
Count
Source
1
use crate::io;
2
use crate::io::{Read, Write};
3
4
use crate::zio;
5
use crate::{Compress, Decompress};
6
7
/// A ZLIB encoder, or compressor.
8
///
9
/// This structure implements a [`Write`] interface and takes a stream of
10
/// uncompressed data, writing the compressed data to the wrapped writer.
11
///
12
/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
13
///
14
/// # Examples
15
///
16
/// ```
17
/// use std::io::prelude::*;
18
/// use flate2::Compression;
19
/// use flate2::write::ZlibEncoder;
20
///
21
/// // Vec<u8> implements Write, assigning the compressed bytes of sample string
22
///
23
/// # fn zlib_encoding() -> std::io::Result<()> {
24
/// let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
25
/// e.write_all(b"Hello World")?;
26
/// let compressed = e.finish()?;
27
/// # Ok(())
28
/// # }
29
/// ```
30
#[derive(Debug)]
31
pub struct ZlibEncoder<W: Write> {
32
    inner: zio::Writer<W, Compress>,
33
}
34
35
impl<W: Write> ZlibEncoder<W> {
36
    /// Creates a new encoder which will write compressed data to the stream
37
    /// given at the given compression level.
38
    ///
39
    /// When this encoder is dropped or unwrapped the final pieces of data will
40
    /// be flushed.
41
0
    pub fn new(w: W, level: crate::Compression) -> ZlibEncoder<W> {
42
0
        ZlibEncoder {
43
0
            inner: zio::Writer::new(w, Compress::new(level, true)),
44
0
        }
45
0
    }
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<alloc::vec::Vec<u8>>>::new
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<_>>::new
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut alloc::vec::Vec<u8>>>::new
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::new
46
47
    /// Creates a new encoder which will write compressed data to the stream
48
    /// `w` with the given `compression` settings.
49
0
    pub fn new_with_compress(w: W, compression: Compress) -> ZlibEncoder<W> {
50
0
        ZlibEncoder {
51
0
            inner: zio::Writer::new(w, compression),
52
0
        }
53
0
    }
54
55
    /// Acquires a reference to the underlying writer.
56
0
    pub fn get_ref(&self) -> &W {
57
0
        self.inner.get_ref()
58
0
    }
59
60
    /// Acquires a mutable reference to the underlying writer.
61
    ///
62
    /// The underlying writer may be mutated or replaced as long as this
63
    /// preserves the bytes and ordering of the logical output stream.
64
    /// Concatenate output from each writer to reconstruct the complete stream.
65
    ///
66
    /// Replacing the writer does not require [`flush`](Write::flush). Call it
67
    /// first when all input accepted so far must be decodable without output
68
    /// from later writes. This inserts a sync-flush point and changes the output
69
    /// bitstream. This is useful before applying [`std::mem::take`] to
70
    /// [`get_mut`](Self::get_mut) when forwarding the stream incrementally.
71
    ///
72
    /// To start a new stream, use [`reset`](Self::reset); replacing the writer
73
    /// does not reset this encoder.
74
0
    pub fn get_mut(&mut self) -> &mut W {
75
0
        self.inner.get_mut()
76
0
    }
77
78
    /// Resets the state of this encoder entirely, swapping out the output
79
    /// stream for another.
80
    ///
81
    /// This function will finish encoding the current stream into the current
82
    /// output stream before swapping out the two output streams.
83
    ///
84
    /// After the current stream has been finished, this will reset the internal
85
    /// state of this encoder and replace the output stream with the one
86
    /// provided, returning the previous output stream. Future data written to
87
    /// this encoder will be the compressed into the stream `w` provided.
88
    ///
89
    /// # Errors
90
    ///
91
    /// This function will perform I/O to complete this stream, and any I/O
92
    /// errors which occur will be returned from this function.
93
0
    pub fn reset(&mut self, w: W) -> io::Result<W> {
94
0
        self.inner.finish()?;
95
0
        self.inner.data.reset();
96
0
        Ok(self.inner.replace(w))
97
0
    }
98
99
    /// Attempt to finish this output stream, writing out final chunks of data.
100
    ///
101
    /// Note that this function can only be used once data has finished being
102
    /// written to the output stream. After this function is called then further
103
    /// calls to `write` may result in a panic.
104
    ///
105
    /// # Panics
106
    ///
107
    /// Attempts to write data to this stream may result in a panic after this
108
    /// function is called.
109
    ///
110
    /// # Errors
111
    ///
112
    /// This function will perform I/O to complete this stream, and any I/O
113
    /// errors which occur will be returned from this function.
114
0
    pub fn try_finish(&mut self) -> io::Result<()> {
115
0
        self.inner.finish()
116
0
    }
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<_>>::try_finish
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut alloc::vec::Vec<u8>>>::try_finish
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::try_finish
117
118
    /// Consumes this encoder, flushing the output stream.
119
    ///
120
    /// This will flush the underlying data stream, close off the compressed
121
    /// stream and, if successful, return the contained writer.
122
    ///
123
    /// Note that this function may not be suitable to call in a situation where
124
    /// the underlying stream is an asynchronous I/O stream. To finish a stream
125
    /// the `try_finish` (or `shutdown`) method should be used instead. To
126
    /// re-acquire ownership of a stream it is safe to call this method after
127
    /// `try_finish` or `shutdown` has returned `Ok`.
128
    ///
129
    /// # Errors
130
    ///
131
    /// This function will perform I/O to complete this stream, and any I/O
132
    /// errors which occur will be returned from this function.
133
0
    pub fn finish(mut self) -> io::Result<W> {
134
0
        self.inner.finish()?;
135
0
        Ok(self.inner.take_inner())
136
0
    }
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<alloc::vec::Vec<u8>>>::finish
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<_>>::finish
137
138
    /// Consumes this encoder, flushing the output stream.
139
    ///
140
    /// This will flush the underlying data stream and then return the contained
141
    /// writer if the flush succeeded.
142
    /// The compressed stream will not be closed but only flushed. This
143
    /// means that obtained byte array can by extended by another deflated
144
    /// stream. To close the stream add the two bytes 0x3 and 0x0.
145
    ///
146
    /// # Errors
147
    ///
148
    /// This function will perform I/O to complete this stream, and any I/O
149
    /// errors which occur will be returned from this function.
150
0
    pub fn flush_finish(mut self) -> io::Result<W> {
151
0
        self.inner.flush()?;
152
0
        Ok(self.inner.take_inner())
153
0
    }
154
155
    /// Returns the number of bytes that have been written to this compressor.
156
    ///
157
    /// Note that not all bytes written to this object may be accounted for,
158
    /// there may still be some active buffering.
159
0
    pub fn total_in(&self) -> u64 {
160
0
        self.inner.data.total_in()
161
0
    }
162
163
    /// Returns the number of bytes that the compressor has produced.
164
    ///
165
    /// Note that not all bytes may have been written yet, some may still be
166
    /// buffered.
167
0
    pub fn total_out(&self) -> u64 {
168
0
        self.inner.data.total_out()
169
0
    }
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<_>>::total_out
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut alloc::vec::Vec<u8>>>::total_out
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::total_out
170
}
171
172
impl<W: Write> Write for ZlibEncoder<W> {
173
0
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
174
0
        self.inner.write(buf)
175
0
    }
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<alloc::vec::Vec<u8>> as std::io::Write>::write
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<_> as std::io::Write>::write
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut alloc::vec::Vec<u8>> as std::io::Write>::write
Unexecuted instantiation: <flate2::zlib::write::ZlibEncoder<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as std::io::Write>::write
176
177
0
    fn flush(&mut self) -> io::Result<()> {
178
0
        self.inner.flush()
179
0
    }
180
}
181
182
impl<W: Read + Write> Read for ZlibEncoder<W> {
183
0
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
184
0
        self.get_mut().read(buf)
185
0
    }
186
}
187
188
/// A ZLIB decoder, or decompressor.
189
///
190
/// This structure implements a [`Write`] and will emit a stream of decompressed
191
/// data when fed a stream of compressed data.
192
///
193
/// After decoding a single member of the ZLIB data this writer will return the number of bytes up
194
/// to the end of the ZLIB member and subsequent writes will return Ok(0) allowing the caller to
195
/// handle any data following the ZLIB member.
196
///
197
/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
198
///
199
/// # Examples
200
///
201
/// ```
202
/// use std::io::prelude::*;
203
/// use std::io;
204
/// # use flate2::Compression;
205
/// # use flate2::write::ZlibEncoder;
206
/// use flate2::write::ZlibDecoder;
207
///
208
/// # fn main() {
209
/// #    let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
210
/// #    e.write_all(b"Hello World").unwrap();
211
/// #    let bytes = e.finish().unwrap();
212
/// #    println!("{}", decode_reader(bytes).unwrap());
213
/// # }
214
/// #
215
/// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error
216
/// // Here Vec<u8> implements Write
217
///
218
/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
219
///    let mut writer = Vec::new();
220
///    let mut z = ZlibDecoder::new(writer);
221
///    z.write_all(&bytes[..])?;
222
///    writer = z.finish()?;
223
///    let return_string = String::from_utf8(writer).expect("String parsing error");
224
///    Ok(return_string)
225
/// }
226
/// ```
227
#[derive(Debug)]
228
pub struct ZlibDecoder<W: Write> {
229
    inner: zio::Writer<W, Decompress>,
230
}
231
232
impl<W: Write> ZlibDecoder<W> {
233
    /// Creates a new decoder which will write uncompressed data to the stream.
234
    ///
235
    /// When this decoder is dropped or unwrapped the final pieces of data will
236
    /// be flushed.
237
0
    pub fn new(w: W) -> ZlibDecoder<W> {
238
0
        ZlibDecoder {
239
0
            inner: zio::Writer::new(w, Decompress::new(true)),
240
0
        }
241
0
    }
242
243
    /// Creates a new decoder which will write uncompressed data to the stream `w`
244
    /// using the given `decompression` settings.
245
    ///
246
    /// When this decoder is dropped or unwrapped the final pieces of data will
247
    /// be flushed.
248
0
    pub fn new_with_decompress(w: W, decompression: Decompress) -> ZlibDecoder<W> {
249
0
        ZlibDecoder {
250
0
            inner: zio::Writer::new(w, decompression),
251
0
        }
252
0
    }
253
254
    /// Acquires a reference to the underlying writer.
255
0
    pub fn get_ref(&self) -> &W {
256
0
        self.inner.get_ref()
257
0
    }
258
259
    /// Acquires a mutable reference to the underlying writer.
260
    ///
261
    /// The underlying writer may be mutated or replaced as long as this
262
    /// preserves the bytes and ordering of the logical output stream.
263
    /// Concatenate output from each writer to reconstruct the complete stream.
264
    ///
265
    /// Replacing the writer does not require [`flush`](Write::flush). Call it
266
    /// first to write all decompressed output currently available to the
267
    /// current writer. This is useful before applying [`std::mem::take`] to
268
    /// [`get_mut`](Self::get_mut) when forwarding output incrementally.
269
    ///
270
    /// To start a new stream, use [`reset`](Self::reset); replacing the writer
271
    /// does not reset this decoder.
272
0
    pub fn get_mut(&mut self) -> &mut W {
273
0
        self.inner.get_mut()
274
0
    }
275
276
    /// Resets the state of this decoder entirely, swapping out the output
277
    /// stream for another.
278
    ///
279
    /// This will reset the internal state of this decoder and replace the
280
    /// output stream with the one provided, returning the previous output
281
    /// stream. Future data written to this decoder will be decompressed into
282
    /// the output stream `w`.
283
    ///
284
    /// # Errors
285
    ///
286
    /// This function will perform I/O to complete this stream, and any I/O
287
    /// errors which occur will be returned from this function.
288
0
    pub fn reset(&mut self, w: W) -> io::Result<W> {
289
0
        self.inner.finish()?;
290
0
        self.inner.data = Decompress::new(true);
291
0
        Ok(self.inner.replace(w))
292
0
    }
293
294
    /// Attempt to finish this output stream, writing out final chunks of data.
295
    ///
296
    /// Note that this function can only be used once data has finished being
297
    /// written to the output stream. After this function is called then further
298
    /// calls to `write` may result in a panic.
299
    ///
300
    /// # Panics
301
    ///
302
    /// Attempts to write data to this stream may result in a panic after this
303
    /// function is called.
304
    ///
305
    /// # Errors
306
    ///
307
    /// This function will perform I/O to complete this stream, and any I/O
308
    /// errors which occur will be returned from this function.
309
0
    pub fn try_finish(&mut self) -> io::Result<()> {
310
0
        self.inner.finish()
311
0
    }
312
313
    /// Consumes this encoder, flushing the output stream.
314
    ///
315
    /// This will flush the underlying data stream and then return the contained
316
    /// writer if the flush succeeded.
317
    ///
318
    /// Note that this function may not be suitable to call in a situation where
319
    /// the underlying stream is an asynchronous I/O stream. To finish a stream
320
    /// the `try_finish` (or `shutdown`) method should be used instead. To
321
    /// re-acquire ownership of a stream it is safe to call this method after
322
    /// `try_finish` or `shutdown` has returned `Ok`.
323
    ///
324
    /// # Errors
325
    ///
326
    /// This function will perform I/O to complete this stream, and any I/O
327
    /// errors which occur will be returned from this function.
328
0
    pub fn finish(mut self) -> io::Result<W> {
329
0
        self.inner.finish()?;
330
0
        Ok(self.inner.take_inner())
331
0
    }
332
333
    /// Returns the number of bytes that the decompressor has consumed for
334
    /// decompression.
335
    ///
336
    /// Note that this will likely be smaller than the number of bytes
337
    /// successfully written to this stream due to internal buffering.
338
0
    pub fn total_in(&self) -> u64 {
339
0
        self.inner.data.total_in()
340
0
    }
341
342
    /// Returns the number of bytes that the decompressor has written to its
343
    /// output stream.
344
0
    pub fn total_out(&self) -> u64 {
345
0
        self.inner.data.total_out()
346
0
    }
347
}
348
349
impl<W: Write> Write for ZlibDecoder<W> {
350
0
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
351
0
        self.inner.write(buf)
352
0
    }
353
354
0
    fn flush(&mut self) -> io::Result<()> {
355
0
        self.inner.flush()
356
0
    }
357
}
358
359
impl<W: Read + Write> Read for ZlibDecoder<W> {
360
0
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
361
0
        self.inner.get_mut().read(buf)
362
0
    }
363
}
364
365
#[cfg(test)]
366
mod tests {
367
    use alloc::string::String;
368
    use alloc::vec::Vec;
369
370
    use super::*;
371
    use crate::Compression;
372
373
    const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
374
        Hello World Hello World Hello World Hello World Hello World \
375
        Hello World Hello World Hello World Hello World Hello World \
376
        Hello World Hello World Hello World Hello World Hello World \
377
        Hello World Hello World Hello World Hello World Hello World";
378
379
    // ZlibDecoder consumes one zlib archive and then returns 0 for subsequent writes, allowing any
380
    // additional data to be consumed by the caller.
381
    #[test]
382
    fn decode_extra_data() {
383
        let compressed = {
384
            let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
385
            e.write_all(STR.as_ref()).unwrap();
386
            let mut b = e.finish().unwrap();
387
            b.push(b'x');
388
            b
389
        };
390
391
        let mut writer = Vec::new();
392
        let mut decoder = ZlibDecoder::new(writer);
393
        let mut consumed_bytes = 0;
394
        loop {
395
            let n = decoder.write(&compressed[consumed_bytes..]).unwrap();
396
            if n == 0 {
397
                break;
398
            }
399
            consumed_bytes += n;
400
        }
401
        writer = decoder.finish().unwrap();
402
        let actual = String::from_utf8(writer).expect("String parsing error");
403
        assert_eq!(actual, STR);
404
        assert_eq!(&compressed[consumed_bytes..], b"x");
405
    }
406
}