diff options
| author | Mark Rowe <mark@vector35.com> | 2025-08-07 22:20:22 -0700 |
|---|---|---|
| committer | Mark Rowe <mark@vector35.com> | 2025-08-13 19:25:43 -0700 |
| commit | e13a82d8a007aa3c2492eaf906f92a8e2adf04e6 (patch) | |
| tree | 0dc23fd7406709f92e4aa2823371c45e8ea30260 /rust/src/workflow.rs | |
| parent | 0cbc2ab62773db17ec29e1027992fcf55905ed76 (diff) | |
[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.
Diffstat (limited to 'rust/src/workflow.rs')
| -rw-r--r-- | rust/src/workflow.rs | 81 |
1 files changed, 4 insertions, 77 deletions
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<BNActivity>, -} - -impl Activity { - #[allow(unused)] - pub(crate) unsafe fn from_raw(handle: NonNull<BNActivity>) -> Self { - Self { handle } - } - - pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNActivity>) -> Ref<Self> { - Ref::new(Self { handle }) - } - - pub fn new(config: &str) -> Ref<Self> { - 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<F>(config: &str, mut action: F) -> Ref<Self> - where - F: FnMut(&AnalysisContext), - { - unsafe extern "C" fn cb_action<F: FnMut(&AnalysisContext)>( - 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::<F>), - ) - }; - 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<Self>; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } - } -} - -unsafe impl RefCountable for Activity { - unsafe fn inc_ref(handle: &Self) -> Ref<Self> { - 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 { |
