use super::Primitive; use std::io::{self, Read, Write}; macro_rules! marshal_number { ($type:ident, $byte:expr) => { impl Primitive for $type { fn write(&self, write: &mut W) -> io::Result<()> { write.write(&self.to_le_bytes())?; Ok(()) } fn read(read: &mut R) -> io::Result { let mut bytes = [0u8; $byte]; read.read_exact(&mut bytes)?; Ok(Self::from_le_bytes(bytes)) } } }; } marshal_number!(u8, 1); marshal_number!(u16, 2); marshal_number!(i16, 2); marshal_number!(u32, 4); marshal_number!(i64, 8); marshal_number!(f64, 8); impl Primitive for bool { fn write(&self, write: &mut W) -> io::Result<()> { if *self { write.write(&[1u8; 1])?; } else { write.write(&[0u8; 1])?; } Ok(()) } fn read(read: &mut R) -> io::Result { let mut bytes = [0u8; 1]; read.read_exact(&mut bytes)?; if bytes[0] == 1 { Ok(true) } else { Ok(false) } } } impl Primitive for String { fn write(&self, write: &mut W) -> io::Result<()> { let bytes = self.as_bytes(); let len = bytes.len(); write.write(&(len as u32).to_le_bytes())?; write.write(&bytes)?; Ok(()) } fn read(read: &mut R) -> io::Result { let len = usize::read(read)?; let mut bytes = vec![0u8; len]; read.read_exact(&mut bytes)?; Ok(String::from_utf8_lossy(bytes.as_slice()).to_string()) } } impl Primitive for usize { fn write(&self, write: &mut W) -> io::Result<()> { (*self as u32).write(write) } fn read(read: &mut R) -> io::Result { Ok(u32::read(read)? as usize) } } pub struct VarInt(pub usize); impl Primitive for VarInt { fn write(&self, write: &mut W) -> io::Result<()> { let mut data = self.0; loop { let mut byte = (data & 0x7F) as u8; data >>= 7; if data != 0 { byte += 0x80; } write.write(&[byte; 1])?; if data == 0 { return Ok(()) } } } fn read(read: &mut R) -> io::Result { let mut buf = [0]; let mut result = 0usize; for count in 0..8 { if read.read(&mut buf)? != 1 { return Ok(Self(0)) } let byte = buf[0]; result |= ((byte & 0x7F) as usize) << (7 * count); if byte & 0x80 == 0 { return Ok(Self(result)) } } Ok(Self(0)) } }