use byteorder::{ReadBytesExt, LE}; pub trait ReadExt { fn read_bool(&mut self) -> Result; fn read_guid(&mut self) -> Result<[u8; 20], super::Error>; fn read_array( &mut self, func: impl FnMut(&mut Self) -> Result, ) -> Result, super::Error>; fn read_string(&mut self) -> Result; fn read_len(&mut self, len: usize) -> Result, super::Error>; } impl ReadExt for R { fn read_bool(&mut self) -> Result { match self.read_u8()? { 1 => Ok(true), 0 => Ok(false), err => Err(super::Error::Bool(err)), } } fn read_guid(&mut self) -> Result<[u8; 20], super::Error> { let mut guid = [0; 20]; self.read_exact(&mut guid)?; Ok(guid) } fn read_array( &mut self, mut func: impl FnMut(&mut Self) -> Result, ) -> Result, super::Error> { let mut buf = Vec::with_capacity(self.read_u32::()? as usize); for _ in 0..buf.capacity() { buf.push(func(self)?); } Ok(buf) } fn read_string(&mut self) -> Result { let mut buf = match self.read_i32::()? { size if size.is_negative() => { let mut buf = Vec::with_capacity(-size as usize); for _ in 0..buf.capacity() { buf.push(self.read_u16::()?); } String::from_utf16(&buf)? } size => String::from_utf8(self.read_len(size as usize)?)?, }; // remove the null byte buf.pop(); Ok(buf) } fn read_len(&mut self, len: usize) -> Result, super::Error> { let mut buf = vec![0; len]; self.read_exact(&mut buf)?; Ok(buf) } }