1use crate::{BlockType, DeflateEncoder, Error, Options, Write};
2
3pub struct ZlibEncoder<W: Write> {
11 deflate_encoder: Option<DeflateEncoder<W>>,
12 adler_hasher: simd_adler32::Adler32,
13}
14
15impl<W: Write> ZlibEncoder<W> {
16 pub fn new(options: Options, btype: BlockType, mut sink: W) -> Result<Self, Error> {
19 let cmf = 120; let flevel = 3;
21 let fdict = 0;
22 let mut cmfflg: u16 = 256 * cmf + fdict * 32 + flevel * 64;
23 let fcheck = 31 - cmfflg % 31;
24 cmfflg += fcheck;
25
26 sink.write_all(&cmfflg.to_be_bytes())?;
27
28 Ok(Self {
29 deflate_encoder: Some(DeflateEncoder::new(options, btype, sink)),
30 adler_hasher: simd_adler32::Adler32::new(),
31 })
32 }
33
34 #[cfg(feature = "std")]
39 pub fn new_buffered(
40 options: Options,
41 btype: BlockType,
42 sink: W,
43 ) -> Result<std::io::BufWriter<Self>, Error> {
44 Ok(std::io::BufWriter::with_capacity(
45 crate::util::ZOPFLI_MASTER_BLOCK_SIZE,
46 Self::new(options, btype, sink)?,
47 ))
48 }
49
50 pub fn finish(mut self) -> Result<W, Error> {
59 self.__finish().map(|sink| sink.unwrap())
60 }
61
62 fn __finish(&mut self) -> Result<Option<W>, Error> {
63 if self.deflate_encoder.is_none() {
64 return Ok(None);
65 }
66
67 let mut sink = self.deflate_encoder.take().unwrap().finish()?;
68
69 sink.write_all(&self.adler_hasher.finish().to_be_bytes())?;
70
71 Ok(Some(sink))
72 }
73
74 pub fn get_ref(&self) -> &W {
76 self.deflate_encoder.as_ref().unwrap().get_ref()
77 }
78
79 pub fn get_mut(&mut self) -> &mut W {
84 self.deflate_encoder.as_mut().unwrap().get_mut()
85 }
86}
87
88impl<W: Write> Write for ZlibEncoder<W> {
89 fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
90 self.deflate_encoder
91 .as_mut()
92 .unwrap()
93 .write(buf)
94 .map(|bytes_written| {
95 self.adler_hasher.write(&buf[..bytes_written]);
96 bytes_written
97 })
98 }
99
100 fn flush(&mut self) -> Result<(), Error> {
101 self.deflate_encoder.as_mut().unwrap().flush()
102 }
103}
104
105impl<W: Write> Drop for ZlibEncoder<W> {
106 fn drop(&mut self) {
107 self.__finish().ok();
108 }
109}
110
111#[cfg(all(doc, feature = "std"))]
113impl<W: crate::io::Write> std::io::Write for ZlibEncoder<W> {
114 fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
115 unimplemented!()
116 }
117
118 fn flush(&mut self) -> std::io::Result<()> {
119 unimplemented!()
120 }
121}