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