use log::trace; use std::io::{Read, Result, Seek}; #[derive(Debug, Clone, Copy, PartialEq)] pub enum Endianness { Big, Little, } pub trait ReadExt { fn read_u8(&mut self) -> Result; fn read_i8(&mut self) -> Result; fn read_u16(&mut self, e: Endianness) -> Result; fn read_u16_le(&mut self) -> Result; fn read_u16_be(&mut self) -> Result; fn read_i16(&mut self, e: Endianness) -> Result; fn read_i16_be(&mut self) -> Result; fn read_i16_le(&mut self) -> Result; fn read_i32(&mut self, e: Endianness) -> Result; fn read_i32_be(&mut self) -> Result; fn read_i32_le(&mut self) -> Result; fn read_u32(&mut self, e: Endianness) -> Result; fn read_u32_be(&mut self) -> Result; fn read_u32_le(&mut self) -> Result; fn read_u64(&mut self, e: Endianness) -> Result; fn read_u64_be(&mut self) -> Result; fn read_u64_le(&mut self) -> Result; fn read_i64(&mut self, e: Endianness) -> Result; fn read_i64_be(&mut self) -> Result; fn read_i64_le(&mut self) -> Result; fn read_u128_be(&mut self) -> Result; fn read_f32(&mut self, e: Endianness) -> Result; fn read_f32_be(&mut self) -> Result; fn read_f32_le(&mut self) -> Result; fn read_f64(&mut self, e: Endianness) -> Result; fn read_f64_be(&mut self) -> Result; fn read_f64_le(&mut self) -> Result; fn read_cstr(&mut self) -> Result; fn discard(&mut self, n: usize) -> Result<()>; } impl ReadExt for T { fn read_u8(&mut self) -> Result { let mut buf = [0; 1]; self.read_exact(&mut buf)?; Ok(buf[0]) } fn read_i8(&mut self) -> Result { Ok(self.read_u8()? as i8) } fn read_u16(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_u16_be(), Endianness::Little => self.read_u16_le(), } } fn read_u16_be(&mut self) -> Result { let mut buf = [0; 2]; self.read_exact(&mut buf)?; Ok(u16::from_be_bytes(buf)) } fn read_u16_le(&mut self) -> Result { let mut buf = [0; 2]; self.read_exact(&mut buf)?; Ok(u16::from_le_bytes(buf)) } fn read_i16(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_i16_be(), Endianness::Little => self.read_i16_le(), } } fn read_i16_be(&mut self) -> Result { let mut buf = [0; 2]; self.read_exact(&mut buf)?; Ok(i16::from_be_bytes(buf)) } fn read_i16_le(&mut self) -> Result { let mut buf = [0; 2]; self.read_exact(&mut buf)?; Ok(i16::from_le_bytes(buf)) } fn read_i32(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_i32_be(), Endianness::Little => self.read_i32_le(), } } fn read_i32_be(&mut self) -> Result { let mut buf = [0; 4]; self.read_exact(&mut buf)?; Ok(i32::from_be_bytes(buf)) } fn read_i32_le(&mut self) -> Result { let mut buf = [0; 4]; self.read_exact(&mut buf)?; Ok(i32::from_le_bytes(buf)) } fn read_u32(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_u32_be(), Endianness::Little => self.read_u32_le(), } } fn read_u32_be(&mut self) -> Result { let mut buf = [0; 4]; self.read_exact(&mut buf)?; Ok(u32::from_be_bytes(buf)) } fn read_u32_le(&mut self) -> Result { let mut buf = [0; 4]; self.read_exact(&mut buf)?; Ok(u32::from_le_bytes(buf)) } fn read_u64(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_u64_be(), Endianness::Little => self.read_u64_le(), } } fn read_u64_be(&mut self) -> Result { let mut buf = [0; 8]; self.read_exact(&mut buf)?; Ok(u64::from_be_bytes(buf)) } fn read_u64_le(&mut self) -> Result { let mut buf = [0; 8]; self.read_exact(&mut buf)?; Ok(u64::from_le_bytes(buf)) } fn read_i64(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_i64_be(), Endianness::Little => self.read_i64_le(), } } fn read_i64_be(&mut self) -> Result { let mut buf = [0; 8]; self.read_exact(&mut buf)?; Ok(i64::from_be_bytes(buf)) } fn read_i64_le(&mut self) -> Result { let mut buf = [0; 8]; self.read_exact(&mut buf)?; Ok(i64::from_le_bytes(buf)) } fn read_f32(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_f32_be(), Endianness::Little => self.read_f32_le(), } } fn read_f32_be(&mut self) -> Result { let mut buf = [0; 4]; self.read_exact(&mut buf)?; Ok(f32::from_be_bytes(buf)) } fn read_f32_le(&mut self) -> Result { let mut buf = [0; 4]; self.read_exact(&mut buf)?; Ok(f32::from_le_bytes(buf)) } fn read_f64(&mut self, e: Endianness) -> Result { match e { Endianness::Big => self.read_f64_be(), Endianness::Little => self.read_f64_le(), } } fn read_f64_be(&mut self) -> Result { let mut buf = [0; 8]; self.read_exact(&mut buf)?; Ok(f64::from_be_bytes(buf)) } fn read_f64_le(&mut self) -> Result { let mut buf = [0; 8]; self.read_exact(&mut buf)?; Ok(f64::from_le_bytes(buf)) } fn read_u128_be(&mut self) -> Result { let mut buf = [0; 16]; self.read_exact(&mut buf)?; Ok(u128::from_be_bytes(buf)) } fn read_cstr(&mut self) -> Result { let mut buf = [0; 1]; let mut s = Vec::new(); loop { self.read_exact(&mut buf)?; if buf[0] == 0 { break; } s.push(buf[0]); } Ok(String::from_utf8_lossy(&s).to_string()) } fn discard(&mut self, n: usize) -> Result<()> { for _ in 0..n { self.read_u8()?; } Ok(()) } } pub trait AlignExt { fn align(&mut self, size: u64) -> Result<()>; } impl AlignExt for T { fn align(&mut self, size: u64) -> Result<()> { let off = self.stream_position()? % size; if off != 0 { trace!("align to {size} (+{})", size - off); self.seek_relative((size - off) as i64)?; } Ok(()) } }