Skip to content

Commit 75a2db1

Browse files
committed
[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.
1 parent cde1c38 commit 75a2db1

File tree

2 files changed

+554
-77
lines changed

2 files changed

+554
-77
lines changed

rust/src/workflow.rs

Lines changed: 4 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ use crate::low_level_il::{LowLevelILMutableFunction, LowLevelILRegularFunction};
99
use crate::medium_level_il::MediumLevelILFunction;
1010
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
1111
use crate::string::{BnString, IntoCStr};
12-
use std::ffi::{c_char, c_void};
12+
use std::ffi::c_char;
1313
use std::ptr;
1414
use std::ptr::NonNull;
1515

16+
pub mod activity;
17+
pub use activity::Activity;
18+
1619
#[repr(transparent)]
1720
/// The AnalysisContext struct is used to represent the current state of
1821
/// analysis for a given function. It allows direct modification of IL and other
@@ -145,82 +148,6 @@ unsafe impl RefCountable for AnalysisContext {
145148
}
146149
}
147150

148-
// TODO: This needs to be made into a trait similar to that of `Command`.
149-
#[repr(transparent)]
150-
pub struct Activity {
151-
handle: NonNull<BNActivity>,
152-
}
153-
154-
impl Activity {
155-
#[allow(unused)]
156-
pub(crate) unsafe fn from_raw(handle: NonNull<BNActivity>) -> Self {
157-
Self { handle }
158-
}
159-
160-
pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNActivity>) -> Ref<Self> {
161-
Ref::new(Self { handle })
162-
}
163-
164-
pub fn new(config: &str) -> Ref<Self> {
165-
unsafe extern "C" fn cb_action_nop(_: *mut c_void, _: *mut BNAnalysisContext) {}
166-
let config = config.to_cstr();
167-
let result =
168-
unsafe { BNCreateActivity(config.as_ptr(), std::ptr::null_mut(), Some(cb_action_nop)) };
169-
unsafe { Activity::ref_from_raw(NonNull::new(result).unwrap()) }
170-
}
171-
172-
pub fn new_with_action<F>(config: &str, mut action: F) -> Ref<Self>
173-
where
174-
F: FnMut(&AnalysisContext),
175-
{
176-
unsafe extern "C" fn cb_action<F: FnMut(&AnalysisContext)>(
177-
ctxt: *mut c_void,
178-
analysis: *mut BNAnalysisContext,
179-
) {
180-
let ctxt = &mut *(ctxt as *mut F);
181-
if let Some(analysis) = NonNull::new(analysis) {
182-
ctxt(&AnalysisContext::from_raw(analysis))
183-
}
184-
}
185-
let config = config.to_cstr();
186-
let result = unsafe {
187-
BNCreateActivity(
188-
config.as_ptr(),
189-
&mut action as *mut F as *mut c_void,
190-
Some(cb_action::<F>),
191-
)
192-
};
193-
unsafe { Activity::ref_from_raw(NonNull::new(result).unwrap()) }
194-
}
195-
196-
pub fn name(&self) -> String {
197-
let result = unsafe { BNActivityGetName(self.handle.as_ptr()) };
198-
assert!(!result.is_null());
199-
unsafe { BnString::into_string(result) }
200-
}
201-
}
202-
203-
impl ToOwned for Activity {
204-
type Owned = Ref<Self>;
205-
206-
fn to_owned(&self) -> Self::Owned {
207-
unsafe { RefCountable::inc_ref(self) }
208-
}
209-
}
210-
211-
unsafe impl RefCountable for Activity {
212-
unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
213-
Ref::new(Self {
214-
handle: NonNull::new(BNNewActivityReference(handle.handle.as_ptr()))
215-
.expect("valid handle"),
216-
})
217-
}
218-
219-
unsafe fn dec_ref(handle: &Self) {
220-
BNFreeActivity(handle.handle.as_ptr());
221-
}
222-
}
223-
224151
// TODO: We need to hide the JSON here behind a sensible/typed API.
225152
#[repr(transparent)]
226153
pub struct Workflow {

0 commit comments

Comments
 (0)