repng 0.2.2

The PNG encoder that no one asked for.
Documentation
use Options;
use flate2::{Compress, FlushCompress};
use std::io::{self, Write};

pub struct Compressor {
    compress: Compress,
    buf: Vec<u8>,
}

impl Compressor {
    pub fn new(opts: &Options) -> Self {
        Self {
            compress: Compress::new(opts.level, true),
            buf: Vec::with_capacity(opts.buffer),
        }
    }

    pub fn reset(&mut self, opts: &Options) {
        self.compress.reset();
        self.buf.clear();
        self.buf.reserve(opts.buffer);
    }
}

pub struct Writer<'a, F> {
    compressor: &'a mut Compressor,
    handler: F,
}

impl<'a, F> Writer<'a, F> {
    pub fn new(compressor: &'a mut Compressor, handler: F) -> Self {
        Self { compressor, handler }
    }
}

impl<'a, F> Write for Writer<'a, F>
where
    F: FnMut(&[u8]) -> io::Result<()>,
{
    fn write(&mut self, raw: &[u8]) -> io::Result<usize> {
        let Compressor {
            ref mut compress,
            ref mut buf,
        } = *self.compressor;

        let in1 = compress.total_in();
        compress.compress_vec(raw, buf, FlushCompress::None)?;
        let in2 = compress.total_in();

        let processed = (in2 - in1) as usize;

        if buf.len() == buf.capacity() {
            (self.handler)(&buf)?;
            buf.clear();
        }

        Ok(processed)
    }

    fn write_all(&mut self, mut buf: &[u8]) -> io::Result<()> {
        while buf.len() > 0 {
            match self.write(buf) {
                Ok(n) => buf = &buf[n..],
                Err(e) => {
                    if e.kind() != io::ErrorKind::Interrupted {
                        return Err(e);
                    }
                },
            }
        }

        Ok(())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl<'a, F> Writer<'a, F>
where
    F: FnMut(&[u8]) -> io::Result<()>,
{
    pub fn finish(&mut self) -> io::Result<()> {
        let Compressor {
            ref mut compress,
            ref mut buf,
        } = *self.compressor;

        compress.compress_vec(&[], buf, FlushCompress::Finish)?;
        loop {
            if buf.len() > 0 {
                (self.handler)(&buf)?;
                buf.clear();
            } else {
                break;
            }

            compress.compress_vec(&[], buf, FlushCompress::Finish)?;
        }

        Ok(())
    }
}