diff options
Diffstat (limited to 'src')
-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) + } +} +*/ |