From e13a82d8a007aa3c2492eaf906f92a8e2adf04e6 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Thu, 7 Aug 2025 22:20:22 -0700 Subject: [Rust] Add a type-safe builder API for Activity configuration This makes it possible to see what structure the configuration takes and eliminates errors due to typos in JSON string literals. --- rust/src/workflow.rs | 81 +++------------------------------------------------- 1 file changed, 4 insertions(+), 77 deletions(-) (limited to 'rust/src/workflow.rs') diff --git a/rust/src/workflow.rs b/rust/src/workflow.rs index 1049cc2f..d937987a 100644 --- a/rust/src/workflow.rs +++ b/rust/src/workflow.rs @@ -9,10 +9,13 @@ use crate::low_level_il::{LowLevelILMutableFunction, LowLevelILRegularFunction}; use crate::medium_level_il::MediumLevelILFunction; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; use crate::string::{BnString, IntoCStr}; -use std::ffi::{c_char, c_void}; +use std::ffi::c_char; use std::ptr; use std::ptr::NonNull; +pub mod activity; +pub use activity::Activity; + #[repr(transparent)] /// The AnalysisContext struct is used to represent the current state of /// analysis for a given function. It allows direct modification of IL and other @@ -145,82 +148,6 @@ unsafe impl RefCountable for AnalysisContext { } } -// TODO: This needs to be made into a trait similar to that of `Command`. -#[repr(transparent)] -pub struct Activity { - handle: NonNull, -} - -impl Activity { - #[allow(unused)] - pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { - Self { handle } - } - - pub(crate) unsafe fn ref_from_raw(handle: NonNull) -> Ref { - Ref::new(Self { handle }) - } - - pub fn new(config: &str) -> Ref { - unsafe extern "C" fn cb_action_nop(_: *mut c_void, _: *mut BNAnalysisContext) {} - let config = config.to_cstr(); - let result = - unsafe { BNCreateActivity(config.as_ptr(), std::ptr::null_mut(), Some(cb_action_nop)) }; - unsafe { Activity::ref_from_raw(NonNull::new(result).unwrap()) } - } - - pub fn new_with_action(config: &str, mut action: F) -> Ref - where - F: FnMut(&AnalysisContext), - { - unsafe extern "C" fn cb_action( - ctxt: *mut c_void, - analysis: *mut BNAnalysisContext, - ) { - let ctxt = &mut *(ctxt as *mut F); - if let Some(analysis) = NonNull::new(analysis) { - ctxt(&AnalysisContext::from_raw(analysis)) - } - } - let config = config.to_cstr(); - let result = unsafe { - BNCreateActivity( - config.as_ptr(), - &mut action as *mut F as *mut c_void, - Some(cb_action::), - ) - }; - unsafe { Activity::ref_from_raw(NonNull::new(result).unwrap()) } - } - - pub fn name(&self) -> String { - let result = unsafe { BNActivityGetName(self.handle.as_ptr()) }; - assert!(!result.is_null()); - unsafe { BnString::into_string(result) } - } -} - -impl ToOwned for Activity { - type Owned = Ref; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } - } -} - -unsafe impl RefCountable for Activity { - unsafe fn inc_ref(handle: &Self) -> Ref { - Ref::new(Self { - handle: NonNull::new(BNNewActivityReference(handle.handle.as_ptr())) - .expect("valid handle"), - }) - } - - unsafe fn dec_ref(handle: &Self) { - BNFreeActivity(handle.handle.as_ptr()); - } -} - // TODO: We need to hide the JSON here behind a sensible/typed API. #[repr(transparent)] pub struct Workflow { -- cgit v1.3.1