Coverage Report

Created: 2026-08-31 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flate2-1.1.10/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
}
16
17
pub trait Ops {
18
    type Error: Into<io::Error>;
19
    type Flush: Flush;
20
    fn total_in(&self) -> u64;
21
    fn total_out(&self) -> u64;
22
    fn run(
23
        &mut self,
24
        input: &[u8],
25
        output: &mut [u8],
26
        flush: Self::Flush,
27
    ) -> Result<Status, Self::Error>;
28
    fn run_vec(
29
        &mut self,
30
        input: &[u8],
31
        output: &mut Vec<u8>,
32
        flush: Self::Flush,
33
    ) -> Result<Status, Self::Error>;
34
}
35
36
impl Ops for Compress {
37
    type Error = CompressError;
38
    type Flush = FlushCompress;
39
37.1k
    fn total_in(&self) -> u64 {
40
37.1k
        self.total_in()
41
37.1k
    }
42
74.2k
    fn total_out(&self) -> u64 {
43
74.2k
        self.total_out()
44
74.2k
    }
45
0
    fn run(
46
0
        &mut self,
47
0
        input: &[u8],
48
0
        output: &mut [u8],
49
0
        flush: FlushCompress,
50
0
    ) -> Result<Status, CompressError> {
51
0
        self.compress(input, output, flush)
52
0
    }
53
55.7k
    fn run_vec(
54
55.7k
        &mut self,
55
55.7k
        input: &[u8],
56
55.7k
        output: &mut Vec<u8>,
57
55.7k
        flush: FlushCompress,
58
55.7k
    ) -> Result<Status, CompressError> {
59
55.7k
        self.compress_vec(input, output, flush)
60
55.7k
    }
61
}
62
63
impl Ops for Decompress {
64
    type Error = DecompressError;
65
    type Flush = FlushDecompress;
66
171k
    fn total_in(&self) -> u64 {
67
171k
        self.total_in()
68
171k
    }
69
171k
    fn total_out(&self) -> u64 {
70
171k
        self.total_out()
71
171k
    }
72
85.6k
    fn run(
73
85.6k
        &mut self,
74
85.6k
        input: &[u8],
75
85.6k
        output: &mut [u8],
76
85.6k
        flush: FlushDecompress,
77
85.6k
    ) -> Result<Status, DecompressError> {
78
85.6k
        self.decompress(input, output, flush)
79
85.6k
    }
80
0
    fn run_vec(
81
0
        &mut self,
82
0
        input: &[u8],
83
0
        output: &mut Vec<u8>,
84
0
        flush: FlushDecompress,
85
0
    ) -> Result<Status, DecompressError> {
86
0
        self.decompress_vec(input, output, flush)
87
0
    }
88
}
89
90
pub trait Flush {
91
    fn none() -> Self;
92
    fn sync() -> Self;
93
    fn finish() -> Self;
94
}
95
96
impl Flush for FlushCompress {
97
18.5k
    fn none() -> Self {
98
18.5k
        FlushCompress::None
99
18.5k
    }
100
101
0
    fn sync() -> Self {
102
0
        FlushCompress::Sync
103
0
    }
104
105
37.1k
    fn finish() -> Self {
106
37.1k
        FlushCompress::Finish
107
37.1k
    }
108
}
109
110
impl Flush for FlushDecompress {
111
57.6k
    fn none() -> Self {
112
57.6k
        FlushDecompress::None
113
57.6k
    }
114
115
0
    fn sync() -> Self {
116
0
        FlushDecompress::Sync
117
0
    }
118
119
28.0k
    fn finish() -> Self {
120
28.0k
        FlushDecompress::Finish
121
28.0k
    }
122
}
123
124
85.8k
pub fn read<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize>
125
85.8k
where
126
85.8k
    R: BufRead,
127
85.8k
    D: Ops,
