binaryninja/types/
enumeration.rs

1use crate::rc::{Ref, RefCountable};
2use crate::string::{raw_to_string, BnString, IntoCStr};
3use binaryninjacore_sys::*;
4use std::fmt::{Debug, Formatter};
5
6#[derive(PartialEq, Eq, Hash)]
7pub struct EnumerationBuilder {
8    pub(crate) handle: *mut BNEnumerationBuilder,
9}
10
11impl EnumerationBuilder {
12    pub fn new() -> Self {
13        Self {
14            handle: unsafe { BNCreateEnumerationBuilder() },
15        }
16    }
17
18    pub(crate) unsafe fn from_raw(handle: *mut BNEnumerationBuilder) -> Self {
19        Self { handle }
20    }
21
22    pub fn finalize(&self) -> Ref<Enumeration> {
23        unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) }
24    }
25
26    pub fn append(&mut self, name: &str) -> &mut Self {
27        let name = name.to_cstr();
28        unsafe {
29            BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _);
30        }
31        self
32    }
33
34    pub fn insert(&mut self, name: &str, value: u64) -> &mut Self {
35        let name = name.to_cstr();
36        unsafe {
37            BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_ref().as_ptr() as _, value);
38        }
39        self
40    }
41
42    pub fn replace(&mut self, id: usize, name: &str, value: u64) -> &mut Self {
43        let name = name.to_cstr();
44        unsafe {
45            BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value);
46        }
47        self
48    }
49
50    pub fn remove(&mut self, id: usize) -> &mut Self {
51        unsafe {
52            BNRemoveEnumerationBuilderMember(self.handle, id);
53        }
54
55        self
56    }
57
58    pub fn members(&self) -> Vec<EnumerationMember> {
59        unsafe {
60            let mut count = 0;
61            let members_raw_ptr = BNGetEnumerationBuilderMembers(self.handle, &mut count);
62            let members_raw: &[BNEnumerationMember] =
63                std::slice::from_raw_parts(members_raw_ptr, count);
64            let members = members_raw
65                .iter()
66                .map(EnumerationMember::from_raw)
67                .collect();
68            BNFreeEnumerationMemberList(members_raw_ptr, count);
69            members
70        }
71    }
72}
73
74impl Default for EnumerationBuilder {
75    fn default() -> Self {
76        Self::new()
77    }
78}
79
80impl From<&Enumeration> for EnumerationBuilder {
81    fn from(enumeration: &Enumeration) -> Self {
82        unsafe {
83            Self::from_raw(BNCreateEnumerationBuilderFromEnumeration(
84                enumeration.handle,
85            ))
86        }
87    }
88}
89
90impl Drop for EnumerationBuilder {
91    fn drop(&mut self) {
92        unsafe { BNFreeEnumerationBuilder(self.handle) };
93    }
94}
95
96#[derive(PartialEq, Eq, Hash)]
97pub struct Enumeration {
98    pub(crate) handle: *mut BNEnumeration,
99}
100
101impl Enumeration {
102    pub(crate) unsafe fn ref_from_raw(handle: *mut BNEnumeration) -> Ref<Self> {
103        debug_assert!(!handle.is_null());
104        Ref::new(Self { handle })
105    }
106
107    pub fn builder() -> EnumerationBuilder {
108        EnumerationBuilder::new()
109    }
110
111    pub fn members(&self) -> Vec<EnumerationMember> {
112        unsafe {
113            let mut count = 0;
114            let members_raw_ptr = BNGetEnumerationMembers(self.handle, &mut count);
115            debug_assert!(!members_raw_ptr.is_null());
116            let members_raw: &[BNEnumerationMember] =
117                std::slice::from_raw_parts(members_raw_ptr, count);
118            let members = members_raw
119                .iter()
120                .map(EnumerationMember::from_raw)
121                .collect();
122            BNFreeEnumerationMemberList(members_raw_ptr, count);
123            members
124        }
125    }
126}
127
128impl Debug for Enumeration {
129    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
130        f.debug_struct("Enumeration")
131            .field("members", &self.members())
132            .finish()
133    }
134}
135
136unsafe impl RefCountable for Enumeration {
137    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
138        Self::ref_from_raw(BNNewEnumerationReference(handle.handle))
139    }
140
141    unsafe fn dec_ref(handle: &Self) {
142        BNFreeEnumeration(handle.handle);
143    }
144}
145
146impl ToOwned for Enumeration {
147    type Owned = Ref<Self>;
148
149    fn to_owned(&self) -> Self::Owned {
150        unsafe { RefCountable::inc_ref(self) }
151    }
152}
153
154#[derive(Debug, Clone, Hash, PartialEq, Eq)]
155pub struct EnumerationMember {
156    pub name: String,
157    /// The associated constant value for the member.
158    pub value: u64,
159    /// Whether this is the default member for the associated [`Enumeration`].
160    pub default: bool,
161}
162
163impl EnumerationMember {
164    pub(crate) fn from_raw(value: &BNEnumerationMember) -> Self {
165        Self {
166            name: raw_to_string(value.name).unwrap(),
167            value: value.value,
168            default: value.isDefault,
169        }
170    }
171
172    #[allow(unused)]
173    pub(crate) fn from_owned_raw(value: BNEnumerationMember) -> Self {
174        let owned = Self::from_raw(&value);
175        Self::free_raw(value);
176        owned
177    }
178
179    #[allow(unused)]
180    pub(crate) fn into_raw(value: Self) -> BNEnumerationMember {
181        let bn_name = BnString::new(value.name);
182        BNEnumerationMember {
183            name: BnString::into_raw(bn_name),
184            value: value.value,
185            isDefault: value.default,
186        }
187    }
188
189    #[allow(unused)]
190    pub(crate) fn free_raw(value: BNEnumerationMember) {
191        unsafe { BnString::free_raw(value.name) };
192    }
193
194    pub fn new(name: String, value: u64, default: bool) -> Self {
195        Self {
196            name,
197            value,
198            default,
199        }
200    }
201}