binaryninja/
confidence.rs

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
16/// The minimum allowed confidence of any given [`Type`].
17pub const MIN_CONFIDENCE: u8 = u8::MIN;
18
19/// The maximum allowed confidence of any given [`Type`].
20pub const MAX_CONFIDENCE: u8 = u8::MAX;
21
22/// Compatible with the `BNType*WithConfidence` types
23pub struct Conf<T> {
24    pub contents: T,
25    pub confidence: u8,
26}
27
28pub trait ConfMergeable<T, O> {
29    type Result;
30    /// Merge two confidence types' values depending on whichever has higher confidence
31    /// In the event of a tie, the LHS (caller's) value is used.
32    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
58/// Returns best value or LHS on tie
59///
60/// `Conf<T>` + `Conf<T>` → `Conf<T>`
61impl<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
72/// Returns LHS if RHS is None
73///
74/// `Conf<T>` + `Option<Conf<T>>` → `Conf<T>`
75impl<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
85/// Returns RHS if LHS is None
86///
87/// `Option<Conf<T>>` + `Conf<T>` → `Conf<T>`
88impl<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
98/// Returns best non-None value or None
99///
100/// `Option<Conf<T>>` + `Option<Conf<T>>` → `Option<Conf<T>>`
101impl<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}