use crate::instruction::{info, Instruction};
use super::error;
use super::Binary;
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct Func<F: FnMut(u64) -> Result<Instruction<I>, E>, I: info::Info, E> {
func: F,
phantom: core::marker::PhantomData<(I, E)>,
}
impl<F: FnMut(u64) -> Result<Instruction<I>, E>, I: info::Info, E> Func<F, I, E> {
fn new(func: F) -> Self {
Self {
func,
phantom: Default::default(),
}
}
}
impl<F: FnMut(u64) -> Result<Instruction<I>, E>, I: info::Info, E> Binary<I> for Func<F, I, E> {
type Error = E;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
(self.func)(address)
}
}
pub fn from_fn<F, I, E>(func: F) -> Func<F, I, E>
where
F: FnMut(u64) -> Result<Instruction<I>, E>,
I: info::Info,
{
Func::new(func)
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Segment<T: AsRef<[u8]>, B> {
data: T,
base: B,
}
impl<T: AsRef<[u8]>, B> Segment<T, B> {
pub fn new(data: T, base: B) -> Self {
Self { data, base }
}
}
impl<T: AsRef<[u8]>, B: info::Decode<I>, I: info::Info> Binary<I> for Segment<T, B> {
type Error = error::SegmentError;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
let offset = address.try_into().map_err(Self::Error::ExceededHostUSize)?;
let insn_data = self
.data
.as_ref()
.split_at_checked(offset)
.map(|(_, d)| d)
.filter(|d| !d.is_empty())
.ok_or(Self::Error::AddressNotCovered)?;
Instruction::extract(insn_data, &self.base)
.map(|(i, _)| i)
.ok_or(Self::Error::InvalidInstruction)
}
}
pub fn from_segment<T: AsRef<[u8]>, B>(data: T, base: B) -> Segment<T, B> {
Segment::new(data, base)
}
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct SimpleMap<T: AsRef<[(u64, Instruction<I>)]>, I: info::Info> {
inner: T,
phantom: core::marker::PhantomData<I>,
}
impl<T: AsRef<[(u64, Instruction<I>)]>, I: info::Info> SimpleMap<T, I> {
pub fn new<J>(mut inner: J) -> Self
where
T: From<J>,
J: AsMut<[(u64, Instruction<I>)]>,
{
inner.as_mut().sort_unstable_by_key(|(a, _)| *a);
Self {
inner: inner.into(),
phantom: Default::default(),
}
}
pub fn from_sorted(inner: T) -> Option<Self> {
inner
.as_ref()
.is_sorted_by_key(|(a, _)| *a)
.then_some(Self {
inner,
phantom: Default::default(),
})
}
}
impl<T, J, I> From<J> for SimpleMap<T, I>
where
T: AsRef<[(u64, Instruction<I>)]> + From<J>,
J: AsMut<[(u64, Instruction<I>)]>,
I: info::Info,
{
fn from(inner: J) -> Self {
Self::new(inner)
}
}
impl<T: AsRef<[(u64, Instruction<I>)]>, I: info::Info + Clone> Binary<I> for SimpleMap<T, I> {
type Error = error::NoInstruction;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
let map = self.inner.as_ref();
map.binary_search_by_key(&address, |(a, _)| *a)
.map(|i| map[i].1.clone())
.map_err(|_| error::NoInstruction)
}
}
pub fn from_sorted_map<T, I>(inner: T) -> Option<SimpleMap<T, I>>
where
T: AsRef<[(u64, Instruction<I>)]>,
I: info::Info,
{
SimpleMap::from_sorted(inner)
}
pub fn from_map<T, J, I>(inner: J) -> SimpleMap<T, I>
where
T: AsRef<[(u64, Instruction<I>)]> + From<J>,
J: AsMut<[(u64, Instruction<I>)]>,
I: info::Info,
{
inner.into()
}
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct Empty;
impl<I: info::Info> Binary<I> for Empty {
type Error = error::NoInstruction;
fn get_insn(&mut self, _: u64) -> Result<Instruction<I>, Self::Error> {
Err(error::NoInstruction)
}
}