Coverage Report

Created: 2026-09-01 07:45

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
0
    fn total_in(&self) -> u64 {
40
0
        self.total_in()
41
0
    }
42
0
    fn total_out(&self) -> u64 {
43
0
        self.total_out()
44
0
    }
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
0
    fn run_vec(
54
0
        &mut self,
55
0
        input: &[u8],
56
0
        output: &mut Vec<u8>,
57
0
        flush: FlushCompress,
58
0
    ) -> Result<Status, CompressError> {
59
0
        self.compress_vec(input, output, flush)
60
0
    }
61
}
62
63
impl Ops for Decompress {
64
    type Error = DecompressError;
65
    type Flush = FlushDecompress;
66
838k
    fn total_in(&self) -> u64 {
67
838k
        self.total_in()
68
838k
    }
69
838k
    fn total_out(&self) -> u64 {
70
838k
        self.total_out()
71
838k
    }
72
419k
    fn run(
73
419k
        &mut self,
74
419k
        input: &[u8],
75
419k
        output: &mut [u8],
76
419k
        flush: FlushDecompress,
77
419k
    ) -> Result<Status, DecompressError> {
78
419k
        self.decompress(input, output, flush)
79
419k
    }
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
0
    fn none() -> Self {
98
0
        FlushCompress::None
99
0
    }
100
101
0
    fn sync() -> Self {
102
0
        FlushCompress::Sync
103
0
    }
104
105
0
    fn finish() -> Self {
106
0
        FlushCompress::Finish
107
0
    }
108
}
109
110
impl Flush for FlushDecompress {
111
417k
    fn none() -> Self {
112
417k
        FlushDecompress::None
113
417k
    }
114
115
0
    fn sync() -> Self {
116
0
        FlushDecompress::Sync
117
0
    }
118
119
2.25k
    fn finish() -> Self {
120
2.25k
        FlushDecompress::Finish
121
2.25k
    }
122
}
123
124
419k
pub fn read<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize>
125
419k
where
126
419k
    R: BufRead,
127
419k
    D: Ops,
128
{
129
    loop {
130
        let (read, consumed, ret, eof);
131
        {
132
419k
            let input = obj.fill_buf()?;
133
419k
            eof = input.is_empty();
134
419k
            let before_out = data.total_out();
135
419k
            let before_in = data.total_in();
136
419k
            let flush = if eof {
137
2.25k
                D::Flush::finish()
138
            } else {
139
417k
                D::Flush::none()
140
            };
141
419k
            ret = data.run(input, dst, flush);
142
419k
            read = (data.total_out() - before_out) as usize;
143
419k
            consumed = (data.total_in() - before_in) as usize;
144
        }
145
419k
        obj.consume(consumed);
146
147
417k
        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
417k
            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
417k
            Ok(Status::Ok | Status::BufError) if read == 0 && eof && !dst.is_empty() => {
156
435
                return Err(io::Error::new(
157
435
                    io::ErrorKind::UnexpectedEof,
158
435
                    "incomplete deflate stream",
159
435
                ));
160
            }
161
418k
            Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read),
162
163
            Err(..) => {
164
283
                return Err(io::Error::new(
165
283
                    io::ErrorKind::InvalidInput,
166
283
                    "corrupt deflate stream",
167
283
                ))
168
            }
169
        }
170
    }
171
419k
}
flate2::zio::read::<flate2::bufreader::BufReader<&mut std::io::cursor::Cursor<&[u8]>>, flate2::mem::Decompress>
Line
Count
Source
124
419k
pub fn read<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize>
125
419k
where
126
419k
    R: BufRead,
127
419k
    D: Ops,
128
{
129
    loop {
130
        let (read, consumed, ret, eof);
131
        {
132
419k
            let input = obj.fill_buf()?;
133
419k
            eof = input.is_empty();
134
419k
            let before_out = data.total_out();
135
419k
            let before_in = data.total_in();
136
419k
            let flush = if eof {
137
2.25k
                D::Flush::finish()
138
            } else {
139
417k
                D::Flush::none()
140
            };
141
419k
            ret = data.run(input, dst, flush);
142
419k
            read = (data.total_out() - before_out) as usize;
143
419k
            consumed = (data.total_in() - before_in) as usize;
144
        }
145
419k
        obj.consume(consumed);
146
147
417k
        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
417k
            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
417k
            Ok(Status::Ok | Status::BufError) if read == 0 && eof && !dst.is_empty() => {
156
435
                return Err(io::Error::new(
157
435
                    io::ErrorKind::UnexpectedEof,
158
435
                    "incomplete deflate stream",
159
435
                ));
160
            }
161
418k
            Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read),
162
163
            Err(..) => {
164
283
                return Err(io::Error::new(
165
283
                    io::ErrorKind::InvalidInput,
166
283
                    "corrupt deflate stream",
167
283
                ))
168
            }
169
        }