128
{
129
    loop {
130
        let (read, consumed, ret, eof);
131
        {
132
85.8k
            let input = obj.fill_buf()?;
133
85.6k
            eof = input.is_empty();
134
85.6k
            let before_out = data.total_out();
135
85.6k
            let before_in = data.total_in();
136
85.6k
            let flush = if eof {
137
28.0k
                D::Flush::finish()
138
            } else {
139
57.6k
                D::Flush::none()
140
            };
141
85.6k
            ret = data.run(input, dst, flush);
142
85.6k
            read = (data.total_out() - before_out) as usize;
143
85.6k
            consumed = (data.total_in() - before_in) as usize;
144
        }
145
85.6k
        obj.consume(consumed);
146
147
41.0k
        match ret {
148
            // If we haven't read any data and we haven't hit EOF yet,
149
            // then we need to keep asking for more data because if we
150
            // return that 0 bytes of data have been read then it will
151
            // be interpreted as EOF.
152
41.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && !eof && !dst.is_empty() => continue,
153
            // If we haven't read any data and we have hit EOF, then the
154
            // deflate stream is incomplete.
155
41.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && eof && !dst.is_empty() => {
156
3.08k
                return Err(io::Error::new(
157
3.08k
                    io::ErrorKind::UnexpectedEof,
158
3.08k
                    "incomplete deflate stream",
159
3.08k
                ));
160
            }
161
67.1k
            Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read),
162
163
            Err(..) => {
164
15.4k
                return Err(io::Error::new(
165
15.4k
                    io::ErrorKind::InvalidInput,
166
15.4k
                    "corrupt deflate stream",
167
15.4k
                ))
168
            }
169
        }
170
    }
171
85.8k
}
flate2::zio::read::<flate2::bufreader::BufReader<zip::read::CryptoReader>, flate2::mem::Decompress>
Line
Count
Source
124
85.8k
pub fn read<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize>
125
85.8k
where
126
85.8k
    R: BufRead,
127
85.8k
    D: Ops,
128
{
129
    loop {
130
        let (read, consumed, ret, eof);
131
        {
132
85.8k
            let input = obj.fill_buf()?;
133
85.6k
            eof = input.is_empty();
134
85.6k
            let before_out = data.total_out();
135
85.6k
            let before_in = data.total_in();
136
85.6k
            let flush = if eof {
137
28.0k
                D::Flush::finish()
138
            } else {
139
57.6k
                D::Flush::none()
140
            };
141
85.6k
            ret = data.run(input, dst, flush);
142
85.6k
            read = (data.total_out() - before_out) as usize;
143
85.6k
            consumed = (data.total_in() - before_in) as usize;
144
        }
145
85.6k
        obj.consume(consumed);
146
147
41.0k
        match ret {
148
            // If we haven't read any data and we haven't hit EOF yet,
149
            // then we need to keep asking for more data because if we
150
            // return that 0 bytes of data have been read then it will
151
            // be interpreted as EOF.
152
41.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && !eof && !dst.is_empty() => continue,
153
            // If we haven't read any data and we have hit EOF, then the
154
            // deflate stream is incomplete.
155
41.0k
            Ok(Status::Ok | Status::BufError) if read == 0 && eof && !dst.is_empty() => {
156
3.08k
                return Err(io::Error::new(
157
3.08k
                    io::ErrorKind::UnexpectedEof,
158
3.08k
                    "incomplete deflate stream",
159
3.08k
                ));
160
            }
161
67.1k
            Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read),
162
163
            Err(..) => {
164
15.4k
                return Err(io::Error::new(
165
15.4k
                    io::ErrorKind::InvalidInput,
166
15.4k
                    "corrupt deflate stream",
167
15.4k
                ))
168
            }
169
        }
170
    }
