war 0.2.0

A viewer/editor for Darksiders saves, worlds, and scripts
Documentation
use crate::utils::{parsing::derailed, seek_ext::SeekExt};
use byteordered::{ByteOrdered, Endianness};
use flate2::{write::ZlibEncoder, Compression};
use std::{
    convert::TryInto,
    io::{self, Seek, SeekFrom, Write},
};

pub struct CompressedOutputStream<'w, W: Write + Seek> {
    inner: ByteOrdered<ZlibEncoder<&'w mut ByteOrdered<W, Endianness>>, Endianness>,
    write_size_here: u64,
}

impl<'w, W: Write + Seek> CompressedOutputStream<'w, W> {
    pub fn new(out: &'w mut ByteOrdered<W, Endianness>) -> io::Result<Self> {
        let write_size_here = out.stream_position_ext()?;
        out.write_i32(0)?;

        let zstream = ZlibEncoder::new(out, Compression::best());
        let inner = ByteOrdered::new(zstream, Endianness::Little);
        Ok(Self {
            inner,
            write_size_here,
        })
    }

    pub fn inner_mut(&mut self) -> &mut ByteOrdered<impl Write + 'w, Endianness> {
        &mut self.inner
    }

    pub fn flush(self) -> io::Result<()> {
        let mut zstream = self.inner.into_inner();
        zstream.flush()?;
        let uncompressed_bytes_written = zstream.total_in();

        let output = zstream.finish()?;

        let end_pos = output.stream_position_ext()?;
        output.seek(SeekFrom::Start(self.write_size_here))?;
        output.write_i32(
            uncompressed_bytes_written
                .try_into()
                .map_err(|_| derailed())?,
        )?;
        output.seek(SeekFrom::Start(end_pos))?;
        Ok(())
    }
}