organicomplex 0.7.0

Interactive complex-valued cellular automaton on 2D and 3D grids in search of that stuff - emergence, open-endedness, organicity etc.
use std::io::{
    Read,
    Write
};

pub trait WriteBin<T> {
    fn write_bin(&mut self, x: T) -> Result<(), String>;
}

pub trait ReadBin<T> {
    fn read_bin(&mut self) -> Result<T, String>;
}

impl<W: Write> WriteBin<i16> for W {
    fn write_bin(&mut self, x: i16) -> Result<(), String> {
        self.write_all(& x.to_le_bytes()).map_err(|e| e.to_string())
    }
}

impl<R: Read> ReadBin<i16> for R {
    fn read_bin(&mut self) -> Result<i16, String> {
        let mut buf = [0u8; (i16::BITS >> 3) as usize];
        self.read_exact(&mut buf).map_err(|e| e.to_string())?;
        Ok(i16::from_le_bytes(buf))
    }
}

impl<W: Write> WriteBin<i32> for W {
    fn write_bin(&mut self, x: i32) -> Result<(), String> {
        self.write_all(& x.to_le_bytes()).map_err(|e| e.to_string())
    }
}

impl<R: Read> ReadBin<i32> for R {
    fn read_bin(&mut self) -> Result<i32, String> {
        let mut buf = [0u8; (i32::BITS >> 3) as usize];
        self.read_exact(&mut buf).map_err(|e| e.to_string())?;
        Ok(i32::from_le_bytes(buf))
    }
}

impl<W: Write> WriteBin<i64> for W {
    fn write_bin(&mut self, x: i64) -> Result<(), String> {
        self.write_all(& x.to_le_bytes()).map_err(|e| e.to_string())
    }
}

impl<R: Read> ReadBin<i64> for R {
    fn read_bin(&mut self) -> Result<i64, String> {
        let mut buf = [0u8; (i64::BITS >> 3) as usize];
        self.read_exact(&mut buf).map_err(|e| e.to_string())?;
        Ok(i64::from_le_bytes(buf))
    }
}

impl<W: Write> WriteBin<i128> for W {
    fn write_bin(&mut self, x: i128) -> Result<(), String> {
        self.write_all(& x.to_le_bytes()).map_err(|e| e.to_string())
    }
}

impl<R: Read> ReadBin<i128> for R {
    fn read_bin(&mut self) -> Result<i128, String> {
        let mut buf = [0u8; (i128::BITS >> 3) as usize];
        self.read_exact(&mut buf).map_err(|e| e.to_string())?;
        Ok(i128::from_le_bytes(buf))
    }
}

impl<W: Write> WriteBin<bool> for W {
    fn write_bin(&mut self, x: bool) -> Result<(), String> {
        self.write_all(& (if x {1u8} else {0u8}).to_le_bytes()).map_err(|e| e.to_string())
    }
}

impl<R: Read> ReadBin<bool> for R {
    fn read_bin(&mut self) -> Result<bool, String> {
        let mut buf8 = [0u8; 1];
        self.read_exact(&mut buf8).map_err(|e| e.to_string())?;
        Ok(u8::from_le_bytes(buf8) != 0)
    }
}

impl<W: Write> WriteBin<usize> for W { // LEB128 encoding ?
    fn write_bin(&mut self, mut x: usize) -> Result<(), String> {
        let mut part: u8;
        loop {
            part = (x & 0x7F) as u8;
            if x >= 0x80 {
                part |= 0x80; // Bit 7 is set iff more parts follow
            }
            self.write_all(&[part]).map_err(|e| e.to_string())?;
            x >>= 7;
            if x == 0 {
                break;
            }
        }
    Ok(())
    }
}

impl<R: Read> ReadBin<usize> for R { // LEB128 encoding ?
    fn read_bin(&mut self) -> Result<usize, String> {
        let mut shift: u32 = 0;
        let mut x: usize = 0;
        let mut buf8 = [0u8; 1];
        loop {
            self.read_exact(&mut buf8).map_err(|e| e.to_string())?;
            x += ((buf8[0] & 0x7F) as usize) << shift;
            if (buf8[0] & 0x80) == 0 { // Bit 7 is not set iff no more parts follow
                break;
            }
            shift += 7;
        }
        Ok(x)
    }
}

impl<W: Write> WriteBin<f64> for W {
    fn write_bin(&mut self, x: f64) -> Result<(), String> {
        self.write_all(& x.to_le_bytes()).map_err(|e| e.to_string())
    }
}

impl<R: Read> ReadBin<f64> for R {
    fn read_bin(&mut self) -> Result<f64, String> {
        let mut buf64 = [0u8; 8];
        self.read_exact(&mut buf64).map_err(|e| e.to_string())?;
        Ok(f64::from_le_bytes(buf64))
    }
}