171
85.8k
}
Unexecuted instantiation: flate2::zio::read::<_, _>
172
173
impl<W: Write, D: Ops> Writer<W, D> {
174
18.5k
    pub fn new(w: W, d: D) -> Writer<W, D> {
175
18.5k
        Writer {
176
18.5k
            obj: Some(w),
177
18.5k
            data: d,
178
18.5k
            buf: Vec::with_capacity(32 * 1024),
179
18.5k
        }
180
18.5k
    }
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
174
18.5k
    pub fn new(w: W, d: D) -> Writer<W, D> {
175
18.5k
        Writer {
176
18.5k
            obj: Some(w),
177
18.5k
            data: d,
178
18.5k
            buf: Vec::with_capacity(32 * 1024),
179
18.5k
        }
180
18.5k
    }
181
182
18.5k
    pub fn finish(&mut self) -> io::Result<()> {
183
        loop {
184
37.1k
            self.dump()?;
185
186
37.1k
            let before = self.data.total_out();
187
37.1k
            self.data
188
37.1k
                .run_vec(&[], &mut self.buf, Flush::finish())
189
37.1k
                .map_err(Into::into)?;
190
37.1k
            if before == self.data.total_out() {
191
18.5k
                return Ok(());
192
18.5k
            }
193
        }
194
18.5k
    }
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
182
18.5k
    pub fn finish(&mut self) -> io::Result<()> {
183
        loop {
184
37.1k
            self.dump()?;
185
186
37.1k
            let before = self.data.total_out();
187
37.1k
            self.data
188
37.1k
                .run_vec(&[], &mut self.buf, Flush::finish())
189
37.1k
                .map_err(Into::into)?;
190
37.1k
            if before == self.data.total_out() {
191
18.5k
                return Ok(());
192
18.5k
            }
193
        }
194
18.5k
    }
195
196
0
    pub fn replace(&mut self, w: W) -> W {
197
0
        self.buf.clear();
198
0
        mem::replace(self.get_mut(), w)
199
0
    }
200
201
0
    pub fn get_ref(&self) -> &W {
202
0
        self.obj.as_ref().unwrap()
203
0
    }
204
205
0
    pub fn get_mut(&mut self) -> &mut W {
206
0
        self.obj.as_mut().unwrap()
207
0
    }
208
209
    // Note that this should only be called if the outer object is just about
210
    // to be consumed!
211
    //
212
    // (e.g. an implementation of `into_inner`)
213
18.5k
    pub fn take_inner(&mut self) -> W {
214
18.5k
        self.obj.take().unwrap()
215
18.5k
    }
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
213
18.5k
    pub fn take_inner(&mut self) -> W {
214
18.5k
        self.obj.take().unwrap()
215
18.5k
    }
216
217
0
    pub fn is_present(&self) -> bool {
218
0
        self.obj.is_some()
219
0
    }
220
221
    // Returns total written bytes and status of underlying codec
222
18.5k
    pub(crate) fn write_with_status(&mut self, buf: &[u8]) -> io::Result<(usize, Status)> {
223
        // miniz isn't guaranteed to actually write any of the buffer provided,
224
        // it may be in a flushing mode where it's just giving us data before
225
        // we're actually giving it any data. We don't want to spuriously return
226
        // `Ok(0)` when possible as it will cause calls to write_all() to fail.
227
        // As a result we execute this in a loop to ensure that we try our
228
        // darndest to write the data.
229
        loop {
230
18.5k
            self.dump()?;
231
232
18.5k
            let before_in = self.data.total_in();
233
18.5k
            let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none());
234
18.5k
            let written = (self.data.total_in() - before_in) as usize;
235
18.5k
            let is_stream_end = matches!(ret, Ok(Status::StreamEnd));
236
237
18.5k
            if !buf.is_empty() && written == 0 && ret.is_ok() && !is_stream_end {
238
0
                continue;
239
18.5k
            }
240
18.5k
            return match ret {
241
18.5k
                Ok(st) => match st {
242
18.5k
                    Status::Ok | Status::BufError | Status::StreamEnd => Ok((written, st)),
243
                },
244
0
                Err(..) => Err(io::Error::new(
245
0
                    io::ErrorKind::InvalidInput,
246
0
                    "corrupt deflate stream",
247
0
                )),
248
            };
249
        }
250
18.5k
    }
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
222
18.5k
    pub(crate) fn write_with_status(&mut self, buf: &[u8]) -> io::Result<(usize, Status)> {
223
        // miniz isn't guaranteed to actually write any of the buffer provided,
224
        // it may be in a flushing mode where it's just giving us data before
225
        // we're actually giving it any data. We don't want to spuriously return
226
        // `Ok(0)` when possible as it will cause calls to write_all() to fail.
227
        // As a result we execute this in a loop to ensure that we try our
228
        // darndest to write the data.
229
        loop {
230
18.5k
            self.dump()?;
231
232
18.5k
            let before_in = self.data.total_in();
233
18.5k
            let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none());
234
18.5k
            let written = (self.data.total_in() - before_in) as usize;
235
18.5k
            let is_stream_end = matches!(ret, Ok(Status::StreamEnd));
236
237
18.5k
            if !buf.is_empty() && written == 0 && ret.is_ok() && !is_stream_end {
238
0
                continue;
239
18.5k
            }
240
18.5k
            return match ret {
241
18.5k
                Ok(st) => match st {
242
18.5k
                    Status::Ok | Status::BufError | Status::StreamEnd => Ok((written, st)),
243
                },
244
0
                Err(..) => Err(io::Error::new(
245
0
                    io::ErrorKind::InvalidInput,
246
0
                    "corrupt deflate stream",
247
0
                )),
248
            };
249
        }
