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, ValueLocation};
7use binaryninjacore_sys::{
8    BNBoolWithConfidence, BNCallingConventionWithConfidence, BNGetCallingConventionArchitecture,
9    BNInlineDuringAnalysis, BNInlineDuringAnalysisWithConfidence, BNOffsetWithConfidence,
10    BNTypeWithConfidence, BNValueLocation, BNValueLocationWithConfidence,
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<ValueLocation> {
229    pub(crate) fn into_rust_raw(value: Self) -> BNValueLocationWithConfidence {
230        BNValueLocationWithConfidence {
231            location: ValueLocation::into_rust_raw(&value.contents),
232            confidence: value.confidence,
233        }
234    }
235
236    pub(crate) fn free_rust_raw(value: BNValueLocationWithConfidence) {
237        ValueLocation::free_rust_raw(value.location);
238    }
239}
240
241impl Conf<Ref<CoreCallingConvention>> {
242    pub(crate) fn from_raw(value: &BNCallingConventionWithConfidence) -> Self {
243        let arch = unsafe {
244            CoreArchitecture::from_raw(BNGetCallingConventionArchitecture(value.convention))
245        };
246        Self::new(
247            unsafe { CoreCallingConvention::from_raw(value.convention, arch).to_owned() },
248            value.confidence,
249        )
250    }
251
252    pub(crate) fn from_owned_raw(value: BNCallingConventionWithConfidence) -> Self {
253        let owned = Self::from_raw(&value);
254        Self::free_raw(value);
255        owned
256    }
257}
258
259impl Conf<Ref<CoreCallingConvention>> {
260    pub(crate) fn into_raw(value: Self) -> BNCallingConventionWithConfidence {
261        BNCallingConventionWithConfidence {
262            convention: unsafe { Ref::into_raw(value.contents) }.handle,
263            confidence: value.confidence,
264        }
265    }
266
267    pub(crate) fn into_owned_raw(value: &Self) -> BNCallingConventionWithConfidence {
268        BNCallingConventionWithConfidence {
269            convention: value.contents.handle,
270            confidence: value.confidence,
271        }
272    }
273
274    pub(crate) fn free_raw(value: BNCallingConventionWithConfidence) {
275        let arch = unsafe {
276            CoreArchitecture::from_raw(BNGetCallingConventionArchitecture(value.convention))
277        };
278        let _ = unsafe { CoreCallingConvention::ref_from_raw(value.convention, arch) };
279    }
280}
281
282impl From<BNBoolWithConfidence> for Conf<bool> {
283    fn from(bool_with_confidence: BNBoolWithConfidence) -> Self {
284        Self::new(bool_with_confidence.value, bool_with_confidence.confidence)
285    }
286}
287
288impl From<BNOffsetWithConfidence> for Conf<i64> {
289    fn from(offset_with_confidence: BNOffsetWithConfidence) -> Self {
290        Self::new(
291            offset_with_confidence.value,
292            offset_with_confidence.confidence,
293        )
294    }
295}
296
297impl From<BNInlineDuringAnalysisWithConfidence> for Conf<BNInlineDuringAnalysis> {
298    fn from(inline_with_confidence: BNInlineDuringAnalysisWithConfidence) -> Self {
299        Self::new(
300            inline_with_confidence.value,
301            inline_with_confidence.confidence,
302        )
303    }
304}
305
306impl From<Conf<bool>> for BNBoolWithConfidence {
307    fn from(conf: Conf<bool>) -> Self {
308        Self {
309            value: conf.contents,
310            confidence: conf.confidence,
311        }
312    }
313}
314
315impl From<Conf<i64>> for BNOffsetWithConfidence {
316    fn from(conf: Conf<i64>) -> Self {
317        Self {
318            value: conf.contents,
319            confidence: conf.confidence,
320        }
321    }
322}
323
324impl From<Conf<BNInlineDuringAnalysis>> for BNInlineDuringAnalysisWithConfidence {
325    fn from(conf: Conf<BNInlineDuringAnalysis>) -> Self {
326        Self {
327            value: conf.contents,
328            confidence: conf.confidence,
329        }
330    }
331}