Coverage Report

Created: 2025-07-12 07:18

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