250
18.5k
    }
251
252
55.7k
    fn dump(&mut self) -> io::Result<()> {
253
        // TODO: should manage this buffer not with `drain` but probably more of
254
        // a deque-like strategy.
255
74.3k
        while !self.buf.is_empty() {
256
18.6k
            let n = self.obj.as_mut().unwrap().write(&self.buf)?;
257
18.6k
            if n == 0 {
258
8
                return Err(io::ErrorKind::WriteZero.into());
259
18.6k
            }
260
18.6k
            self.buf.drain(..n);
261
        }
262
55.7k
        Ok(())
263
55.7k
    }
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
252
55.7k
    fn dump(&mut self) -> io::Result<()> {
253
        // TODO: should manage this buffer not with `drain` but probably more of
254
        // a deque-like strategy.
255
74.3k
        while !self.buf.is_empty() {
256
18.6k
            let n = self.obj.as_mut().unwrap().write(&self.buf)?;
257
18.6k
            if n == 0 {
258
8
                return Err(io::ErrorKind::WriteZero.into());
259
18.6k
            }
260
18.6k
            self.buf.drain(..n);
261
        }
262
55.7k
        Ok(())
263
55.7k
    }
264
}
265
266
impl<W: Write, D: Ops> Write for Writer<W, D> {
267
18.5k
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
268
18.5k
        self.write_with_status(buf).map(|res| res.0)
269
18.5k
    }
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
267
18.5k
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
268
18.5k
        self.write_with_status(buf).map(|res| res.0)
269
18.5k
    }
270
271
0
    fn flush(&mut self) -> io::Result<()> {
272
0
        self.data
273
0
            .run_vec(&[], &mut self.buf, Flush::sync())
274
0
            .map_err(Into::into)?;
275
276
        // Unfortunately miniz doesn't actually tell us when we're done with
277
        // pulling out all the data from the internal stream. To remedy this we
278
        // have to continually ask the stream for more memory until it doesn't
279
        // give us a chunk of memory the same size as our own internal buffer,
280
        // at which point we assume it's reached the end.
281
        loop {
282
0
            self.dump()?;
283
0
            let before = self.data.total_out();
284
0
            self.data
285
0
                .run_vec(&[], &mut self.buf, Flush::none())
286
0
                .map_err(Into::into)?;
287
0
            if before == self.data.total_out() {
288
0
                break;
289
0
            }
290
        }
291
292
0
        self.obj.as_mut().unwrap().flush()
293
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
294
}
295
296
impl<W: Write, D: Ops> Drop for Writer<W, D> {
297
18.5k
    fn drop(&mut self) {
298
18.5k
        if self.obj.is_some() {
299
4
            let _ = self.finish();
300
18.5k
        }
301
18.5k
    }
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
297
18.5k
    fn drop(&mut self) {
298
18.5k
        if self.obj.is_some() {
299
4
            let _ = self.finish();
300
18.5k
        }
301
18.5k
    }
302
}