Coverage Report

Created: 2026-11-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flate2-1.1.11/src/zio.rs
Line
Count
Source
1
use crate::io;
2
use crate::io::{BufRead, Write};
3
use alloc::vec::Vec;
4
use core::mem;
5
6
use crate::{
7
    Compress, CompressError, Decompress, DecompressError, FlushCompress, FlushDecompress, Status,
8
};
9
10
#[derive(Debug)]
11
pub struct Writer<W: Write, D: Ops> {
12
    obj: Option<W>,
13
    pub data: D,
14
    buf: Vec<u8>,
15
    finished: bool,
16
    buf_pos: usize,
17
}
18
19
pub trait Ops {
20
    type Error: Into<io::Error>;
21
    type Flush: Flush;
22
    /// Whether running out of input before `Status::StreamEnd` means the
23
    /// stream is incomplete, as is the case for decompression.
24
    const REQUIRES_STREAM_END: bool;
25
    fn total_in(&self) -> u64;
26
    fn total_out(&self) -> u64;
27
    fn run(
28
        &mut self,
29
        input: &[u8],
30
        output: &mut [u8],
31
        flush: Self::Flush,
32
    ) -> Result<Status, Self::Error>;
33
    fn run_vec(
34
        &mut self,
35
        input: &[u8],
36
        output: &mut Vec<u8>,
37
        flush: Self::Flush,
38
    ) -> Result<Status, Self::Error>;
39
    fn flush<W: Write>(writer: &mut Writer<W, Self>) -> io::Result<()>
40
    where
41
        Self: Sized;
42
}
43
44
impl Ops for Compress {
45
    type Error = CompressError;
46
    type Flush = FlushCompress;
47
    /// Unlike decompression, compression accepts arbitrary, unframed input and
48
    /// creates the stream's ending with `FlushCompress::Finish`. Exhausting the
49
    /// input cannot indicate truncation, so `Writer::finish` keeps the encoder's
50
    /// existing no-more-output completion rule instead of requiring `StreamEnd`.
51
    const REQUIRES_STREAM_END: bool = false;
52
42.4k
    fn total_in(&self) -> u64 {
53
42.4k
        self.total_in()
54
42.4k
    }
55
21.2k
    fn total_out(&self) -> u64 {
56
21.2k
        self.total_out()
57
21.2k
    }
58
0
    fn run(
59
0
        &mut self,
60
0
        input: &[u8],
61
0
        output: &mut [u8],
62
0
        flush: FlushCompress,
63
0
    ) -> Result<Status, CompressError> {
64
0
        self.compress(input, output, flush)
65
0
    }
66
42.4k
    fn run_vec(
67
42.4k
        &mut self,
68
42.4k
        input: &[u8],
69
42.4k
        output: &mut Vec<u8>,
70
42.4k
        flush: FlushCompress,
71
42.4k
    ) -> Result<Status, CompressError> {
72
42.4k
        self.compress_vec(input, output, flush)
73
42.4k
    }
74
75
0
    fn flush<W: Write>(writer: &mut Writer<W, Self>) -> io::Result<()> {
76
        loop {
77
0
            writer.dump()?;
78
0
            writer
79
0
                .data
80
0
                .compress_vec(&[], &mut writer.buf, FlushCompress::Sync)?;
81
0
            if writer.buf.len() < writer.buf.capacity() {
82
0
                return writer.dump();
83
0
            }
84
            // A full buffer may leave the sync flush incomplete; repeat it with fresh space.
85
        }
86
0
    }
Unexecuted instantiation: <flate2::mem::Compress as flate2::zio::Ops>::flush::<_>
Unexecuted instantiation: <flate2::mem::Compress as flate2::zio::Ops>::flush::<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>>
87
}
88
89
impl Ops for Decompress {
90
    type Error = DecompressError;
91
    type Flush = FlushDecompress;
92
    /// Unlike compression, decompression must find the stream's ending in the
93
    /// supplied input; `FlushDecompress::Finish` cannot create missing bytes.
94
    /// Once `Writer::finish` can produce no more output, only `StreamEnd` proves
95
    /// the input was complete. Otherwise, it must report `UnexpectedEof`.
96
    const REQUIRES_STREAM_END: bool = true;
97
127k
    fn total_in(&self) -> u64 {
98
127k
        self.total_in()
99
127k
    }
100
127k
    fn total_out(&self) -> u64 {
101
127k
        self.total_out()
102
127k
    }
103
63.5k
    fn run(
104
63.5k
        &mut self,
105
63.5k
        input: &[u8],
106
63.5k
        output: &mut [u8],
107
63.5k
        flush: FlushDecompress,
108
63.5k
    ) -> Result<Status, DecompressError> {
109
63.5k
        self.decompress(input, output, flush)
110
63.5k
    }
111
0
    fn run_vec(
112
0
        &mut self,
113
0
        input: &[u8],
114
0
        output: &mut Vec<u8>,
115
0
        flush: FlushDecompress,
116
0
    ) -> Result<Status, DecompressError> {
117
0
        self.decompress_vec(input, output, flush)
118
0
    }
119
120
0
    fn flush<W: Write>(writer: &mut Writer<W, Self>) -> io::Result<()> {
121
0
        writer.dump()?;
122
0
        writer
123
0
            .data
124
0
            .decompress_vec(&[], &mut writer.buf, FlushDecompress::Sync)?;
125
126
        // Decoders can leave pending output even after producing a short chunk.
127
        loop {
128
0
            writer.dump()?;
129
0
            let before = writer.data.total_out();
130
0
            writer
131
0
                .data
132
0
                .decompress_vec(&[], &mut writer.buf, FlushDecompress::None)?;
133
0
            if before == writer.data.total_out() {
134
0
                return Ok(());
135
0
            }
136
        }
137
0
    }
138
}
139
140
pub trait Flush {
141
    fn none() -> Self;
142
    fn finish() -> Self;
143
}
144
145
impl Flush for FlushCompress {
146
21.2k
    fn none() -> Self {
147
21.2k
        FlushCompress::None
148
21.2k
    }
149
150
21.2k
    fn finish() -> Self {
151
21.2k
        FlushCompress::Finish
152
21.2k
    }
153
}
154
155
impl Flush for FlushDecompress {
156
44.9k
    fn none() -> Self {
157
44.9k
        FlushDecompress::None
158
44.9k
    }
159
160
18.5k
    fn finish() -> Self {
161
18.5k
        FlushDecompress::Finish
162
18.5k
    }
163
}
164
165
63.7k
pub fn read<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize>
166
63.7k
where
167
63.7k
    R: BufRead,
