pub mod basic;
#[cfg(feature = "alloc")]
pub mod boxed;
pub mod combinators;
#[cfg(feature = "elf")]
pub mod elf;
pub mod error;
#[cfg(test)]
mod tests;
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
pub use basic::{Empty, from_fn, from_map, from_segment, from_sorted_map};
pub use combinators::Multi;
use crate::instruction::{self, Instruction};
use error::Miss;
use instruction::info::Info;
pub trait Binary<I: Info> {
type Error;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error>;
}
impl<A, B, I, E> Binary<I> for (A, B)
where
A: Binary<I, Error = E>,
B: Binary<I, Error = E>,
I: Info,
E: error::MaybeMiss,
{
type Error = B::Error;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
use error::MaybeMiss;
let res = self.0.get_insn(address);
if res.is_miss() {
self.1.get_insn(address)
} else {
res
}
}
}
impl<B, I> Binary<I> for Option<B>
where
B: Binary<I>,
B::Error: Miss,
I: Info,
{
type Error = B::Error;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
self.as_mut()
.map(|b| b.get_insn(address))
.unwrap_or_else(|| Miss::miss(address))
}
}
#[cfg(feature = "alloc")]
impl<B: Binary<I> + ?Sized, I: Info> Binary<I> for Box<B> {
type Error = B::Error;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
B::get_insn(self.as_mut(), address)
}
}
#[cfg(feature = "either")]
impl<L, R, I, E> Binary<I> for either::Either<L, R>
where
L: Binary<I, Error = E>,
R: Binary<I, Error = E>,
I: Info,
{
type Error = E;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
either::for_both!(self, b => b.get_insn(address))
}
}
pub trait Adaptable: Sized {
fn with_offset(self, offset: u64) -> Offset<Self> {
Offset::new(self, offset)
}
#[cfg(feature = "alloc")]
fn boxed<'a, I>(self) -> boxed::Binary<'a, I>
where
I: Info,
Self: Binary<I>,
Self: Send + Sync + 'a,
Self::Error: error::MaybeMissError + 'static,
{
Box::new(boxed::BoxedError::new(self))
}
#[cfg(feature = "alloc")]
fn boxer<'a, I>(self) -> alloc::sync::Arc<dyn Fn() -> boxed::Binary<'a, I> + 'a>
where
I: Info,
Self: Binary<I>,
Self: Clone + Send + Sync + 'a,
Self::Error: error::MaybeMissError + 'static,
{
let boxed = boxed::BoxedError::new(self);
alloc::sync::Arc::new(move || Box::new(boxed.clone()))
}
}
impl<T> Adaptable for T {}
#[derive(Copy, Clone, Debug)]
pub struct Offset<B> {
inner: B,
offset: u64,
}
impl<B> Offset<B> {
pub fn new(inner: B, offset: u64) -> Self {
Self { inner, offset }
}
pub fn inner(&self) -> &B {
&self.inner
}
pub fn offset(&self) -> u64 {
self.offset
}
}
impl<B, I> Binary<I> for Offset<B>
where
B: Binary<I>,
B::Error: Miss,
I: Info,
{
type Error = B::Error;
fn get_insn(&mut self, address: u64) -> Result<Instruction<I>, Self::Error> {
address
.checked_sub(self.offset)
.ok_or(B::Error::miss(address))
.and_then(|a| self.inner.get_insn(a))
}
}