diff options
| author | iximeow <me@iximeow.net> | 2021-07-03 19:36:15 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2021-07-03 19:36:15 -0700 | 
| commit | 041ef2605f5de35e268bd0f82d9a6240a9a58e61 (patch) | |
| tree | efb4e4d42780b46df931e55f6df7bfd0450c5c79 | |
| parent | 3863d7023e1c7ae71f989e172200898d8a658f71 (diff) | |
add a Reader type that can read architecture-defined words
this is useful for instruction sets like arm where instructions are
guaranteed to be 4 bytes, as well as instruction sets where an
instruction word is not a multiple of u8 bytes.
| -rw-r--r-- | src/lib.rs | 13 | ||||
| -rw-r--r-- | src/reader.rs | 261 | 
2 files changed, 269 insertions, 5 deletions
| @@ -31,6 +31,8 @@ pub use color::{Colorize, NoColors, YaxColors};  pub use color::ColorSettings;  pub mod display; +mod reader; +pub use reader::{Reader, ReadError, U8Reader}; //, U16le, U16be, U32le, U32be, U64le, U64be};  pub trait DecodeError {      fn data_exhausted(&self) -> bool; @@ -61,12 +63,13 @@ impl DecodeError for StandardDecodeError {      fn bad_operand(&self) -> bool { *self == StandardDecodeError::InvalidOperand }  } -    fn decode<T: Reader<A::Word>>(&self, bytes: &mut T) -> Result<A::Instruction, Self::Error> { +pub trait Decoder<A: Arch + ?Sized> { +    fn decode<T: Reader<A::Address, A::Word>>(&self, words: &mut T) -> Result<A::Instruction, A::DecodeError> {          let mut inst = A::Instruction::default(); -        self.decode_into(&mut inst, bytes).map(|_: ()| inst) +        self.decode_into(&mut inst, words).map(|_: ()| inst)      } -    fn decode_into<T: Reader<A::Word>>(&self, inst: &mut A::Instruction, bytes: &mut T) -> Result<(), Self::Error>; +    fn decode_into<T: Reader<A::Address, A::Word>>(&self, inst: &mut A::Instruction, words: &mut T) -> Result<(), A::DecodeError>;  }  #[cfg(feature="use-serde")] @@ -75,7 +78,7 @@ pub trait Arch {      type Address: Address + Debug + Hash + PartialEq + Eq + Serialize + for<'de> Deserialize<'de>;      type Instruction: Instruction + LengthedInstruction<Unit=AddressDiff<Self::Address>> + Debug + Default + Sized;      type DecodeError: DecodeError + Debug + Display; -    type Decoder: Decoder<Self, Error=Self::DecodeError> + Default; +    type Decoder: Decoder<Self> + Default;      type Operand;  } @@ -85,7 +88,7 @@ pub trait Arch {      type Address: Address + Debug + Hash + PartialEq + Eq;      type Instruction: Instruction + LengthedInstruction<Unit=AddressDiff<Self::Address>> + Debug + Default + Sized;      type DecodeError: DecodeError + Debug + Display; -    type Decoder: Decoder<Self, Error=Self::DecodeError> + Default; +    type Decoder: Decoder<Self> + Default;      type Operand;  } diff --git a/src/reader.rs b/src/reader.rs new file mode 100644 index 0000000..c5dacf6 --- /dev/null +++ b/src/reader.rs @@ -0,0 +1,261 @@ +use crate::StandardDecodeError; + +impl From<ReadError> for StandardDecodeError { +    fn from(_: ReadError) -> StandardDecodeError { +        StandardDecodeError::ExhaustedInput +    } +} + +pub enum ReadError { +    ExhaustedInput, +    IOError(&'static str), +} + +pub trait Reader<Address, Item> { +    fn next(&mut self) -> Result<Item, ReadError>; +    fn next_n(&mut self, buf: &mut [Item]) -> Result<(), ReadError>; +    fn mark(&mut self); +    fn offset(&mut self) -> Address; +    fn total_offset(&mut self) -> Address; +} + +pub struct U8Reader<'a> { +    start: *const u8, +    data: *const u8, +    end: *const u8, +    mark: *const u8, +    _lifetime: core::marker::PhantomData<&'a [u8]>, +} + +impl<'a> U8Reader<'a> { +    pub fn new(data: &'a [u8]) -> U8Reader<'a> { +        U8Reader { +            start: data.as_ptr(), +            data: data.as_ptr(), +            end: unsafe { data.as_ptr().offset(data.len() as isize) }, +            mark: data.as_ptr(), +            _lifetime: core::marker::PhantomData, +        } +    } +} + +/* +#[cfg(feature = "std")] +impl<T: std::io::Read> Reader<u8> for T { +    fn next(&mut self) -> Result<u8, ReadError> { +        let mut buf = [0u8]; +        match self.read(&mut buf) { +            Ok(0) => { Err(ReadError::ExhaustedInput) } +            Ok(1) => { Ok(buf[0]) } +            Err(_) => { +                Err(ReadError::IOError("error")) +            } +        } +    } +} +*/ + +impl Reader<u64, u8> for U8Reader<'_> { +    #[inline] +    fn next(&mut self) -> Result<u8, ReadError> { +        if self.data == self.end { +            Err(ReadError::ExhaustedInput) +        } else { +            let word = unsafe { core::ptr::read(self.data) }; +            unsafe { +                self.data = self.data.offset(1); +            } +            Ok(word) +        } +    } +    #[inline] +    fn next_n(&mut self, buf: &mut [u8]) -> Result<(), ReadError> { +        if let Some(data_size) = (self.end as usize).checked_sub(self.data as usize) { +            if buf.len() > data_size { +                return Err(ReadError::ExhaustedInput); +            } +            unsafe { +                core::ptr::copy_nonoverlapping(self.data, buf.as_mut_ptr(), buf.len()); +            } +            unsafe { +                self.data = self.data.offset(buf.len() as isize); +            } +            Ok(()) +        } else { +            Err(ReadError::ExhaustedInput) +        } +    } +    #[inline] +    fn mark(&mut self) { +        self.mark = self.data; +    } +    #[inline] +    fn offset(&mut self) -> u64 { +        self.data as u64 - self.mark as u64 +    } +    #[inline] +    fn total_offset(&mut self) -> u64 { +        self.data as u64 - self.start as u64 +    } +} + +impl Reader<u32, u8> for U8Reader<'_> { +    fn next(&mut self) -> Result<u8, ReadError> { +        if self.data == self.end { +            Err(ReadError::ExhaustedInput) +        } else { +            let word = unsafe { core::ptr::read(self.data) }; +            unsafe { +                self.data = self.data.offset(1); +            } +            Ok(word) +        } +    } +    #[inline] +    fn next_n(&mut self, buf: &mut [u8]) -> Result<(), ReadError> { +        if let Some(data_size) = (self.end as usize).checked_sub(self.data as usize) { +            if buf.len() > data_size { +                return Err(ReadError::ExhaustedInput); +            } +            unsafe { +                core::ptr::copy_nonoverlapping(self.data, buf.as_mut_ptr(), buf.len()); +            } +            self.data = unsafe { self.data.offset(buf.len() as isize) }; +            Ok(()) +        } else { +            Err(ReadError::ExhaustedInput) +        } +    } +    fn mark(&mut self) { +        self.mark = self.data; +    } +    fn offset(&mut self) -> u32 { +        self.data as u32 - self.mark as u32 +    } +    fn total_offset(&mut self) -> u32 { +        self.data as u32 - self.start as u32 +    } +} + +/* +#[derive(Debug, PartialEq, Eq)] +pub struct U16le(pub u16); + +impl Reader<U16le> for &[u8] { +    fn next(&mut self) -> Result<U16le, ReadError> { +        if self.len() < 2 { +            Err(ReadError::ExhaustedInput) +        } else { +            let bytes = [self[0], self[1]]; +            *self = &self[2..]; +            Ok(U16le(u16::from_le_bytes(bytes))) +        } +    } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct U16be(pub u16); + +impl Reader<U16be> for &[u8] { +    fn next(&mut self) -> Result<U16be, ReadError> { +        if self.len() < 2 { +            Err(ReadError::ExhaustedInput) +        } else { +            let bytes = [self[0], self[1]]; +            *self = &self[2..]; +            Ok(U16be(u16::from_be_bytes(bytes))) +        } +    } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct U32le(pub u32); + +impl Reader<U32le> for &[u8] { +    fn next(&mut self) -> Result<U32le, ReadError> { +        if self.len() < 4 { +            Err(ReadError::ExhaustedInput) +        } else { +            let bytes = [self[0], self[1], self[2], self[3]]; +            *self = &self[4..]; +            Ok(U32le(u32::from_le_bytes(bytes))) +        } +    } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct U32be(pub u32); + +impl Reader<U32be> for &[u8] { +    fn next(&mut self) -> Result<U32be, ReadError> { +        if self.len() < 4 { +            Err(ReadError::ExhaustedInput) +        } else { +            let bytes = [self[0], self[1], self[2], self[3]]; +            *self = &self[4..]; +            Ok(U32be(u32::from_be_bytes(bytes))) +        } +    } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct U64le(pub u64); + +impl Reader<U64le> for &[u8] { +    fn next(&mut self) -> Result<U64le, ReadError> { +        if self.len() < 8 { +            Err(ReadError::ExhaustedInput) +        } else { +            let bytes = [self[0], self[1], self[2], self[3], self[4], self[5], self[6], self[7]]; +            *self = &self[8..]; +            Ok(U64le(u64::from_le_bytes(bytes))) +        } +    } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct U64be(pub u64); + +impl Reader<U64be> for &[u8] { +    fn next(&mut self) -> Result<U64be, ReadError> { +        if self.len() < 8 { +            Err(ReadError::ExhaustedInput) +        } else { +            let bytes = [self[0], self[1], self[2], self[3], self[4], self[5], self[6], self[7]]; +            *self = &self[8..]; +            Ok(U64be(u64::from_be_bytes(bytes))) +        } +    } +} + +impl core::fmt::Display for U16le { +    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { +        write!(f, "{}", self.0) +    } +} +impl core::fmt::Display for U16be { +    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { +        write!(f, "{}", self.0) +    } +} +impl core::fmt::Display for U32le { +    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { +        write!(f, "{}", self.0) +    } +} +impl core::fmt::Display for U32be { +    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { +        write!(f, "{}", self.0) +    } +} +impl core::fmt::Display for U64le { +    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { +        write!(f, "{}", self.0) +    } +} +impl core::fmt::Display for U64be { +    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { +        write!(f, "{}", self.0) +    } +} +*/ | 
