diff options
Diffstat (limited to 'shared/src/helper.rs')
-rw-r--r-- | shared/src/helper.rs | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/shared/src/helper.rs b/shared/src/helper.rs new file mode 100644 index 0000000..65918ad --- /dev/null +++ b/shared/src/helper.rs @@ -0,0 +1,132 @@ +/* + wearechat - generic multiplayer game with voip + Copyright (C) 2025 metamuffin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License only. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ +use crate::packets::{Data, Object, Resource}; +use anyhow::Result; +use std::{ + io::{Read, Write}, + marker::PhantomData, +}; + +pub trait ReadWrite: Sized { + fn write(&self, w: &mut dyn Write) -> Result<()>; + fn read(r: &mut dyn Read) -> Result<Self>; + + fn write_alloc(&self) -> Vec<u8> { + let mut buf = Vec::new(); + self.write(&mut buf).unwrap(); + buf + } +} + +impl ReadWrite for f32 { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&self.to_be_bytes())?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut buf = [0; 4]; + r.read_exact(&mut buf)?; + Ok(f32::from_be_bytes(buf)) + } +} +impl ReadWrite for u32 { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&self.to_be_bytes())?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut buf = [0; 4]; + r.read_exact(&mut buf)?; + Ok(u32::from_be_bytes(buf)) + } +} +impl ReadWrite for Vec<u8> { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&self)?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut buf = Vec::new(); + r.read_to_end(&mut buf)?; + Ok(buf) + } +} +impl ReadWrite for String { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&(self.len() as u32).to_be_bytes())?; + w.write_all(self.as_bytes())?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut size = [0; 4]; + r.read_exact(&mut size)?; + let size = u32::from_be_bytes(size); + let mut buf = vec![0; size as usize]; + r.read_exact(&mut buf)?; + Ok(String::from_utf8(buf)?) + } +} + +impl ReadWrite for Data { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&(self.0.len() as u32).to_be_bytes())?; + w.write_all(&self.0)?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut size = [0; 4]; + r.read_exact(&mut size)?; + let size = u32::from_be_bytes(size); + let mut buf = vec![0; size as usize]; + r.read_exact(&mut buf)?; + Ok(Self(buf)) + } +} +impl<T> ReadWrite for Resource<T> { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&self.0)?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut s = Self([0; 32], PhantomData); + r.read_exact(&mut s.0)?; + Ok(s) + } +} +impl ReadWrite for Object { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&self.0.to_be_bytes())?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut s = [0; 16]; + r.read_exact(&mut s)?; + Ok(Object(u128::from_be_bytes(s))) + } +} +impl<T: ReadWrite, const N: usize> ReadWrite for [T; N] { + fn write(&self, w: &mut dyn Write) -> Result<()> { + for e in self { + e.write(w)?; + } + Ok(()) + } + + fn read(r: &mut dyn Read) -> Result<Self> { + [(); N].try_map(|()| T::read(r)) + } +} |