use num_traits::AsPrimitive;
use std::io;
use std::io::{Read, Seek};
pub trait ElfioReadSeek: Read + Seek {}
impl ElfioReadSeek for std::fs::File {}
impl<T: Read + Seek> ElfioReadSeek for std::io::BufReader<T> {}
impl<T: Read + Seek + AsRef<[u8]>> ElfioReadSeek for std::io::Cursor<T> {}
pub trait Load {
fn load(&mut self, reader: &mut (dyn ElfioReadSeek)) -> io::Result<()>;
}
macro_rules! impl_load_for {
( $x:ty ) => {
impl Load for $x {
fn load(&mut self, reader: &mut (dyn ElfioReadSeek)) -> io::Result<()> {
let mut buffer = self.to_ne_bytes();
reader.read_exact(&mut buffer)?;
*self = <$x>::from_ne_bytes(buffer);
Ok(())
}
}
};
}
impl_load_for!(u8);
impl_load_for!(u16);
impl_load_for!(u32);
impl_load_for!(u64);
impl Load for &mut [u8; 16] {
fn load(&mut self, reader: &mut dyn ElfioReadSeek) -> io::Result<()> {
reader.read_exact(*self)?;
Ok(())
}
}
pub trait Convert<T>
where
T: AsPrimitive<u64>,
{
fn convert(&self, value: T) -> T;
}
#[derive(Debug, Copy, Clone)]
pub struct Converter {
pub is_needed: bool,
}
macro_rules! impl_convert_for {
( $x:ty ) => {
#[cfg(target_endian = "little")]
impl Convert<$x> for Converter {
fn convert(&self, value: $x) -> $x {
if self.is_needed {
value.to_be()
} else {
value
}
}
}
#[cfg(target_endian = "big")]
impl Convert<$x> for Converter {
fn convert(&self, value: $x) -> $x {
if self.is_needed {
value.to_le()
} else {
value
}
}
}
};
}
impl_convert_for!(u8);
impl_convert_for!(i8);
impl_convert_for!(u16);
impl_convert_for!(i16);
impl_convert_for!(u32);
impl_convert_for!(i32);
impl_convert_for!(u64);
impl_convert_for!(i64);
#[test]
fn test_conv() -> () {
let conv = Converter { is_needed: true };
let a = 0x12u8;
let a = conv.convert(a);
let b = 0x1234u16;
let b = conv.convert(b);
let c = 0x12345678u32;
let c = conv.convert(c);
let d = 0x1234567890ABCDEFu64;
let d = conv.convert(d);
assert_eq!(a, 0x12);
assert_eq!(b, 0x3412);
assert_eq!(c, 0x78563412);
assert_eq!(d, 0xEFCDAB9078563412);
}
#[test]
fn test_no_conv() -> () {
let conv = Converter { is_needed: false };
let a = 0x12u8;
let a = conv.convert(a);
let b = 0x1234u16;
let b = conv.convert(b);
let c = 0x12345678u32;
let c = conv.convert(c);
let d = 0x1234567890ABCDEFu64;
let d = conv.convert(d);
assert_eq!(a, 0x12);
assert_eq!(b, 0x1234);
assert_eq!(c, 0x12345678);
assert_eq!(d, 0x1234567890ABCDEF);
}