1use std::io::Write;
2use std::{io, thread};
3
4use crate::checksum::{Adler32Checksum, RollingChecksum};
5use crate::compress::compress_data_dynamic_n;
6use crate::compress::Flush;
7use crate::compression_options::CompressionOptions;
8use crate::deflate_state::DeflateState;
9use crate::zlib::{write_zlib_header, CompressionLevel};
10
11const ERR_STR: &str = "Error! The wrapped writer is missing.\
12 This is a bug, please file an issue.";
13
14pub fn compress_until_done<W: Write>(
16 mut input: &[u8],
17 deflate_state: &mut DeflateState<W>,
18 flush_mode: Flush,
19) -> io::Result<()> {
20 assert!(flush_mode != Flush::None);
22 loop {
23 match compress_data_dynamic_n(input, deflate_state, flush_mode) {
24 Ok(0) => {
25 if deflate_state.output_buf().is_empty() {
26 break;
27 } else {
28 input = &[];
31 }
32 }
33 Ok(n) => {
34 if n < input.len() {
35 input = &input[n..]
36 } else {
37 input = &[];
38 }
39 }
40 Err(e) => {
41 match e.kind() {
42 io::ErrorKind::Interrupted => (),
46 _ => return Err(e),
47 }
48 }
49 }
50 }
51
52 debug_assert_eq!(
53 deflate_state.bytes_written,
54 deflate_state.bytes_written_control.get()
55 );
56
57 Ok(())
58}
59
60pub struct DeflateEncoder<W: Write> {
90 deflate_state: DeflateState<W>,
91}
92
93impl<W: Write> DeflateEncoder<W> {
94 pub fn new<O: Into<CompressionOptions>>(writer: W, options: O) -> DeflateEncoder<W> {
96 DeflateEncoder {
97 deflate_state: DeflateState::new(options.into(), writer),
98 }
99 }
100
101 pub fn finish(mut self) -> io::Result<W> {
104 self.output_all()?;
105 Ok(self.deflate_state.inner.take().expect(ERR_STR))
108 }
109
110 pub fn reset(&mut self, w: W) -> io::Result<W> {
113 self.output_all()?;
114 self.deflate_state.reset(w)
115 }
116
117 fn output_all(&mut self) -> io::Result<()> {
119 compress_until_done(&[], &mut self.deflate_state, Flush::Finish)
120 }
121}
122
123impl<W: Write> io::Write for DeflateEncoder<W> {
124 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
125 let flush_mode = self.deflate_state.flush_mode;
126 compress_data_dynamic_n(buf, &mut self.deflate_state, flush_mode)
127 }
128
129 fn flush(&mut self) -> io::Result<()> {
135 compress_until_done(&[], &mut self.deflate_state, Flush::Sync)
136 }
137}
138
139impl<W: Write> Drop for DeflateEncoder<W> {
140 fn drop(&mut self) {
146 if self.deflate_state.inner.is_some() && !thread::panicking() {
149 let _ = self.output_all();
150 }
151 }
152}
153
154pub struct ZlibEncoder<W: Write> {
184 deflate_state: DeflateState<W>,
185 checksum: Adler32Checksum,
186 header_written: bool,
187}
188
189impl<W: Write> ZlibEncoder<W> {
190 pub fn new<O: Into<CompressionOptions>>(writer: W, options: O) -> ZlibEncoder<W> {
192 ZlibEncoder {
193 deflate_state: DeflateState::new(options.into(), writer),
194 checksum: Adler32Checksum::new(),
195 header_written: false,
196 }
197 }
198
199 fn output_all(&mut self) -> io::Result<()> {
202 self.check_write_header()?;
203 compress_until_done(&[], &mut self.deflate_state, Flush::Finish)?;
204 self.write_trailer()
205 }
206
207 pub fn finish(mut self) -> io::Result<W> {
210 self.output_all()?;
211 Ok(self.deflate_state.inner.take().expect(ERR_STR))
214 }
215
216 pub fn reset(&mut self, writer: W) -> io::Result<W> {
219 self.output_all()?;
220 self.header_written = false;
221 self.checksum = Adler32Checksum::new();
222 self.deflate_state.reset(writer)
223 }
224
225 fn check_write_header(&mut self) -> io::Result<()> {
227 if !self.header_written {
228 write_zlib_header(self.deflate_state.output_buf(), CompressionLevel::Default)?;
229 self.header_written = true;
230 }
231 Ok(())
232 }
233
234 fn write_trailer(&mut self) -> io::Result<()> {
236 let hash = self.checksum.current_hash();
237
238 self.deflate_state
239 .inner
240 .as_mut()
241 .expect(ERR_STR)
242 .write_all(&hash.to_be_bytes())?;
243
244 Ok(())
245 }
246
247 pub fn checksum(&self) -> u32 {
249 self.checksum.current_hash()
250 }
251}
252
253impl<W: Write> io::Write for ZlibEncoder<W> {
254 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
255 self.check_write_header()?;
256 let flush_mode = self.deflate_state.flush_mode;
257 let res = compress_data_dynamic_n(buf, &mut self.deflate_state, flush_mode);
258 match res {
259 Ok(0) => self.checksum.update_from_slice(buf),
261 Ok(n) => self.checksum.update_from_slice(&buf[0..n]),
264 _ => (),
265 };
266 res
267 }
268
269 fn flush(&mut self) -> io::Result<()> {
275 compress_until_done(&[], &mut self.deflate_state, Flush::Sync)
276 }
277}
278
279impl<W: Write> Drop for ZlibEncoder<W> {
280 fn drop(&mut self) {
286 if self.deflate_state.inner.is_some() && !thread::panicking() {
287 let _ = self.output_all();
288 }
289 }
290}
291
292#[cfg(feature = "gzip")]
293pub mod gzip {
294
295 use std::io::{Cursor, Write};
296 use std::{io, thread};
297
298 use super::*;
299
300 use gzip_header::{Crc, GzBuilder};
301
302 pub struct GzEncoder<W: Write> {
332 inner: DeflateEncoder<W>,
333 checksum: Crc,
334 header: Vec<u8>,
335 }
336
337 impl<W: Write> GzEncoder<W> {
338 pub fn new<O: Into<CompressionOptions>>(writer: W, options: O) -> GzEncoder<W> {
341 GzEncoder::from_builder(GzBuilder::new(), writer, options)
342 }
343
344 pub fn from_builder<O: Into<CompressionOptions>>(
347 builder: GzBuilder,
348 writer: W,
349 options: O,
350 ) -> GzEncoder<W> {
351 GzEncoder {
352 inner: DeflateEncoder::new(writer, options),
353 checksum: Crc::new(),
354 header: builder.into_header(),
355 }
356 }
357
358 fn check_write_header(&mut self) {
360 if !self.header.is_empty() {
361 self.inner
362 .deflate_state
363 .output_buf()
364 .extend_from_slice(&self.header);
365 self.header.clear();
366 }
367 }
368
369 fn output_all(&mut self) -> io::Result<()> {
372 self.check_write_header();
373 self.inner.output_all()?;
374 self.write_trailer()
375 }
376
377 pub fn finish(mut self) -> io::Result<W> {
380 self.output_all()?;
381 Ok(self.inner.deflate_state.inner.take().expect(ERR_STR))
384 }
385
386 fn reset_no_header(&mut self, writer: W) -> io::Result<W> {
387 self.output_all()?;
388 self.checksum = Crc::new();
389 self.inner.deflate_state.reset(writer)
390 }
391
392 pub fn reset(&mut self, writer: W) -> io::Result<W> {
395 let w = self.reset_no_header(writer);
396 self.header = GzBuilder::new().into_header();
397 w
398 }
399
400 pub fn reset_with_builder(&mut self, writer: W, builder: GzBuilder) -> io::Result<W> {
404 let w = self.reset_no_header(writer);
405 self.header = builder.into_header();
406 w
407 }
408
409 fn write_trailer(&mut self) -> io::Result<()> {
411 let crc = self.checksum.sum();
412 let amount = self.checksum.amt_as_u32();
413
414 let mut buf = [0u8; 8];
417 let mut temp = Cursor::new(&mut buf[..]);
418 temp.write_all(&crc.to_le_bytes()).unwrap();
419 temp.write_all(&amount.to_le_bytes()).unwrap();
420 self.inner
421 .deflate_state
422 .inner
423 .as_mut()
424 .expect(ERR_STR)
425 .write_all(temp.into_inner())
426 }
427
428 pub fn checksum(&self) -> u32 {
430 self.checksum.sum()
431 }
432 }
433
434 impl<W: Write> io::Write for GzEncoder<W> {
435 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
436 self.check_write_header();
437 let res = self.inner.write(buf);
438 match res {
439 Ok(0) => self.checksum.update(buf),
440 Ok(n) => self.checksum.update(&buf[0..n]),
441 _ => (),
442 };
443 res
444 }
445
446 fn flush(&mut self) -> io::Result<()> {
452 self.inner.flush()
453 }
454 }
455
456 impl<W: Write> Drop for GzEncoder<W> {
457 fn drop(&mut self) {
463 if self.inner.deflate_state.inner.is_some() && !thread::panicking() {
464 let _ = self.output_all();
465 }
466 }
467 }
468
469 #[cfg(test)]
470 mod test {
471 use super::*;
472 use crate::test_utils::{decompress_gzip, get_test_data};
473 #[test]
474 fn gzip_writer() {
475 let data = get_test_data();
476 let comment = b"Comment";
477 let compressed = {
478 let mut compressor = GzEncoder::from_builder(
479 GzBuilder::new().comment(&comment[..]),
480 Vec::with_capacity(data.len() / 3),
481 CompressionOptions::default(),
482 );
483 compressor.write_all(&data[0..data.len() / 2]).unwrap();
484 compressor.write_all(&data[data.len() / 2..]).unwrap();
485 compressor.finish().unwrap()
486 };
487
488 let (dec, res) = decompress_gzip(&compressed);
489 assert_eq!(dec.comment().unwrap(), comment);
490 assert!(res == data);
491 }
492 }
493}
494
495#[cfg(test)]
496mod test {
497 use super::*;
498 use crate::compression_options::CompressionOptions;
499 use crate::test_utils::{decompress_to_end, decompress_zlib, get_test_data};
500 use std::io::Write;
501
502 #[test]
503 fn deflate_writer() {
504 let data = get_test_data();
505 let compressed = {
506 let mut compressor = DeflateEncoder::new(
507 Vec::with_capacity(data.len() / 3),
508 CompressionOptions::high(),
509 );
510 compressor.write_all(&data[0..data.len() / 2]).unwrap();
512 compressor.write_all(&data[data.len() / 2..]).unwrap();
513 compressor.finish().unwrap()
514 };
515
516 let res = decompress_to_end(&compressed);
517 assert!(res == data);
518 }
519
520 #[test]
521 fn zlib_writer() {
522 let data = get_test_data();
523 let compressed = {
524 let mut compressor = ZlibEncoder::new(
525 Vec::with_capacity(data.len() / 3),
526 CompressionOptions::high(),
527 );
528 compressor.write_all(&data[0..data.len() / 2]).unwrap();
529 compressor.write_all(&data[data.len() / 2..]).unwrap();
530 compressor.finish().unwrap()
531 };
532
533 let res = decompress_zlib(&compressed);
534 assert!(res == data);
535 }
536
537 #[test]
538 fn writer_reset() {
540 let data = get_test_data();
541 let mut compressor = DeflateEncoder::new(
542 Vec::with_capacity(data.len() / 3),
543 CompressionOptions::default(),
544 );
545 compressor.write_all(&data).unwrap();
546 let res1 = compressor
547 .reset(Vec::with_capacity(data.len() / 3))
548 .unwrap();
549 compressor.write_all(&data).unwrap();
550 let res2 = compressor.finish().unwrap();
551 assert!(res1 == res2);
552 }
553
554 #[test]
555 fn writer_reset_zlib() {
556 let data = get_test_data();
557 let mut compressor = ZlibEncoder::new(
558 Vec::with_capacity(data.len() / 3),
559 CompressionOptions::default(),
560 );
561 compressor.write_all(&data).unwrap();
562 let res1 = compressor
563 .reset(Vec::with_capacity(data.len() / 3))
564 .unwrap();
565 compressor.write_all(&data).unwrap();
566 let res2 = compressor.finish().unwrap();
567 assert!(res1 == res2);
568 }
569
570 #[test]
571 fn writer_sync() {
572 let data = get_test_data();
573 let compressed = {
574 let mut compressor = DeflateEncoder::new(
575 Vec::with_capacity(data.len() / 3),
576 CompressionOptions::default(),
577 );
578 let split = data.len() / 2;
579 compressor.write_all(&data[..split]).unwrap();
580 compressor.flush().unwrap();
581 {
582 let buf = &mut compressor.deflate_state.inner.as_mut().unwrap();
583 let buf_len = buf.len();
584 assert_eq!(buf[buf_len - 4..], [0, 0, 255, 255]);
587 }
588 compressor.write_all(&data[split..]).unwrap();
589 compressor.finish().unwrap()
590 };
591
592 let decompressed = decompress_to_end(&compressed);
593
594 assert!(decompressed == data);
595 }
596
597 #[test]
598 fn issue_18() {
600 use crate::compression_options::Compression;
601 let data = vec![0; 61000];
602 let compressed = {
603 let mut compressor = ZlibEncoder::new(Vec::new(), Compression::Default);
604 compressor.write_all(&data[..]).unwrap();
605 compressor.finish().unwrap()
606 };
607 let decompressed = decompress_zlib(&compressed);
608 assert!(decompressed == data);
609 }
610
611 #[test]
612 fn writer_sync_multiple() {
613 use std::cmp;
614 let data = get_test_data();
615 let compressed = {
616 let mut compressor = DeflateEncoder::new(
617 Vec::with_capacity(data.len() / 3),
618 CompressionOptions::default(),
619 );
620 let split = data.len() / 2;
621 compressor.write_all(&data[..split]).unwrap();
622 compressor.flush().unwrap();
623 compressor.flush().unwrap();
624 {
625 let buf = &mut compressor.deflate_state.inner.as_mut().unwrap();
626 let buf_len = buf.len();
627 assert_eq!(buf[buf_len - 4..], [0, 0, 255, 255]);
630 }
631 compressor
632 .write_all(&data[split..cmp::min(split + 2, data.len())])
633 .unwrap();
634 compressor.flush().unwrap();
635 compressor
636 .write_all(&data[cmp::min(split + 2, data.len())..])
637 .unwrap();
638 compressor.finish().unwrap()
639 };
640
641 let decompressed = decompress_to_end(&compressed);
642
643 assert!(decompressed == data);
644
645 let mut compressor = DeflateEncoder::new(
646 Vec::with_capacity(data.len() / 3),
647 CompressionOptions::default(),
648 );
649
650 compressor.flush().unwrap();
651 compressor.write_all(&[1, 2]).unwrap();
652 compressor.flush().unwrap();
653 compressor.write_all(&[3]).unwrap();
654 compressor.flush().unwrap();
655 let compressed = compressor.finish().unwrap();
656
657 let decompressed = decompress_to_end(&compressed);
658
659 assert_eq!(decompressed, [1, 2, 3]);
660 }
661}