use anyhow::Context; use std::io::{Read, Write}; use crate::helpers::{matrix::Mat2, vector::Vec2}; pub trait Sink { fn put(&mut self, value: V) -> anyhow::Result<()>; } pub trait Source { fn get(&mut self) -> anyhow::Result; } impl Sink for T { fn put(&mut self, value: V) -> anyhow::Result<()> { value.write(self) } } impl Source for T { fn get(&mut self) -> anyhow::Result { V::read(self) } } pub trait Ser: Sized { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()>; fn read(source: &mut impl Read) -> anyhow::Result; } impl Ser for (A, B) { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { self.0.write(sink).context("first tuple field")?; self.1.write(sink).context("second tuple field")?; Ok(()) } fn read(source: &mut impl Read) -> anyhow::Result { Ok((A::read(source)?, B::read(source)?)) } } impl Ser for (A, B, C) { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { self.0.write(sink).context("first tuple field")?; self.1.write(sink).context("second tuple field")?; self.2.write(sink).context("third tuple field")?; Ok(()) } fn read(source: &mut impl Read) -> anyhow::Result { Ok((A::read(source)?, B::read(source)?, C::read(source)?)) } } impl Ser for (A, B, C, D) { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { self.0.write(sink).context("first tuple field")?; self.1.write(sink).context("second tuple field")?; self.2.write(sink).context("third tuple field")?; self.3.write(sink).context("fourth tuple field")?; Ok(()) } fn read(source: &mut impl Read) -> anyhow::Result { Ok(( A::read(source)?, B::read(source)?, C::read(source)?, D::read(source)?, )) } } impl Ser for [A; N] { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { for e in self { e.write(sink).context("some array")?; } Ok(()) } fn read(source: &mut impl Read) -> anyhow::Result { let mut k: [A; N] = unsafe { std::mem::zeroed() }; for i in 0..N { k[i] = A::read(source)?; } Ok(k) } } impl Ser for Vec { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { self.len().write(sink)?; for e in self { e.write(sink).context("some vec")?; } Ok(()) } fn read(source: &mut impl Read) -> anyhow::Result { let mut v = vec![]; for _ in 0..usize::read(source)? { v.push(T::read(source)?) } Ok(v) } } pub trait ConstSizeSerExt: Sized { fn write_const_size(&self, sink: &mut impl Write, size: usize) -> anyhow::Result<()>; fn read_const_size(source: &mut impl Read, size: usize) -> anyhow::Result; } impl ConstSizeSerExt for Vec { fn write_const_size(&self, sink: &mut impl Write, size: usize) -> anyhow::Result<()> { assert_eq!(self.len(), size); for e in self { e.write(sink).context("some const-size vec")?; } Ok(()) } fn read_const_size(source: &mut impl Read, size: usize) -> anyhow::Result { let mut v = vec![]; for _ in 0..size { v.push(T::read(source)?) } Ok(v) } } impl Ser for u8 { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink.write_all(&[*self]).context("write u8")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 1]; source.read_exact(&mut buf)?; Ok(buf[0]) } } impl Ser for i8 { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 1]>(self) }) .context("write i8")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 1]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for u16 { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 2]>(self) }) .context("write 16")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 2]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for u32 { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) .context("write u32")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 4]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for u64 { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) .context("write u64")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for usize { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) .context("write usize")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for isize { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) .context("write isize")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for f32 { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) .context("write f32")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 4]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for f64 { fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { Ok(sink .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) .context("write f64")?) } fn read(source: &mut impl Read) -> anyhow::Result { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for Vec2 { fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { sink.put((self.x, self.y)) } fn read(source: &mut impl std::io::Read) -> anyhow::Result { let (x, y) = source.get()?; Ok(Vec2 { x, y }) } } impl Ser for Mat2 { fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { sink.put((self.a, self.b, self.c, self.d)) } fn read(source: &mut impl std::io::Read) -> anyhow::Result { let (a, b, c, d) = source.get()?; Ok(Mat2 { a, b, c, d }) } } pub struct Small(pub T); impl Ser for Small> { fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { sink.put((self.0.x as i8, self.0.y as i8)) } fn read(source: &mut impl std::io::Read) -> anyhow::Result { let (x, y): (i8, i8) = source.get()?; Ok(Small(Vec2 { x: x as isize, y: y as isize, })) } } pub fn map_scalar8(v: i8) -> f32 { match v { 0 => 0.0, x if x > 0 => 2f32.powf((x as f32).abs() / 2.0 - 2.0), x => -2f32.powf((-x as f32).abs() / 2.0 - 2.0), } } // const SCALAR8: [f32; 256] = gen_scalar8_lookup(); // const fn gen_scalar8_lookup() -> [f32; 256] { // let mut a = [0.0; 256]; // let mut i = 0usize; // while i < 256 { // a[i as usize] = if i == 0 { // 0.0 // } else { // let x = i as i8 as f32; // x.signum() * 2f32.powf(x.abs() / 2.0 - 2.0) // }; // i += 1; // } // a // } #[cfg(test)] mod test { use super::{Ser, Sink}; use crate::format::header::Header; use crate::{format::ser::Source, helpers::vector::Vec2}; use std::fmt::Debug; use std::io::Cursor; fn test_ser(value: T) { let mut buf = vec![]; Cursor::new(&mut buf).put(value.clone()).unwrap(); assert_eq!(value, Cursor::new(&mut buf).get().unwrap()); } #[test] fn simple() { let mut buf = vec![]; Cursor::new(&mut buf).put(10usize).unwrap(); assert_eq!(10usize, Cursor::new(&mut buf).get().unwrap()); } #[test] fn tuple() { let mut buf = vec![]; Cursor::new(&mut buf).put((10usize, 5u8, 3u16)).unwrap(); assert_eq!((10usize, 5u8, 3u16), Cursor::new(&mut buf).get().unwrap()); } #[test] fn header() { test_ser(Header { frame_count: 123, resolution: Vec2 { x: 13, y: 37 }, }); } #[test] fn vec() { test_ser(vec![1u16, 2, 3, 4]); } #[test] fn array() { test_ser([1u16, 2, 3, 4]); } }