use anyhow::{Result, bail}; use glam::Vec3A; use std::{ fmt::{Debug, Display}, io::{Read, Write}, }; #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct Resource(pub [u8; 32]); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Object(pub u128); #[derive(Clone)] pub struct Data(pub Vec); #[derive(Debug, Clone)] pub enum Packet { Connect(u128), Disconnect, RequestResource(Resource), RespondResource(Data), Add(Object, Resource), Remove(Object), Position(Object, Vec3A, Vec3A), Pose(Object, Vec), Parent(Object, Object), Sound(Object, Data), } pub trait ReadWrite: Sized { fn write(&self, w: &mut dyn Write) -> Result<()>; fn read(r: &mut dyn Read) -> Result; fn write_alloc(&self) -> Vec { let mut buf = Vec::new(); self.write(&mut buf).unwrap(); buf } } impl Object { pub fn new() -> Self { Self(rand::random()) } } impl Packet { fn serialize_inner(&self, w: &mut impl Write) -> Result<()> { match self { Packet::Connect(id) => { w.write_all(&[0x00])?; w.write_all(&id.to_be_bytes())?; } Packet::Disconnect => { w.write_all(&[0xff])?; } Packet::RequestResource(resource) => { w.write_all(&[0x01])?; w.write_all(&resource.0)?; } Packet::RespondResource(data) => { w.write_all(&[0x02])?; data.write(w)?; } Packet::Add(object, resource) => { w.write_all(&[0x03])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&resource.0)?; } Packet::Remove(object) => { w.write_all(&[0x04])?; w.write_all(&object.0.to_be_bytes())?; } Packet::Position(object, pos, rot) => { w.write_all(&[0x05])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&pos.x.to_be_bytes())?; w.write_all(&pos.y.to_be_bytes())?; w.write_all(&pos.z.to_be_bytes())?; w.write_all(&rot.x.to_be_bytes())?; w.write_all(&rot.y.to_be_bytes())?; w.write_all(&rot.z.to_be_bytes())?; } Packet::Pose(object, vec) => { w.write_all(&[0x06])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&(vec.len() as u16).to_be_bytes())?; } Packet::Parent(parent, child) => { w.write_all(&[0x07])?; w.write_all(&parent.0.to_be_bytes())?; w.write_all(&child.0.to_be_bytes())?; } Packet::Sound(object, data) => { w.write_all(&[0x08])?; w.write_all(&object.0.to_be_bytes())?; data.write(w)?; } } Ok(()) } } impl ReadWrite for Packet { fn write(&self, w: &mut dyn Write) -> Result<()> { let mut buf = Vec::new(); self.serialize_inner(&mut buf)?; w.write_all(&(buf.len() as u32).to_be_bytes())?; w.write_all(&buf)?; Ok(()) } fn read(r: &mut dyn Read) -> Result { let packet_len = u32::read(r)?; Ok(match u8::read(r)? { 0x00 => Packet::Connect(read_u128(r)?), 0x01 => Packet::RequestResource(Resource::read(r)?), 0x02 => Packet::RespondResource(Data::read(r)?), 0x03 => Packet::Add(Object(read_u128(r)?), Resource::read(r)?), 0x04 => Packet::Remove(Object(read_u128(r)?)), 0x05 => Packet::Position( Object(read_u128(r)?), Vec3A::new(f32::read(r)?, f32::read(r)?, f32::read(r)?), Vec3A::new(f32::read(r)?, f32::read(r)?, f32::read(r)?), ), 0x06 => Packet::Pose(Object(read_u128(r)?), read_params(r)?), 0x07 => Packet::Parent(Object(read_u128(r)?), Object(read_u128(r)?)), 0x08 => Packet::Sound(Object(read_u128(r)?), Data::read(r)?), _ => { for _ in 0..packet_len.max(1) - 1 { r.read_exact(&mut [0])?; } bail!("unknown packet tag"); } }) } } fn read_u128(r: &mut dyn Read) -> Result { let mut buf = [0; 16]; r.read_exact(&mut buf)?; Ok(u128::from_be_bytes(buf)) } impl ReadWrite for Resource { fn write(&self, w: &mut dyn Write) -> Result<()> { w.write_all(&self.0)?; Ok(()) } fn read(r: &mut dyn Read) -> Result { let mut s = Self([0; 32]); r.read_exact(&mut s.0)?; Ok(s) } } 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 { 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(Data(buf)) } } fn read_params(r: &mut dyn Read) -> Result> { let mut size = [0; 2]; r.read_exact(&mut size)?; let size = u16::from_be_bytes(size); let mut v = Vec::with_capacity(size as usize); for _ in 0..size { v.push(f32::read(r)?); } Ok(v) } 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 { 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 { let mut buf = [0; 4]; r.read_exact(&mut buf)?; Ok(u32::from_be_bytes(buf)) } } impl Display for Resource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "Res{{{:08x}{:08x}{:08x}{:08x}}}", u64::from_be_bytes(self.0[0..8].try_into().unwrap()), u64::from_be_bytes(self.0[8..16].try_into().unwrap()), u64::from_be_bytes(self.0[16..24].try_into().unwrap()), u64::from_be_bytes(self.0[24..32].try_into().unwrap()), ) } } impl Debug for Resource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self) } } impl 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 { [(); N].try_map(|()| T::read(r)) } } impl Debug for Data { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Data").finish_non_exhaustive() } }