168
63.7k
    D: Ops,
169
{
170
    loop {
171
        let (read, consumed, ret, eof);
172
        {
173
63.7k
            let input = obj.fill_buf()?;
174
63.5k
            eof = input.is_empty();
175
63.5k
            let before_out = data.total_out();
176
63.5k
            let before_in = data.total_in();
177
63.5k
            let flush = if eof {
178
18.5k
                D::Flush::finish()
179
            } else {
180
44.9k
                D::Flush::none()
181
            };
182
63.5k
            ret = data.run(input, dst, flush);
183
63.5k
            read = (data.total_out() - before_out) as usize;
184
63.5k
            consumed = (data.total_in() - before_in) as usize;
185
        }
186
63.5k
        obj.consume(consumed);
187
188
27.0k
        match ret {
189
            // If we haven't read any data and we haven't hit EOF yet,
190
            // then we need to keep asking for more data because if we
191
            // return that 0 bytes of data have been read then it will
192
            // be interpreted as EOF.
193
27.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && !eof && !dst.is_empty() => continue,
194
            // If we haven't read any data and we have hit EOF, then the
195
            // deflate stream is incomplete.
196
27.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && eof && !dst.is_empty() => {
197
1.67k
                return Err(io::Error::new(
198
1.67k
                    io::ErrorKind::UnexpectedEof,
199
1.67k
                    "incomplete deflate stream",
200
1.67k
                ));
201
            }
202
58.0k
            Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read),
203
204
            Err(..) => {
205
3.82k
                return Err(io::Error::new(
206
3.82k
                    io::ErrorKind::InvalidInput,
207
3.82k
                    "corrupt deflate stream",
208
3.82k
                ))
209
            }
210
        }
211
    }
212
63.7k
}
flate2::zio::read::<flate2::bufreader::BufReader<zip::read::CryptoReader>, flate2::mem::Decompress>
Line
Count
Source
165
63.7k
pub fn read<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize>
166
63.7k
where
167
63.7k
    R: BufRead,
168
63.7k
    D: Ops,
