matrix/matrix-lang/src/binary/mod.rs
2024-02-29 17:04:28 -05:00

154 lines
3.8 KiB
Rust

use crate::prelude::*;
use std::io::{self, Read, Write};
mod serialize;
mod deserialize;
mod prim;
pub struct Program {
version: u8,
fun: Rc<Function>
}
const PROGRAM_HEADER: [u8; 5] = [0x00, 0x4d, 0x41, 0x54, 0x0a];
impl Program {
pub fn load(body: &str) -> Result<Option<Rc<Function>>> {
let mut bytes = body.as_bytes();
if bytes.len() < 6 {
return Ok(None)
}
let header = &bytes[0..5];
if header != &PROGRAM_HEADER {
return Ok(None)
}
let mut s = ProgramDeserializer::from(&mut bytes);
let program = <Self>::deserialize(&mut s)?;
s.finish()?;
Ok(Some(program.fun.clone()))
}
pub fn save<W: Write>(fun: Rc<Function>, w: &mut W) -> Result<()> {
let mut s = ProgramSerializer::from(w);
let p = Program {
version: 0,
fun
};
s.serialize(&p)?;
s.finish()?;
Ok(())
}
}
pub trait Primitive : Sized {
fn write<W: Write>(&self, w: &mut W) -> io::Result<()>;
fn read<R: Read>(r: &mut R) -> io::Result<Self>;
}
pub trait Serialize : Sized {
fn serialize<S: Serializer>(&self, s: &mut S) -> Result<()>;
}
pub trait Serializer : Sized {
fn serialize<S: Serialize>(&mut self, val: &S) -> Result<()> {
val.serialize(self)
}
fn write<P: Primitive>(&mut self, val: P) -> Result<()>;
}
pub trait Deserialize : Sized {
fn deserialize<S: Deserializer>(s: &mut S) -> Result<Self>;
}
pub trait Deserializer : Sized {
fn deserialize<D: Deserialize>(&mut self) -> Result<D> {
D::deserialize(self)
}
fn read<P: Primitive>(&mut self) -> Result<P>;
}
macro_rules! error {
($($arg:tt)*) => {
exception!(BINARY_EXCEPTION, $($arg)*)
};
}
pub struct ProgramSerializer<'w, W: Write> {
writer: &'w mut W,
checksum: u64,
}
impl<'w, W: Write> ProgramSerializer<'w, W> {
fn finish(self) -> Result<()> {
let bytes = self.checksum.to_le_bytes();
self.writer.write(&bytes).map_err(|e| error!("{e}"))?;
Ok(())
}
}
impl<'w, W: Write> Serializer for ProgramSerializer<'w, W> {
fn write<P: Primitive>(&mut self, val: P) -> Result<()> {
val.write(self).map_err(|e| error!("{e}"))
}
}
impl<'w, W: Write> Write for ProgramSerializer<'w, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
for b in buf {
self.checksum %= 0xf1e3beef;
self.checksum += *b as u64;
}
self.writer.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.writer.flush()
}
}
impl<'w, W: Write> From<&'w mut W> for ProgramSerializer<'w, W> {
fn from(writer: &'w mut W) -> Self {
Self { writer, checksum: 0xfe }
}
}
pub struct ProgramDeserializer<'r, R: Read> {
reader: &'r mut R,
checksum: u64,
}
impl<'r, R: Read> ProgramDeserializer<'r, R> {
fn finish(self) -> Result<()> {
let mut bytes = [0u8; 8];
self.reader.read_exact(&mut bytes).map_err(|e| error!("{e}"))?;
let checksum = u64::from_le_bytes(bytes);
if self.checksum != checksum {
return Err(error!("checksum doesnt match"))
}
Ok(())
}
}
impl<'r, R: Read> Deserializer for ProgramDeserializer<'r, R> {
fn read<P: Primitive>(&mut self) -> Result<P> {
P::read(self).map_err(|e| error!("{e}"))
}
}
impl<'r, R: Read> Read for ProgramDeserializer<'r, R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let c = self.reader.read(buf)?;
for i in 0..c {
let b = buf[i];
self.checksum %= 0xf1e3beef;
self.checksum += b as u64;
}
Ok(c)
}
}
impl<'r, R: Read> From<&'r mut R> for ProgramDeserializer<'r, R> {
fn from(reader: &'r mut R) -> Self {
Self { reader, checksum: 0xfe }
}
}