170
    }
171
419k
}
Unexecuted instantiation: flate2::zio::read::<_, _>
172
173
impl<W: Write, D: Ops> Writer<W, D> {
174
0
    pub fn new(w: W, d: D) -> Writer<W, D> {
175
0
        Writer {
176
0
            obj: Some(w),
177
0
            data: d,
178
0
            buf: Vec::with_capacity(32 * 1024),
179
0
        }
180
0
    }
Unexecuted instantiation: <flate2::zio::Writer<alloc::vec::Vec<u8>, flate2::mem::Compress>>::new
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::new
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut alloc::vec::Vec<u8>, flate2::mem::Compress>>::new
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, flate2::mem::Compress>>::new
181
182
0
    pub fn finish(&mut self) -> io::Result<()> {
183
        loop {
184
0
            self.dump()?;
185
186
0
            let before = self.data.total_out();
187
0
            self.data
188
0
                .run_vec(&[], &mut self.buf, Flush::finish())
189
0
                .map_err(Into::into)?;
190
0
            if before == self.data.total_out() {
191
0
                return Ok(());
192
0
            }
193
        }
194
0
    }
Unexecuted instantiation: <flate2::zio::Writer<alloc::vec::Vec<u8>, flate2::mem::Compress>>::finish
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::finish
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut alloc::vec::Vec<u8>, flate2::mem::Compress>>::finish
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, flate2::mem::Compress>>::finish
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
0
    pub fn take_inner(&mut self) -> W {
214
0
        self.obj.take().unwrap()
215
0
    }
Unexecuted instantiation: <flate2::zio::Writer<alloc::vec::Vec<u8>, flate2::mem::Compress>>::take_inner
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::take_inner
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
0
    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
0
            self.dump()?;
231
232
0
            let before_in = self.data.total_in();
233
0
            let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none());
234
0
            let written = (self.data.total_in() - before_in) as usize;
235
0
            let is_stream_end = matches!(ret, Ok(Status::StreamEnd));
236
237
0
            if !buf.is_empty() && written == 0 && ret.is_ok() && !is_stream_end {
238
0
                continue;
239
0
            }
240
0
            return match ret {
241
0
                Ok(st) => match st {
242
0
                    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
0
    }
Unexecuted instantiation: <flate2::zio::Writer<alloc::vec::Vec<u8>, flate2::mem::Compress>>::write_with_status
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::write_with_status
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut alloc::vec::Vec<u8>, flate2::mem::Compress>>::write_with_status
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, flate2::mem::Compress>>::write_with_status
251
252
0
    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
0
        while !self.buf.is_empty() {
256
0
            let n = self.obj.as_mut().unwrap().write(&self.buf)?;
257
0
            if n == 0 {
258
0
                return Err(io::ErrorKind::WriteZero.into());
259
0
            }
260
0
            self.buf.drain(..n);
261
        }
262
0
        Ok(())
263
0
    }
Unexecuted instantiation: <flate2::zio::Writer<alloc::vec::Vec<u8>, flate2::mem::Compress>>::dump
Unexecuted instantiation: <flate2::zio::Writer<_, _>>::dump
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut alloc::vec::Vec<u8>, flate2::mem::Compress>>::dump
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, flate2::mem::Compress>>::dump
264
}
265
266
impl<W: Write, D: Ops> Write for Writer<W, D> {
267
0
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
268
0
        self.write_with_status(buf).map(|res| res.0)
269
0
    }
Unexecuted instantiation: <flate2::zio::Writer<alloc::vec::Vec<u8>, flate2::mem::Compress> as std::io::Write>::write
Unexecuted instantiation: <flate2::zio::Writer<_, _> as std::io::Write>::write
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut alloc::vec::Vec<u8>, flate2::mem::Compress> as std::io::Write>::write
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, flate2::mem::Compress> as std::io::Write>::write
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
    }
294
}
295
296
impl<W: Write, D: Ops> Drop for Writer<W, D> {
297
0
    fn drop(&mut self) {
298
0
        if self.obj.is_some() {
299
0
            let _ = self.finish();
300
0
        }
301
0
    }
Unexecuted instantiation: <flate2::zio::Writer<alloc::vec::Vec<u8>, flate2::mem::Compress> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <flate2::zio::Writer<_, _> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut alloc::vec::Vec<u8>, flate2::mem::Compress> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <flate2::zio::Writer<&mut &mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>, flate2::mem::Compress> as core::ops::drop::Drop>::drop
302
}