use std::io::{self, Read, Write}; pub trait Sink { fn put(&mut self, value: V) -> io::Result<()>; } pub trait Source { fn get(&mut self) -> io::Result; } impl Sink for T { fn put(&mut self, value: V) -> io::Result<()> { value.write(self) } } impl Source for T { fn get(&mut self) -> io::Result { V::read(self) } } pub trait Ser: Sized { fn write(&self, sink: &mut impl Write) -> io::Result<()>; fn read(source: &mut impl Read) -> io::Result; } impl Ser for (A, B) { fn write(&self, sink: &mut impl Write) -> io::Result<()> { self.0.write(sink)?; self.1.write(sink)?; Ok(()) } fn read(source: &mut impl Read) -> io::Result { Ok((A::read(source)?, B::read(source)?)) } } impl Ser for (A, B, C) { fn write(&self, sink: &mut impl Write) -> io::Result<()> { self.0.write(sink)?; self.1.write(sink)?; self.2.write(sink)?; Ok(()) } fn read(source: &mut impl Read) -> io::Result { Ok((A::read(source)?, B::read(source)?, C::read(source)?)) } } impl Ser for [A; N] { fn write(&self, sink: &mut impl Write) -> io::Result<()> { for e in self { e.write(sink)?; } Ok(()) } fn read(source: &mut impl Read) -> io::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) -> io::Result<()> { self.len().write(sink)?; for e in self { e.write(sink)?; } Ok(()) } fn read(source: &mut impl Read) -> io::Result { let mut v = vec![]; for _ in 0..usize::read(source)? { v.push(T::read(source)?) } Ok(v) } } impl Ser for u8 { fn write(&self, sink: &mut impl Write) -> io::Result<()> { sink.write_all(&[*self]) } fn read(source: &mut impl Read) -> io::Result { let mut buf = [0u8; 1]; source.read_exact(&mut buf)?; Ok(buf[0]) } } impl Ser for u16 { fn write(&self, sink: &mut impl Write) -> io::Result<()> { sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 2]>(self) }) } fn read(source: &mut impl Read) -> io::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) -> io::Result<()> { sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) } fn read(source: &mut impl Read) -> io::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) -> io::Result<()> { sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) } fn read(source: &mut impl Read) -> io::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) -> io::Result<()> { sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) } fn read(source: &mut impl Read) -> io::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) -> io::Result<()> { sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) } fn read(source: &mut impl Read) -> io::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) -> io::Result<()> { sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) } fn read(source: &mut impl Read) -> io::Result { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } #[cfg(test)] mod test { use super::Sink; use crate::ser::Source; use std::io::Cursor; #[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()); } }