169
{
170
    loop {
171
        let (read, consumed, ret, eof);
172
        {
173
63.7k
            let input = obj.fill_buf()?;
174
63.5k
            eof = input.is_empty();
175
63.5k
            let before_out = data.total_out();
176
63.5k
            let before_in = data.total_in();
177
63.5k
            let flush = if eof {
178
18.5k
                D::Flush::finish()
179
            } else {
180
44.9k
                D::Flush::none()
181
            };
182
63.5k
            ret = data.run(input, dst, flush);
183
63.5k
            read = (data.total_out() - before_out) as usize;
184
63.5k
            consumed = (data.total_in() - before_in) as usize;
185
        }
186
63.5k
        obj.consume(consumed);
187
188
27.0k
        match ret {
189
            // If we haven't read any data and we haven't hit EOF yet,
190
            // then we need to keep asking for more data because if we
191
            // return that 0 bytes of data have been read then it will
192
            // be interpreted as EOF.
193
27.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && !eof && !dst.is_empty() => continue,
194
            // If we haven't read any data and we have hit EOF, then the
195
            // deflate stream is incomplete.
196
27.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && eof && !dst.is_empty() => {
197
1.67k
                return Err(io::Error::new(
198
1.67k
                    io::ErrorKind::UnexpectedEof,
199
1.67k
                    "incomplete deflate stream",
200
1.67k
                ));
201
            }
202
58.0k
            Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read),
203
204
            Err(..) => {
205
3.82k
                return Err(io::Error::new(
206
3.82k
                    io::ErrorKind::InvalidInput,
207
3.82k
                    "corrupt deflate stream",
208
3.82k
                ))
209
            }
210
        }
211
    }
