binaryninja/similarity/
node.rs1use super::{
2 SimilarityApplyStatus, SimilarityEntityId, SimilarityEntityInfo, SimilarityEntityRef,
3 SimilarityResult, SimilarityResultId, SimilaritySessionNodeId,
4};
5use crate::binary_view::BinaryView;
6use crate::file_metadata::FileMetadata;
7use crate::function::Function;
8use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
9use crate::settings::Settings;
10use binaryninjacore_sys::*;
11use std::ffi::{CStr, CString};
12
13pub struct SimilaritySessionNode {
15 pub(crate) handle: *mut BNSimilaritySessionNode,
16}
17
18impl SimilaritySessionNode {
19 pub fn new(view: &BinaryView) -> Ref<Self> {
21 let handle = unsafe { BNCreateSimilaritySessionNode(view.handle) };
22 unsafe { Ref::new(Self { handle }) }
23 }
24
25 pub fn new_from_file(file: &FileMetadata) -> Ref<Self> {
30 let handle = unsafe { BNCreateSimilaritySessionNodeFromFile(file.handle) };
31 unsafe { Ref::new(Self { handle }) }
32 }
33
34 pub unsafe fn from_raw(handle: *mut BNSimilaritySessionNode) -> Self {
35 Self { handle }
36 }
37
38 pub unsafe fn ref_from_raw(handle: *mut BNSimilaritySessionNode) -> Ref<Self> {
39 Ref::new(Self { handle })
40 }
41
42 pub fn view(&self) -> Option<Ref<BinaryView>> {
48 let view = unsafe { BNSimilaritySessionNodeGetView(self.handle) };
49 if view.is_null() {
50 None
51 } else {
52 Some(unsafe { BinaryView::ref_from_raw(view) })
53 }
54 }
55
56 pub fn set_view(&self, view: Option<&BinaryView>) {
60 unsafe {
61 BNSimilaritySessionNodeSetView(
62 self.handle,
63 view.map(|view| view.handle).unwrap_or(std::ptr::null_mut()),
64 )
65 }
66 }
67
68 pub fn file(&self) -> Ref<FileMetadata> {
70 let file = unsafe { BNSimilaritySessionNodeGetFile(self.handle) };
71 FileMetadata::ref_from_raw(file)
72 }
73
74 pub fn load_options(&self) -> Ref<Settings> {
78 let settings = unsafe { BNSimilaritySessionNodeGetLoadOptions(self.handle) };
79 unsafe { Settings::ref_from_raw(settings) }
80 }
81
82 pub fn id(&self) -> SimilaritySessionNodeId {
84 unsafe { BNSimilaritySessionNodeGetId(self.handle) }.into()
85 }
86
87 pub fn create_entity(&self, info: SimilarityEntityInfo) -> SimilarityEntityId {
92 let name =
93 CString::new(info.name).expect("similarity entity names cannot contain null bytes");
94 let raw_info = BNSimilarityEntityInfo {
95 type_: info.entity_type,
96 address: info.address,
97 name: name.as_ptr(),
98 };
99 unsafe { BNSimilaritySessionNodeCreateEntity(self.handle, &raw_info) }.into()
100 }
101
102 pub fn remove_entity(&self, id: SimilarityEntityId) -> bool {
106 unsafe { BNSimilaritySessionNodeRemoveEntity(self.handle, id.into()) }
107 }
108
109 pub fn entity(&self, id: SimilarityEntityId) -> Option<SimilarityEntityInfo> {
111 let mut info = BNSimilarityEntityInfo::default();
112 let success =
113 unsafe { BNSimilaritySessionNodeGetEntity(self.handle, id.into(), &mut info) };
114 if success {
115 let result = SimilarityEntityInfo {
116 entity_type: info.type_,
117 address: info.address,
118 name: if info.name.is_null() {
119 String::new()
120 } else {
121 unsafe { CStr::from_ptr(info.name) }
122 .to_string_lossy()
123 .into_owned()
124 },
125 };
126 unsafe { BNFreeSimilarityEntityInfo(&mut info) };
127 Some(result)
128 } else {
129 None
130 }
131 }
132
133 pub fn entities(&self) -> Array<SimilarityEntityId> {
135 let mut count = 0;
136 let entities = unsafe { BNSimilaritySessionNodeGetEntities(self.handle, &mut count) };
137 unsafe { Array::new(entities, count, ()) }
138 }
139
140 pub fn add_scheduled_entity(&self, id: SimilarityEntityId) -> bool {
147 unsafe { BNSimilaritySessionNodeAddScheduledEntity(self.handle, id.into()) }
148 }
149
150 pub fn remove_scheduled_entity(&self, id: SimilarityEntityId) -> bool {
154 unsafe { BNSimilaritySessionNodeRemoveScheduledEntity(self.handle, id.into()) }
155 }
156
157 pub fn scheduled_entities(&self) -> Array<SimilarityEntityId> {
159 let mut count = 0;
160 let entities =
161 unsafe { BNSimilaritySessionNodeGetScheduledEntities(self.handle, &mut count) };
162 unsafe { Array::new(entities, count, ()) }
163 }
164
165 pub fn entity_function(&self, id: SimilarityEntityId) -> Option<Ref<Function>> {
167 let function = unsafe { BNSimilaritySessionNodeGetEntityFunction(self.handle, id.into()) };
168 if function.is_null() {
169 None
170 } else {
171 Some(unsafe { Function::ref_from_raw(function) })
172 }
173 }
174
175 pub fn results(&self, entity: SimilarityEntityId) -> Vec<SimilarityResultId> {
177 let mut count = 0;
178 let results =
179 unsafe { BNSimilaritySessionNodeGetResults(self.handle, entity.into(), &mut count) };
180 let output = unsafe { std::slice::from_raw_parts(results, count) }
181 .iter()
182 .copied()
183 .map(SimilarityResultId::from)
184 .collect();
185 unsafe { BNFreeSimilarityResultIdList(results) };
186 output
187 }
188
189 pub fn result(&self, result: SimilarityResultId) -> Option<SimilarityResult> {
191 let mut output = BNSimilarityResult::default();
192 unsafe {
193 BNSimilaritySessionNodeGetResult(self.handle, result.into(), &mut output)
194 .then(|| output.into())
195 }
196 }
197
198 pub fn apply_target(
200 &self,
201 entity: SimilarityEntityId,
202 target: SimilarityEntityRef,
203 ) -> SimilarityApplyStatus {
204 let target = target.into();
205 unsafe { BNSimilaritySessionNodeApplyTarget(self.handle, entity.into(), &target) }
206 }
207
208 pub fn set_resolved_result(
211 &self,
212 entity: SimilarityEntityId,
213 result: SimilarityResultId,
214 ) -> bool {
215 unsafe {
216 BNSimilaritySessionNodeSetResolvedResult(self.handle, entity.into(), result.into())
217 }
218 }
219
220 pub fn resolved_result(&self, entity: SimilarityEntityId) -> Option<SimilarityResultId> {
222 let mut result = BNSimilarityResultId::default();
223 let success = unsafe {
224 BNSimilaritySessionNodeGetResolvedResult(self.handle, entity.into(), &mut result)
225 };
226 success.then(|| result.into())
227 }
228
229 pub fn clear_resolved_result(&self, entity: SimilarityEntityId) -> bool {
231 unsafe { BNSimilaritySessionNodeClearResolvedResult(self.handle, entity.into()) }
232 }
233
234 pub fn incoming_edges(&self) -> Vec<SimilaritySessionNodeId> {
236 let mut count = 0;
237 let edges = unsafe { BNSimilaritySessionNodeGetIncomingEdges(self.handle, &mut count) };
238 let result = unsafe { std::slice::from_raw_parts(edges, count) }
239 .iter()
240 .copied()
241 .map(Into::into)
242 .collect();
243 unsafe { BNFreeSimilaritySessionNodeEdgeList(edges) };
244 result
245 }
246
247 pub fn outgoing_edges(&self) -> Vec<SimilaritySessionNodeId> {
249 let mut count = 0;
250 let edges = unsafe { BNSimilaritySessionNodeGetOutgoingEdges(self.handle, &mut count) };
251 let result = unsafe { std::slice::from_raw_parts(edges, count) }
252 .iter()
253 .copied()
254 .map(Into::into)
255 .collect();
256 unsafe { BNFreeSimilaritySessionNodeEdgeList(edges) };
257 result
258 }
259
260 pub fn incoming_nodes(&self) -> Array<SimilaritySessionNode> {
262 let mut count = 0;
263 let result = unsafe { BNSimilaritySessionNodeGetIncomingNodes(self.handle, &mut count) };
264 unsafe { Array::new(result, count, ()) }
265 }
266
267 pub fn outgoing_nodes(&self) -> Array<SimilaritySessionNode> {
269 let mut count = 0;
270 let result = unsafe { BNSimilaritySessionNodeGetOutgoingNodes(self.handle, &mut count) };
271 unsafe { Array::new(result, count, ()) }
272 }
273}
274
275unsafe impl RefCountable for SimilaritySessionNode {
276 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
277 Ref::new(Self {
278 handle: BNNewSimilaritySessionNodeReference(handle.handle),
279 })
280 }
281 unsafe fn dec_ref(handle: &Self) {
282 BNFreeSimilaritySessionNode(handle.handle);
283 }
284}
285
286impl ToOwned for SimilaritySessionNode {
287 type Owned = Ref<Self>;
288
289 fn to_owned(&self) -> Self::Owned {
290 unsafe { RefCountable::inc_ref(self) }
291 }
292}
293
294impl CoreArrayProvider for SimilaritySessionNode {
295 type Raw = *mut BNSimilaritySessionNode;
296 type Context = ();
297 type Wrapped<'a> = Guard<'a, Self>;
298}
299
300impl CoreArrayProvider for SimilarityEntityId {
301 type Raw = BNSimilarityEntityId;
302 type Context = ();
303 type Wrapped<'a> = SimilarityEntityId;
304}
305
306unsafe impl CoreArrayProviderInner for SimilarityEntityId {
307 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
308 BNFreeSimilarityEntityList(raw)
309 }
310
311 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
312 (*raw).into()
313 }
314}
315
316unsafe impl CoreArrayProviderInner for SimilaritySessionNode {
317 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
318 BNFreeSimilaritySessionNodeList(raw, count)
319 }
320
321 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
322 Guard::new(Self::from_raw(*raw), context)
323 }
324}