|
6 | 6 |
|
7 | 7 | use alloc::vec::Vec;
|
8 | 8 | use core::fmt::Debug;
|
9 |
| -use core::marker::PhantomData; |
10 | 9 |
|
11 | 10 | use crate::capstone::Capstone;
|
12 | 11 | use crate::constants::Endian;
|
13 | 12 | 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}; |
15 | 14 |
|
16 | 15 | macro_rules! define_subset_enum {
|
17 | 16 | ( [
|
@@ -176,14 +175,6 @@ macro_rules! define_arch_builder {
|
176 | 175 | }
|
177 | 176 | }
|
178 | 177 | )+
|
179 |
| - |
180 |
| - impl CapstoneBuilder { |
181 |
| - $( |
182 |
| - pub fn $arch(self) -> $arch::ArchCapstoneBuilder { |
183 |
| - Default::default() |
184 |
| - } |
185 |
| - )* |
186 |
| - } |
187 | 178 | }
|
188 | 179 | }
|
189 | 180 |
|
@@ -442,10 +433,83 @@ pub(crate) mod arch_builder {
|
442 | 433 |
|
443 | 434 | /// Builds `Capstone` object
|
444 | 435 | #[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 | +} |
449 | 513 |
|
450 | 514 | /// Provides architecture-specific details about an instruction
|
451 | 515 | pub trait DetailsArchInsn: PartialEq + Debug {
|
|
0 commit comments