Coverage Report

Created: 2025-06-02 07:01

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