gix_features/zlib/stream/deflate/
mod.rs1use flate2::Compress;
2
3const BUF_SIZE: usize = 4096 * 8;
4
5pub struct Write<W> {
9 compressor: Compress,
10 inner: W,
11 buf: [u8; BUF_SIZE],
12}
13
14impl<W> Clone for Write<W>
15where
16 W: Clone,
17{
18 fn clone(&self) -> Self {
19 Write {
20 compressor: impls::new_compress(),
21 inner: self.inner.clone(),
22 buf: self.buf,
23 }
24 }
25}
26
27mod impls {
28 use std::io;
29
30 use flate2::{Compress, Compression, FlushCompress, Status};
31
32 use crate::zlib::stream::deflate;
33
34 pub(crate) fn new_compress() -> Compress {
35 Compress::new(Compression::fast(), true)
36 }
37
38 impl<W> deflate::Write<W>
39 where
40 W: io::Write,
41 {
42 pub fn new(inner: W) -> deflate::Write<W> {
44 deflate::Write {
45 compressor: new_compress(),
46 inner,
47 buf: [0; deflate::BUF_SIZE],
48 }
49 }
50
51 pub fn reset(&mut self) {
55 self.compressor.reset();
56 }
57
58 pub fn into_inner(self) -> W {
60 self.inner
61 }
62
63 fn write_inner(&mut self, mut buf: &[u8], flush: FlushCompress) -> io::Result<usize> {
64 let total_in_when_start = self.compressor.total_in();
65 loop {
66 let last_total_in = self.compressor.total_in();
67 let last_total_out = self.compressor.total_out();
68
69 let status = self
70 .compressor
71 .compress(buf, &mut self.buf, flush)
72 .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
73
74 let written = self.compressor.total_out() - last_total_out;
75 if written > 0 {
76 self.inner.write_all(&self.buf[..written as usize])?;
77 }
78
79 match status {
80 Status::StreamEnd => return Ok((self.compressor.total_in() - total_in_when_start) as usize),
81 Status::Ok | Status::BufError => {
82 let consumed = self.compressor.total_in() - last_total_in;
83 buf = &buf[consumed as usize..];
84
85 if self.compressor.total_out() > last_total_out {
87 continue;
88 }
89 if self.compressor.total_in() > last_total_in {
91 continue;
92 }
93 return Ok((self.compressor.total_in() - total_in_when_start) as usize);
95 }
96 }
97 }
98 }
99 }
100
101 impl<W: io::Write> io::Write for deflate::Write<W> {
102 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
103 self.write_inner(buf, FlushCompress::None)
104 }
105
106 fn flush(&mut self) -> io::Result<()> {
107 self.write_inner(&[], FlushCompress::Finish).map(|_| ())
108 }
109 }
110}
111
112#[cfg(test)]
113mod tests;