212
63.7k
}
Unexecuted instantiation: flate2::zio::read::<_, _>
213
214
impl<W: Write, D: Ops> Writer<W, D> {
215
21.2k
    pub fn new(w: W, d: D) -> Writer<W, D> {
216
21.2k
        Writer {
217
21.2k
            obj: Some(w),
218
21.2k
            data: d,
219
21.2k
            buf: Vec::with_capacity(32 * 1024),
220
21.2k
            finished: false,
221
21.2k
            buf_pos: 0,
222
21.2k
        }
223
21.2k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::new
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress>>::new
Line
Count
Source
215
21.2k
    pub fn new(w: W, d: D) -> Writer<W, D> {
216
21.2k
        Writer {
217
21.2k
            obj: Some(w),
218
21.2k
            data: d,
219
21.2k
            buf: Vec::with_capacity(32 * 1024),
220
21.2k
            finished: false,
221
21.2k
            buf_pos: 0,
222
21.2k
        }
223
21.2k
    }
224
225
21.2k
    pub fn finish(&mut self) -> io::Result<()> {
226
21.2k
        self.finish_inner(false)
227
21.2k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::finish
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress>>::finish
Line
Count
Source
225
21.2k
    pub fn finish(&mut self) -> io::Result<()> {
226
21.2k
        self.finish_inner(false)
227
21.2k
    }
228
229
0
    pub(crate) fn drain(&mut self) -> io::Result<()> {
230
0
        self.finish_inner(true)
231
0
    }
232
233
21.2k
    fn finish_inner(&mut self, allow_incomplete: bool) -> io::Result<()> {
234
21.2k
        if self.finished {
235
4
            return self.dump();
236
21.2k
        }
237
238
        loop {
239
21.2k
            self.dump()?;
240
241
21.2k
            let before = self.data.total_out();
242
21.2k
            let status = self
243
21.2k
                .data
244
21.2k
                .run_vec(&[], &mut self.buf, Flush::finish())
245
21.2k
                .map_err(Into::into)?;
246
21.2k
            if status == Status::StreamEnd {
247
21.2k
                self.finished = true;
248
21.2k
                return self.dump();
249
0
            }
250
0
            if before == self.data.total_out() {
251
                // No more output and no end of stream: the input was
252
                // truncated, mirroring the check in `read` above.
253
0
                if D::REQUIRES_STREAM_END && !allow_incomplete {
254
0
                    return Err(io::Error::new(
255
0
                        io::ErrorKind::UnexpectedEof,
256
0
                        "incomplete deflate stream",
257
0
                    ));
258
0
                }
259
0
                return Ok(());
260
0
            }
261
        }
262
21.2k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::finish_inner
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress>>::finish_inner
Line
Count
Source
233
21.2k
    fn finish_inner(&mut self, allow_incomplete: bool) -> io::Result<()> {
234
21.2k
        if self.finished {
235
4
            return self.dump();
236
21.2k
        }
237
238
        loop {
239
21.2k
            self.dump()?;
240
241
21.2k
            let before = self.data.total_out();
242
21.2k
            let status = self
243
21.2k
                .data
244
21.2k
                .run_vec(&[], &mut self.buf, Flush::finish())
245
21.2k
                .map_err(Into::into)?;
246
21.2k
            if status == Status::StreamEnd {
247
21.2k
                self.finished = true;
248
21.2k
                return self.dump();
249
0
            }
250
0
            if before == self.data.total_out() {
251
                // No more output and no end of stream: the input was
252
                // truncated, mirroring the check in `read` above.
253
0
                if D::REQUIRES_STREAM_END && !allow_incomplete {
254
0
                    return Err(io::Error::new(
255
0
                        io::ErrorKind::UnexpectedEof,
256
0
                        "incomplete deflate stream",
257
0
                    ));
258
0
                }
259
0
                return Ok(());
260
0
            }
261
        }
262
21.2k
    }
263
264
0
    pub fn replace(&mut self, w: W) -> W {
265
0
        self.buf.clear();
266
0
        self.finished = false;
267
0
        self.buf_pos = 0;
268
0
        mem::replace(self.get_mut(), w)
269
0
    }
270
271
0
    pub fn get_ref(&self) -> &W {
272
0
        self.obj.as_ref().unwrap()
273
0
    }
274
275
0
    pub fn get_mut(&mut self) -> &mut W {
276
0
        self.obj.as_mut().unwrap()
277
0
    }
278
279
    // Note that this should only be called if the outer object is just about
280
    // to be consumed!
281
    //
282
    // (e.g. an implementation of `into_inner`)
283
21.2k
    pub fn take_inner(&mut self) -> W {
284
21.2k
        self.obj.take().unwrap()
285
21.2k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::take_inner
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress>>::take_inner
Line
Count
Source
283
21.2k
    pub fn take_inner(&mut self) -> W {
284
21.2k
        self.obj.take().unwrap()
285
21.2k
    }
286
287
0
    pub fn is_present(&self) -> bool {
288
0
        self.obj.is_some()
289
0
    }
290
291
    // Returns total written bytes and status of underlying codec
292
21.2k
    pub(crate) fn write_with_status(&mut self, buf: &[u8]) -> io::Result<(usize, Status)> {
293
        // miniz isn't guaranteed to actually write any of the buffer provided,
294
        // it may be in a flushing mode where it's just giving us data before
295
        // we're actually giving it any data. We don't want to spuriously return
296
        // `Ok(0)` when possible as it will cause calls to write_all() to fail.
297
        // As a result we execute this in a loop to ensure that we try our
298
        // darndest to write the data.
299
        loop {
300
21.2k
            self.dump()?;
301
302
21.2k
            let before_in = self.data.total_in();
303
21.2k
            let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none());
304
21.2k
            let written = (self.data.total_in() - before_in) as usize;
305
21.2k
            let is_stream_end = matches!(ret, Ok(Status::StreamEnd));
306
307
            // Without input consumed or output to drain, retrying can loop forever.
308
21.2k
            if !buf.is_empty()
309
21.2k
                && written == 0
310
0
                && ret.is_ok()
311
0
                && !is_stream_end
312
0
                && !self.buf.is_empty()
313
            {
314
0
                continue;
315
21.2k
            }
316
21.2k
            if is_stream_end {
317
0
                self.finished = true;
318
21.2k
            }
319
21.2k
            return match ret {
320
21.2k
                Ok(st) => match st {
321
21.2k
                    Status::Ok | Status::BufError | Status::StreamEnd => Ok((written, st)),
322
                },
323
0
                Err(..) => Err(io::Error::new(
324
0
                    io::ErrorKind::InvalidInput,
325
0
                    "corrupt deflate stream",
326
0
                )),
327
            };
328
        }
329
21.2k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::write_with_status
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress>>::write_with_status
Line
Count
Source
292
21.2k
    pub(crate) fn write_with_status(&mut self, buf: &[u8]) -> io::Result<(usize, Status)> {
293
        // miniz isn't guaranteed to actually write any of the buffer provided,
294
        // it may be in a flushing mode where it's just giving us data before
295
        // we're actually giving it any data. We don't want to spuriously return
296
        // `Ok(0)` when possible as it will cause calls to write_all() to fail.
297
        // As a result we execute this in a loop to ensure that we try our
298
        // darndest to write the data.
299
        loop {
300
21.2k
            self.dump()?;
301
302
21.2k
            let before_in = self.data.total_in();
303
21.2k
            let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none());
304
21.2k
            let written = (self.data.total_in() - before_in) as usize;
305
21.2k
            let is_stream_end = matches!(ret, Ok(Status::StreamEnd));
306
307
            // Without input consumed or output to drain, retrying can loop forever.
308
21.2k
            if !buf.is_empty()
309
21.2k
                && written == 0
310
0
                && ret.is_ok()
311
0
                && !is_stream_end
312
0
                && !self.buf.is_empty()
313
            {
314
0
                continue;
315
21.2k
            }
316
21.2k
            if is_stream_end {
317
0
                self.finished = true;
318
21.2k
            }
319
21.2k
            return match ret {
320
21.2k
                Ok(st) => match st {
321
21.2k
                    Status::Ok | Status::BufError | Status::StreamEnd => Ok((written, st)),
322
                },
323
0
                Err(..) => Err(io::Error::new(
324
0
                    io::ErrorKind::InvalidInput,
325
0
                    "corrupt deflate stream",
326
0
                )),
327
            };
328
        }
329
21.2k
    }
330
331
63.6k
    fn dump(&mut self) -> io::Result<()> {
332
63.6k
        let obj = self
333
63.6k
            .obj
334
63.6k
            .as_mut()
335
63.6k
            .expect("inner writer should only be taken when the outer writer is consumed");
336
84.9k
        while self.buf_pos < self.buf.len() {
337
21.2k
            let n = obj.write(&self.buf[self.buf_pos..])?;
338
21.2k
            if n == 0 {
339
10
                return Err(io::ErrorKind::WriteZero.into());
340
21.2k
            }
341
21.2k
            self.buf_pos += n;
342
        }
343
63.6k
        self.buf.clear();
344
63.6k
        self.buf_pos = 0;
345
63.6k
        Ok(())
346
63.6k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::dump
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress>>::dump
Line
Count
Source
331
63.6k
    fn dump(&mut self) -> io::Result<()> {
332
63.6k
        let obj = self
333
63.6k
            .obj
334
63.6k
            .as_mut()
335
63.6k
            .expect("inner writer should only be taken when the outer writer is consumed");
336
84.9k
        while self.buf_pos < self.buf.len() {
337
21.2k
            let n = obj.write(&self.buf[self.buf_pos..])?;
338
21.2k
            if n == 0 {
339
10
                return Err(io::ErrorKind::WriteZero.into());
340
21.2k
            }
341
21.2k
            self.buf_pos += n;
342
        }
343
63.6k
        self.buf.clear();
344
63.6k
        self.buf_pos = 0;
345
63.6k
        Ok(())
346
63.6k
    }
347
}
348
349
impl<W: Write, D: Ops> Write for Writer<W, D> {
350
21.2k
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
351
21.2k
        self.write_with_status(buf).map(|res| res.0)
352
21.2k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _> as std::io::Write>::write
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress> as std::io::Write>::write
Line
Count
Source
350
21.2k
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
351
21.2k
        self.write_with_status(buf).map(|res| res.0)
352
21.2k
    }
353
354
0
    fn flush(&mut self) -> io::Result<()> {
355
0
        D::flush(self)?;
356
357
0
        self.obj
358
0
            .as_mut()
359
0
            .expect("inner writer should only be taken when the outer writer is consumed")
360
0
            .flush()
361
0
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _> as std::io::Write>::flush
Unexecuted instantiation: <flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress> as std::io::Write>::flush
362
}
363
364
impl<W: Write, D: Ops> Drop for Writer<W, D> {
365
21.2k
    fn drop(&mut self) {
366
21.2k
        if self.obj.is_some() {
367
5
            let _ = self.finish();
368
21.2k
        }
369
21.2k
    }
Unexecuted instantiation: <flate2::zio::Writer<_, _> as core::ops::drop::Drop>::drop
<flate2::zio::Writer<zip::write::MaybeEncrypted<std::io::cursor::Cursor<&mut [u8]>>, flate2::mem::Compress> as core::ops::drop::Drop>::drop
Line
Count
Source
365
21.2k
    fn drop(&mut self) {
366
21.2k
        if self.obj.is_some() {
367
5
            let _ = self.finish();
368
21.2k
        }
369
21.2k
    }
370
}