1#![allow(unused)]
2
3use crate::architecture::{Architecture, CoreArchitecture};
4use crate::calling_convention::CoreCallingConvention;
5use crate::rc::{Ref, RefCountable};
6use crate::types::Type;
7use binaryninjacore_sys::{
8 BNBoolWithConfidence, BNCallingConventionWithConfidence, BNGetCallingConventionArchitecture,
9 BNInlineDuringAnalysis, BNInlineDuringAnalysisWithConfidence, BNOffsetWithConfidence,
10 BNTypeWithConfidence,
11};
12use std::fmt;
13use std::fmt::{Debug, Display, Formatter};
14use std::hash::{Hash, Hasher};
15
16pub const MIN_CONFIDENCE: u8 = u8::MIN;
18
19pub const MAX_CONFIDENCE: u8 = u8::MAX;
21
22pub struct Conf<T> {
24 pub contents: T,
25 pub confidence: u8,
26}
27
28pub trait ConfMergeable<T, O> {
29 type Result;
30 fn merge(self, other: O) -> Self::Result;
33}
34
35impl<T> Conf<T> {
36 pub fn new(contents: T, confidence: u8) -> Self {
37 Self {
38 contents,
39 confidence,
40 }
41 }
42
43 pub fn map<U, F>(self, f: F) -> Conf<U>
44 where
45 F: FnOnce(T) -> U,
46 {
47 Conf::new(f(self.contents), self.confidence)
48 }
49
50 pub fn as_ref<U>(&self) -> Conf<&U>
51 where
52 T: AsRef<U>,
53 {
54 Conf::new(self.contents.as_ref(), self.confidence)
55 }
56}
57
58impl<T> ConfMergeable<T, Conf<T>> for Conf<T> {
62 type Result = Conf<T>;
63 fn merge(self, other: Conf<T>) -> Conf<T> {
64 if other.confidence > self.confidence {
65 other
66 } else {
67 self
68 }
69 }
70}
71
72impl<T> ConfMergeable<T, Option<Conf<T>>> for Conf<T> {
76 type Result = Conf<T>;
77 fn merge(self, other: Option<Conf<T>>) -> Conf<T> {
78 match other {
79 Some(c @ Conf { confidence, .. }) if confidence > self.confidence => c,
80 _ => self,
81 }
82 }
83}
84
85impl<T> ConfMergeable<T, Conf<T>> for Option<Conf<T>> {
89 type Result = Conf<T>;
90 fn merge(self, other: Conf<T>) -> Conf<T> {
91 match self {
92 Some(c @ Conf { confidence, .. }) if confidence >= other.confidence => c,
93 _ => other,
94 }
95 }
96}
97
98impl<T> ConfMergeable<T, Option<Conf<T>>> for Option<Conf<T>> {
102 type Result = Option<Conf<T>>;
103 fn merge(self, other: Option<Conf<T>>) -> Option<Conf<T>> {
104 match (self, other) {
105 (
106 Some(
107 this @ Conf {
108 confidence: this_confidence,
109 ..
110 },
111 ),
112 Some(
113 other @ Conf {
114 confidence: other_confidence,
115 ..
116 },
117 ),
118 ) => {
119 if this_confidence >= other_confidence {
120 Some(this)
121 } else {
122 Some(other)
123 }
124 }
125 (None, Some(c)) => Some(c),
126 (Some(c), None) => Some(c),
127 (None, None) => None,
128 }
129 }
130}
131
132impl<T: Debug> Debug for Conf<T> {
133 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
134 write!(f, "{:?} ({} confidence)", self.contents, self.confidence)
135 }
136}
137
138impl<T: Display> Display for Conf<T> {
139 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
140 write!(f, "{} ({} confidence)", self.contents, self.confidence)
141 }
142}
143
144impl<T: PartialEq> PartialEq for Conf<T> {
145 fn eq(&self, other: &Self) -> bool {
146 self.contents.eq(&other.contents)
147 }
148}
149
150impl<T: Eq> Eq for Conf<T> {}
151
152impl<T: Hash> Hash for Conf<T> {
153 fn hash<H: Hasher>(&self, state: &mut H) {
154 self.contents.hash(state);
155 }
156}
157
158impl<'a, T> From<&'a Conf<T>> for Conf<&'a T> {
159 fn from(c: &'a Conf<T>) -> Self {
160 Conf::new(&c.contents, c.confidence)
161 }
162}
163
164impl<'a, T: RefCountable> From<&'a Conf<Ref<T>>> for Conf<&'a T> {
165 fn from(c: &'a Conf<Ref<T>>) -> Self {
166 Conf::new(c.contents.as_ref(), c.confidence)
167 }
168}
169
170impl<'a, T: RefCountable> From<&'a Ref<T>> for Conf<&'a T> {
171 fn from(r: &'a Ref<T>) -> Self {
172 r.as_ref().into()
173 }
174}
175
176impl<T: Clone> Clone for Conf<T> {
177 fn clone(&self) -> Self {
178 Self {
179 contents: self.contents.clone(),
180 confidence: self.confidence,
181 }
182 }
183}
184
185impl<T: Copy> Copy for Conf<T> {}
186
187impl<T> From<T> for Conf<T> {
188 fn from(contents: T) -> Self {
189 Self::new(contents, MAX_CONFIDENCE)
190 }
191}
192
193impl Conf<&'_ Type> {
194 pub(crate) fn into_raw(value: Self) -> BNTypeWithConfidence {
195 BNTypeWithConfidence {
196 type_: value.contents.handle,
197 confidence: value.confidence,
198 }
199 }
200}
201
202impl Conf<Ref<Type>> {
203 pub(crate) fn from_raw(value: &BNTypeWithConfidence) -> Self {
204 Self::new(
205 unsafe { Type::from_raw(value.type_) }.to_owned(),
206 value.confidence,
207 )
208 }
209
210 pub(crate) fn from_owned_raw(value: BNTypeWithConfidence) -> Self {
211 let owned = Self::from_raw(&value);
212 Self::free_raw(value);
213 owned
214 }
215
216 pub(crate) fn into_raw(value: Self) -> BNTypeWithConfidence {
217 BNTypeWithConfidence {
218 type_: unsafe { Ref::into_raw(value.contents) }.handle,
219 confidence: value.confidence,
220 }
221 }
222
223 pub(crate) fn free_raw(value: BNTypeWithConfidence) {
224 let _ = unsafe { Type::ref_from_raw(value.type_) };
225 }
226}
227
228impl Conf<Ref<CoreCallingConvention>> {
229 pub(crate) fn from_raw(value: &BNCallingConventionWithConfidence) -> Self {
230 let arch = unsafe {
231 CoreArchitecture::from_raw(BNGetCallingConventionArchitecture(value.convention))
232 };
233 Self::new(
234 unsafe { CoreCallingConvention::from_raw(value.convention, arch).to_owned() },
235 value.confidence,
236 )
237 }
238
239 pub(crate) fn from_owned_raw(value: BNCallingConventionWithConfidence) -> Self {
240 let owned = Self::from_raw(&value);
241 Self::free_raw(value);
242 owned
243 }
244}
245
246impl Conf<Ref<CoreCallingConvention>> {
247 pub(crate) fn into_raw(value: Self) -> BNCallingConventionWithConfidence {
248 BNCallingConventionWithConfidence {
249 convention: unsafe { Ref::into_raw(value.contents) }.handle,
250 confidence: value.confidence,
251 }
252 }
253
254 pub(crate) fn into_owned_raw(value: &Self) -> BNCallingConventionWithConfidence {
255 BNCallingConventionWithConfidence {
256 convention: value.contents.handle,
257 confidence: value.confidence,
258 }
259 }
260
261 pub(crate) fn free_raw(value: BNCallingConventionWithConfidence) {
262 let arch = unsafe {
263 CoreArchitecture::from_raw(BNGetCallingConventionArchitecture(value.convention))
264 };
265 let _ = unsafe { CoreCallingConvention::ref_from_raw(value.convention, arch) };
266 }
267}
268
269impl From<BNBoolWithConfidence> for Conf<bool> {
270 fn from(bool_with_confidence: BNBoolWithConfidence) -> Self {
271 Self::new(bool_with_confidence.value, bool_with_confidence.confidence)
272 }
273}
274
275impl From<BNOffsetWithConfidence> for Conf<i64> {
276 fn from(offset_with_confidence: BNOffsetWithConfidence) -> Self {
277 Self::new(
278 offset_with_confidence.value,
279 offset_with_confidence.confidence,
280 )
281 }
282}
283
284impl From<BNInlineDuringAnalysisWithConfidence> for Conf<BNInlineDuringAnalysis> {
285 fn from(inline_with_confidence: BNInlineDuringAnalysisWithConfidence) -> Self {
286 Self::new(
287 inline_with_confidence.value,
288 inline_with_confidence.confidence,
289 )
290 }
291}
292
293impl From<Conf<bool>> for BNBoolWithConfidence {
294 fn from(conf: Conf<bool>) -> Self {
295 Self {
296 value: conf.contents,
297 confidence: conf.confidence,
298 }
299 }
300}
301
302impl From<Conf<i64>> for BNOffsetWithConfidence {
303 fn from(conf: Conf<i64>) -> Self {
304 Self {
305 value: conf.contents,
306 confidence: conf.confidence,
307 }
308 }
309}
310
311impl From<Conf<BNInlineDuringAnalysis>> for BNInlineDuringAnalysisWithConfidence {
312 fn from(conf: Conf<BNInlineDuringAnalysis>) -> Self {
313 Self {
314 value: conf.contents,
315 confidence: conf.confidence,
316 }
317 }
318}