use core::str::Utf8Error; use byteorder::{ByteOrder, NativeEndian}; use alloc::vec; use alloc::string::String; use core_io::{Read, Write, Error as IoError}; #[allow(dead_code)] #[derive(Debug, Clone, PartialEq)] pub enum ReadStringError { Utf8(Utf8Error), Other(T) } pub trait ProtoRead { type ReadError; fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError>; #[inline] fn read_u8(&mut self) -> Result { let mut bytes = [0; 1]; self.read_exact(&mut bytes)?; Ok(bytes[0]) } #[inline] fn read_u16(&mut self) -> Result { let mut bytes = [0; 2]; self.read_exact(&mut bytes)?; Ok(NativeEndian::read_u16(&bytes)) } #[inline] fn read_u32(&mut self) -> Result { let mut bytes = [0; 4]; self.read_exact(&mut bytes)?; Ok(NativeEndian::read_u32(&bytes)) } #[inline] fn read_u64(&mut self) -> Result { let mut bytes = [0; 8]; self.read_exact(&mut bytes)?; Ok(NativeEndian::read_u64(&bytes)) } #[inline] fn read_bool(&mut self) -> Result { Ok(self.read_u8()? != 0) } #[inline] fn read_bytes(&mut self) -> Result<::alloc::vec::Vec, Self::ReadError> { let length = self.read_u32()?; let mut value = vec![0; length as usize]; self.read_exact(&mut value)?; Ok(value) } #[inline] fn read_string(&mut self) -> Result<::alloc::string::String, ReadStringError> { let bytes = self.read_bytes().map_err(ReadStringError::Other)?; String::from_utf8(bytes).map_err(|err| ReadStringError::Utf8(err.utf8_error())) } } pub trait ProtoWrite { type WriteError; fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError>; #[inline] fn write_u8(&mut self, value: u8) -> Result<(), Self::WriteError> { let bytes = [value; 1]; self.write_all(&bytes) } #[inline] fn write_i8(&mut self, value: i8) -> Result<(), Self::WriteError> { let bytes = [value as u8; 1]; self.write_all(&bytes) } #[inline] fn write_u16(&mut self, value: u16) -> Result<(), Self::WriteError> { let mut bytes = [0; 2]; NativeEndian::write_u16(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_i16(&mut self, value: i16) -> Result<(), Self::WriteError> { let mut bytes = [0; 2]; NativeEndian::write_i16(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_u32(&mut self, value: u32) -> Result<(), Self::WriteError> { let mut bytes = [0; 4]; NativeEndian::write_u32(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_i32(&mut self, value: i32) -> Result<(), Self::WriteError> { let mut bytes = [0; 4]; NativeEndian::write_i32(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_u64(&mut self, value: u64) -> Result<(), Self::WriteError> { let mut bytes = [0; 8]; NativeEndian::write_u64(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_i64(&mut self, value: i64) -> Result<(), Self::WriteError> { let mut bytes = [0; 8]; NativeEndian::write_i64(&mut bytes, value); self.write_all(&bytes) } #[inline] fn write_bool(&mut self, value: bool) -> Result<(), Self::WriteError> { self.write_u8(value as u8) } #[inline] fn write_bytes(&mut self, value: &[u8]) -> Result<(), Self::WriteError> { self.write_u32(value.len() as u32)?; self.write_all(value) } #[inline] fn write_string(&mut self, value: &str) -> Result<(), Self::WriteError> { self.write_bytes(value.as_bytes()) } } impl ProtoRead for T where T: Read + ?Sized { type ReadError = IoError; fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError> { T::read_exact(self, buf) } } impl ProtoWrite for T where T: Write + ?Sized { type WriteError = IoError; fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError> { T::write_all(self, buf) } }