Skip to content

Commit 061994f

Browse files
committed
Make CapstoneBuilder an actual builder that builds Capstone<DynamicArchTag>
1 parent 260f346 commit 061994f

File tree

1 file changed

+78
-14
lines changed

1 file changed

+78
-14
lines changed

capstone-rs/src/arch/mod.rs

+78-14
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66

77
use alloc::vec::Vec;
88
use core::fmt::Debug;
9-
use core::marker::PhantomData;
109

1110
use crate::capstone::Capstone;
1211
use crate::constants::Endian;
1312
use crate::error::CsResult;
14-
use crate::{Arch, ExtraMode, InsnDetail, InsnGroupId, InsnId, Mode, RegId, Syntax};
13+
use crate::{Arch, Error, ExtraMode, InsnDetail, InsnGroupId, InsnId, Mode, RegId, Syntax};
1514

1615
macro_rules! define_subset_enum {
1716
( [
@@ -176,14 +175,6 @@ macro_rules! define_arch_builder {
176175
}
177176
}
178177
)+
179-
180-
impl CapstoneBuilder {
181-
$(
182-
pub fn $arch(self) -> $arch::ArchCapstoneBuilder {
183-
Default::default()
184-
}
185-
)*
186-
}
187178
}
188179
}
189180

@@ -442,10 +433,83 @@ pub(crate) mod arch_builder {
442433

443434
/// Builds `Capstone` object
444435
#[derive(Debug, Default)]
445-
pub struct CapstoneBuilder(
446-
/// Hidden field to prevent users from instantiating `CapstoneBuilder`
447-
PhantomData<()>,
448-
);
436+
pub struct CapstoneBuilder {
437+
arch: Option<Arch>,
438+
mode: Option<Mode>,
439+
is_detail: bool,
440+
extra_mode: Vec<ExtraMode>,
441+
syntax: Option<Syntax>,
442+
endian: Option<Endian>,
443+
}
444+
445+
impl CapstoneBuilder {
446+
/// Set the capstone architecture.
447+
///
448+
/// This function must be called before the `build` function is called.
449+
pub fn arch(mut self, arch: Arch) -> Self {
450+
self.arch = Some(arch);
451+
self
452+
}
453+
}
454+
455+
impl BuildsCapstone<DynamicArchTag> for CapstoneBuilder {
456+
fn mode(mut self, mode: Mode) -> Self {
457+
self.mode = Some(mode);
458+
self
459+
}
460+
461+
fn detail(mut self, enable_detail: bool) -> Self {
462+
self.is_detail = enable_detail;
463+
self
464+
}
465+
466+
fn build(self) -> CsResult<Capstone<DynamicArchTag>> {
467+
let arch = self
468+
.arch
469+
.ok_or_else(|| Error::CustomError("Must specify arch with `arch()` method"))?;
470+
let mode = self
471+
.mode
472+
.ok_or_else(|| Error::CustomError("Must specify mode with `mode()` method"))?;
473+
474+
let mut capstone = Capstone::new_raw(
475+
arch,
476+
mode.into(),
477+
self.extra_mode.iter().copied().map(|x| x.into()),
478+
self.endian,
479+
)?;
480+
481+
if let Some(syntax) = self.syntax {
482+
capstone.set_syntax(syntax)?;
483+
}
484+
if self.is_detail {
485+
capstone.set_detail(self.is_detail)?;
486+
}
487+
488+
Ok(capstone)
489+
}
490+
}
491+
492+
impl BuildsCapstoneEndian<DynamicArchTag> for CapstoneBuilder {
493+
fn endian(mut self, endian: Endian) -> Self {
494+
self.endian = Some(endian);
495+
self
496+
}
497+
}
498+
499+
impl BuildsCapstoneExtraMode<DynamicArchTag> for CapstoneBuilder {
500+
fn extra_mode<T: Iterator<Item = ExtraMode>>(mut self, extra_mode: T) -> Self {
501+
self.extra_mode.clear();
502+
self.extra_mode.extend(extra_mode);
503+
self
504+
}
505+
}
506+
507+
impl BuildsCapstoneSyntax<DynamicArchTag> for CapstoneBuilder {
508+
fn syntax(mut self, syntax: Syntax) -> Self {
509+
self.syntax = Some(syntax);
510+
self
511+
}
512+
}
449513

450514
/// Provides architecture-specific details about an instruction
451515
pub trait DetailsArchInsn: PartialEq + Debug {

0 commit comments

Comments
 (0)