use capstone::Capstone;
use constants::Endian;
use error::CsResult;
use std::marker::PhantomData;
macro_rules! define_subset_enum {
( [
$subset_enum:ident = $base_enum:ident
]
$( $variant:ident, )*
) => {
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum $subset_enum {
$(
$variant,
)*
}
impl From<$subset_enum> for $base_enum {
fn from(other: $subset_enum) -> $base_enum {
match other {
$(
$subset_enum::$variant => $base_enum::$variant,
)*
}
}
}
};
}
macro_rules! define_arch_builder {
( @extra_modes () ) => {};
( @extra_modes ( $( $extra_mode:ident, )+ ) ) => {
impl super::BuildsCapstoneExtraMode<ArchMode, ArchExtraMode> for ArchCapstoneBuilder {
fn extra_mode<T: Iterator<Item=ArchExtraMode>>(&mut self, extra_mode: T) -> & mut Self {
self.extra_mode.clear();
self.extra_mode.extend(extra_mode);
self
}
}
};
( @syntax () ) => {};
( @syntax ( $( $syntax:ident, )+ ) ) => {
impl super::BuildsCapstoneSyntax<ArchMode, ArchSyntax> for ArchCapstoneBuilder {
fn syntax(& mut self, syntax: ArchSyntax) -> &mut Self {
self.syntax = Some(syntax);
self
}
}
};
( @endian ( false) ) => {};
( @endian ( true ) ) => {
impl super::BuildsCapstoneEndian<ArchMode> for ArchCapstoneBuilder {
fn endian(&mut self, endian: Endian) -> &mut Self {
self.endian = Some(endian);
self
}
}
};
(
$( [
( $arch:ident, $arch_variant:ident )
( mode: $( $mode:ident, )+ )
( extra_modes: $( $extra_mode:ident, )* )
( syntax: $( $syntax:ident, )* )
( both_endian: $( $endian:ident )* )
] )+
) => {
$(
pub mod $arch {
use capstone::Capstone;
use constants::{Arch, Endian, ExtraMode, Mode, Syntax};
use error::{CsResult, Error};
define_arch_builder!( @syntax ( $( $syntax, )* ) );
define_arch_builder!( @endian ( $( $endian )* ) );
define_arch_builder!( @extra_modes ( $( $extra_mode, )* ) );
define_subset_enum!(
[ ArchMode = Mode ]
$( $mode, )*
);
define_subset_enum!(
[ ArchExtraMode = ExtraMode ]
$( $extra_mode, )*
);
define_subset_enum!(
[ ArchSyntax = Syntax ]
$( $syntax, )*
);
pub struct ArchCapstoneBuilder {
pub(crate) mode: Option<ArchMode>,
pub(crate) is_detail: bool,
pub(crate) extra_mode: Vec<ArchExtraMode>,
pub(crate) syntax: Option<ArchSyntax>,
pub(crate) endian: Option<Endian>,
}
impl super::BuildsCapstone<ArchMode> for ArchCapstoneBuilder {
fn mode(&mut self, mode: ArchMode) -> &mut Self {
self.mode = Some(mode);
self
}
fn detail(&mut self, enable_detail: bool) -> &mut Self {
self.is_detail = enable_detail;
self
}
fn build(&mut self) -> CsResult<Capstone> {
let mode = match self.mode {
Some(mode) => mode,
None => {
let msg: &'static str = concat!(
"Must specify mode for ",
stringify!($arch),
"::ArchCapstoneBuilder with `mode()` method",
);
return Err(Error::CustomError(msg));
}
};
let extra_mode = self.extra_mode.iter().map(|x| ExtraMode::from(*x));
let mut capstone = Capstone::new_raw(Arch::$arch_variant,
mode.into(),
extra_mode,
self.endian)?;
if let Some(syntax) = self.syntax {
capstone.set_syntax(Syntax::from(syntax))?;
}
if self.is_detail {
capstone.set_detail(self.is_detail)?;
}
Ok(capstone)
}
}
impl Default for ArchCapstoneBuilder {
fn default() -> Self {
ArchCapstoneBuilder {
mode: None,
is_detail: false,
extra_mode: vec![],
endian: None,
syntax: None,
}
}
}
}
)+
impl CapstoneBuilder {
pub(crate) fn new() -> Self {
CapstoneBuilder(PhantomData)
}
$(
pub fn $arch(self) -> $arch::ArchCapstoneBuilder {
Default::default()
}
)*
}
}
}
pub trait BuildsCapstone<ArchMode> {
fn mode(&mut self, mode: ArchMode) -> &mut Self;
fn detail(&mut self, enable_detail: bool) -> &mut Self;
fn build(&mut self) -> CsResult<Capstone>;
}
pub trait BuildsCapstoneExtraMode<ArchMode, ArchExtraMode>
: BuildsCapstone<ArchMode> {
fn extra_mode<T: Iterator<Item = ArchExtraMode>>(&mut self, extra_mode: T) -> &mut Self;
}
pub trait BuildsCapstoneSyntax<ArchMode, ArchSyntax>: BuildsCapstone<ArchMode> {
fn syntax(&mut self, syntax: ArchSyntax) -> &mut Self;
}
pub trait BuildsCapstoneEndian<ArchMode>: BuildsCapstone<ArchMode> {
fn endian(&mut self, endian: Endian) -> &mut Self;
}
define_arch_builder!(
[
( arm, ARM )
( mode:
Arm,
Thumb,
)
( extra_modes:
MClass,
V8,
)
( syntax:
NoRegName,
)
( both_endian: true )
]
[
( arm64, ARM64 )
( mode:
Arm,
)
( extra_modes: )
( syntax: )
( both_endian: true )
]
[
( mips, MIPS )
( mode:
Mode32,
Mode64,
Mips32R6,
MipsGP64,
)
( extra_modes:
Micro,
)
( syntax: )
( both_endian: true )
]
[
( ppc, PPC )
( mode:
Mode32,
Mode64,
)
( extra_modes: )
( syntax:
NoRegName,
)
( both_endian: true )
]
[
( sparc, SPARC )
( mode:
Default,
V9,
)
( extra_modes: )
( syntax: )
( both_endian: false )
]
[
( sysz, SYSZ )
( mode:
Default,
)
( extra_modes: )
( syntax: )
( both_endian: false )
]
[
( x86, X86 )
( mode:
Mode16,
Mode32,
Mode64,
)
( extra_modes: )
( syntax:
Intel,
Att,
)
( both_endian: false )
]
[
( xcore, XCORE )
( mode:
Default,
)
( extra_modes: )
( syntax: )
( both_endian: false )
]
);
pub struct CapstoneBuilder(
PhantomData<()>
);