binaryninja/similarity/
graph.rs1use super::node::SimilaritySessionNode;
2use super::SimilaritySessionNodeId;
3use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
4use binaryninjacore_sys::*;
5use std::ffi::c_void;
6
7pub trait SimilaritySessionGraphReceiver: Send + Sync + 'static {
9 fn on_graph_changed(&self);
10}
11
12pub struct CoreSimilaritySessionGraphReceiver {
14 pub(crate) handle: *mut BNSimilaritySessionGraphReceiver,
15}
16
17impl CoreSimilaritySessionGraphReceiver {
18 pub unsafe fn from_raw(handle: *mut BNSimilaritySessionGraphReceiver) -> Self {
19 Self { handle }
20 }
21
22 pub unsafe fn ref_from_raw(handle: *mut BNSimilaritySessionGraphReceiver) -> Ref<Self> {
23 Ref::new(Self { handle })
24 }
25
26 pub fn create<C: SimilaritySessionGraphReceiver>(
27 receiver: C,
28 ) -> Ref<CoreSimilaritySessionGraphReceiver> {
29 let receiver = Box::into_raw(Box::new(receiver));
30 let mut callbacks = BNCustomSimilaritySessionGraphReceiver {
31 context: receiver.cast(),
32 externalRefTaken: None,
33 externalRefReleased: None,
34 onGraphChanged: Some(cb_on_graph_changed::<C>),
35 free: Some(cb_receiver_free::<C>),
36 };
37 let raw_receiver = unsafe { BNCreateCustomSimilaritySessionGraphReceiver(&mut callbacks) };
38 unsafe { CoreSimilaritySessionGraphReceiver::ref_from_raw(raw_receiver) }
39 }
40}
41
42impl SimilaritySessionGraphReceiver for CoreSimilaritySessionGraphReceiver {
43 fn on_graph_changed(&self) {
44 unsafe { BNSimilaritySessionGraphReceiverNotifyGraphChanged(self.handle) }
45 }
46}
47
48unsafe impl Send for CoreSimilaritySessionGraphReceiver {}
49unsafe impl Sync for CoreSimilaritySessionGraphReceiver {}
50
51impl ToOwned for CoreSimilaritySessionGraphReceiver {
52 type Owned = Ref<Self>;
53
54 fn to_owned(&self) -> Self::Owned {
55 unsafe { RefCountable::inc_ref(self) }
56 }
57}
58
59unsafe impl RefCountable for CoreSimilaritySessionGraphReceiver {
60 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
61 Ref::new(Self {
62 handle: BNNewSimilaritySessionGraphReceiverReference(handle.handle),
63 })
64 }
65
66 unsafe fn dec_ref(handle: &Self) {
67 BNFreeSimilaritySessionGraphReceiver(handle.handle);
68 }
69}
70
71impl CoreArrayProvider for CoreSimilaritySessionGraphReceiver {
72 type Raw = *mut BNSimilaritySessionGraphReceiver;
73 type Context = ();
74 type Wrapped<'a> = Guard<'a, Self>;
75}
76
77unsafe impl CoreArrayProviderInner for CoreSimilaritySessionGraphReceiver {
78 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
79 BNFreeSimilaritySessionGraphReceiverList(raw, count)
80 }
81
82 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
83 Guard::new(Self::from_raw(*raw), context)
84 }
85}
86
87unsafe extern "C" fn cb_on_graph_changed<C: SimilaritySessionGraphReceiver>(ctxt: *mut c_void) {
88 ffi_wrap!("SimilaritySessionGraphReceiver::on_graph_changed", unsafe {
89 let ctxt: &C = &*(ctxt as *const C);
90 ctxt.on_graph_changed();
91 })
92}
93
94unsafe extern "C" fn cb_receiver_free<C: SimilaritySessionGraphReceiver>(ctxt: *mut c_void) {
95 ffi_wrap!("SimilaritySessionGraphReceiver::free", unsafe {
96 let _ = Box::from_raw(ctxt as *mut C);
97 })
98}
99
100pub struct SimilaritySessionGraph {
104 pub(crate) handle: *mut BNSimilaritySessionGraph,
105}
106
107impl SimilaritySessionGraph {
108 pub unsafe fn ref_from_raw(handle: *mut BNSimilaritySessionGraph) -> Ref<Self> {
109 Ref::new(Self { handle })
110 }
111
112 pub fn add_node(&self, node: &SimilaritySessionNode) {
116 unsafe { BNSimilaritySessionGraphAddNode(self.handle, node.handle) }
117 }
118
119 pub fn remove_node(&self, node: &SimilaritySessionNode) {
121 unsafe { BNSimilaritySessionGraphRemoveNode(self.handle, node.handle) }
122 }
123
124 pub fn node(&self, id: SimilaritySessionNodeId) -> Option<Ref<SimilaritySessionNode>> {
126 let handle = unsafe { BNSimilaritySessionGraphGetNode(self.handle, id.into()) };
127 match handle.is_null() {
128 true => None,
129 false => Some(unsafe { SimilaritySessionNode::ref_from_raw(handle) }),
130 }
131 }
132
133 pub fn nodes(&self) -> Array<SimilaritySessionNode> {
135 let mut count = 0;
136 let result = unsafe { BNSimilaritySessionGraphGetNodes(self.handle, &mut count) };
137 unsafe { Array::new(result, count, ()) }
138 }
139
140 pub fn is_valid_edge(&self, from: &SimilaritySessionNode, to: &SimilaritySessionNode) -> bool {
142 unsafe { BNSimilaritySessionGraphIsValidEdge(self.handle, from.handle, to.handle) }
143 }
144
145 pub fn add_edge(&self, from: &SimilaritySessionNode, to: &SimilaritySessionNode) -> bool {
147 unsafe { BNSimilaritySessionGraphAddEdge(self.handle, from.handle, to.handle) }
148 }
149
150 pub fn remove_edge(&self, from: &SimilaritySessionNode, to: &SimilaritySessionNode) -> bool {
152 unsafe { BNSimilaritySessionGraphRemoveEdge(self.handle, from.handle, to.handle) }
153 }
154
155 pub fn add_receiver(&self, receiver: &CoreSimilaritySessionGraphReceiver) {
157 unsafe { BNSimilaritySessionGraphAddReceiver(self.handle, receiver.handle) }
158 }
159
160 pub fn remove_receiver(&self, receiver: &CoreSimilaritySessionGraphReceiver) {
162 unsafe { BNSimilaritySessionGraphRemoveReceiver(self.handle, receiver.handle) }
163 }
164
165 pub fn receivers(&self) -> Array<CoreSimilaritySessionGraphReceiver> {
167 let mut count = 0;
168 let result = unsafe { BNSimilaritySessionGraphGetReceivers(self.handle, &mut count) };
169 unsafe { Array::new(result, count, ()) }
170 }
171
172 pub fn schedule(&self) -> Vec<Vec<Ref<SimilaritySessionNode>>> {
174 let mut level_count = 0;
175 let mut node_counts_ptr: *mut usize = std::ptr::null_mut();
176 let raw_schedule = unsafe {
177 BNSimilaritySessionGraphGetSchedule(self.handle, &mut node_counts_ptr, &mut level_count)
178 };
179
180 let mut result = Vec::with_capacity(level_count);
181 unsafe {
182 let raw_levels = std::slice::from_raw_parts(raw_schedule, level_count);
183 let node_counts = std::slice::from_raw_parts(node_counts_ptr, level_count);
184 for (&raw_level, &count) in raw_levels.iter().zip(node_counts) {
185 let level = std::slice::from_raw_parts(raw_level, count)
186 .iter()
187 .map(|&node| {
188 SimilaritySessionNode::ref_from_raw(BNNewSimilaritySessionNodeReference(
189 node,
190 ))
191 })
192 .collect();
193 result.push(level);
194 }
195 BNFreeSimilaritySessionNodeSchedule(raw_schedule, node_counts_ptr, level_count);
196 }
197 result
198 }
199}
200
201impl ToOwned for SimilaritySessionGraph {
202 type Owned = Ref<Self>;
203
204 fn to_owned(&self) -> Self::Owned {
205 unsafe { RefCountable::inc_ref(self) }
206 }
207}
208
209unsafe impl RefCountable for SimilaritySessionGraph {
210 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
211 Ref::new(Self {
212 handle: BNNewSimilaritySessionGraphReference(handle.handle),
213 })
214 }
215 unsafe fn dec_ref(handle: &Self) {
216 BNFreeSimilaritySessionGraph(handle.handle);
217 }
218}