binaryninja/
qualified_name.rs1use crate::rc::{CoreArrayProvider, CoreArrayProviderInner};
4use crate::string::{raw_to_string, strings_to_string_list, BnString};
5use binaryninjacore_sys::*;
6use std::borrow::Cow;
7use std::fmt::{Display, Formatter};
8use std::ops::{Index, IndexMut};
9
10#[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
39pub struct QualifiedName {
40 pub separator: String,
42 pub items: Vec<String>,
43}
44
45impl QualifiedName {
46 pub fn from_raw(value: &BNQualifiedName) -> Self {
47 let raw_names = unsafe { std::slice::from_raw_parts(value.name, value.nameCount) };
49 let items = raw_names
50 .iter()
51 .filter_map(|&raw_name| raw_to_string(raw_name as *const _))
52 .collect();
53 let separator = raw_to_string(value.join).unwrap();
54 Self { items, separator }
55 }
56
57 pub fn from_owned_raw(value: BNQualifiedName) -> Self {
58 let result = Self::from_raw(&value);
59 Self::free_raw(value);
60 result
61 }
62
63 pub fn into_raw(value: Self) -> BNQualifiedName {
64 let bn_join = BnString::new(&value.separator);
65 BNQualifiedName {
66 name: strings_to_string_list(&value.items),
68 join: BnString::into_raw(bn_join),
70 nameCount: value.items.len(),
71 }
72 }
73
74 pub fn free_raw(value: BNQualifiedName) {
75 unsafe { BnString::free_raw(value.join) };
76 unsafe { BNFreeStringList(value.name, value.nameCount) };
77 }
78
79 pub fn new<I, S>(items: I) -> Self
81 where
82 I: IntoIterator<Item = S>,
83 S: Into<String>,
84 {
85 Self::new_with_separator(items, "::")
86 }
87
88 pub fn new_with_separator<I, S>(items: I, separator: impl Into<String>) -> Self
90 where
91 I: IntoIterator<Item = S>,
92 S: Into<String>,
93 {
94 let items = items.into_iter().map(Into::into).collect::<Vec<String>>();
95 Self {
96 items,
97 separator: separator.into(),
98 }
99 }
100
101 pub fn with_item(&self, item: impl Into<String>) -> Self {
102 let mut items = self.items.clone();
103 items.push(item.into());
104 Self::new_with_separator(items, self.separator.clone())
105 }
106
107 pub fn push(&mut self, item: String) {
108 self.items.push(item);
109 }
110
111 pub fn pop(&mut self) -> Option<String> {
112 self.items.pop()
113 }
114
115 pub fn insert(&mut self, index: usize, item: String) {
116 if index <= self.items.len() {
117 self.items.insert(index, item);
118 }
119 }
120
121 pub fn split_last(&self) -> Option<(String, QualifiedName)> {
122 self.items.split_last().map(|(a, b)| {
123 (
124 a.to_owned(),
125 QualifiedName::new_with_separator(b.to_vec(), self.separator.clone()),
126 )
127 })
128 }
129
130 pub fn replace(&self, from: &str, to: &str) -> Self {
147 Self {
148 items: self
149 .items
150 .iter()
151 .map(|item| item.replace(from, to))
152 .collect(),
153 separator: self.separator.clone(),
154 }
155 }
156
157 pub fn last(&self) -> Option<&String> {
159 self.items.last()
160 }
161
162 pub fn last_mut(&mut self) -> Option<&mut String> {
164 self.items.last_mut()
165 }
166
167 pub fn len(&self) -> usize {
168 self.items.len()
169 }
170
171 pub fn is_empty(&self) -> bool {
176 self.items.is_empty()
177 }
178}
179
180impl Default for QualifiedName {
181 fn default() -> Self {
182 Self::new(Vec::<String>::new())
183 }
184}
185
186impl From<String> for QualifiedName {
187 fn from(value: String) -> Self {
188 Self {
189 items: vec![value],
190 separator: String::from("::"),
192 }
193 }
194}
195
196impl From<BnString> for QualifiedName {
197 fn from(value: BnString) -> Self {
198 Self {
199 items: vec![value.to_string_lossy().to_string()],
200 separator: String::from("::"),
201 }
202 }
203}
204
205impl From<&str> for QualifiedName {
206 fn from(value: &str) -> Self {
207 Self::from(value.to_string())
208 }
209}
210
211impl From<&String> for QualifiedName {
212 fn from(value: &String) -> Self {
213 Self::from(value.to_owned())
214 }
215}
216
217impl From<Cow<'_, str>> for QualifiedName {
218 fn from(value: Cow<'_, str>) -> Self {
219 Self::from(value.to_string())
220 }
221}
222
223impl From<Vec<String>> for QualifiedName {
224 fn from(value: Vec<String>) -> Self {
225 Self::new(value)
226 }
227}
228
229impl From<Vec<&str>> for QualifiedName {
230 fn from(value: Vec<&str>) -> Self {
231 value
232 .iter()
233 .map(ToString::to_string)
234 .collect::<Vec<_>>()
235 .into()
236 }
237}
238
239impl From<QualifiedName> for String {
240 fn from(value: QualifiedName) -> Self {
241 value.to_string()
242 }
243}
244
245impl Index<usize> for QualifiedName {
246 type Output = String;
247
248 fn index(&self, index: usize) -> &Self::Output {
249 &self.items[index]
250 }
251}
252
253impl IndexMut<usize> for QualifiedName {
254 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
255 &mut self.items[index]
256 }
257}
258
259impl Display for QualifiedName {
260 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
261 write!(f, "{}", self.items.join(&self.separator))
262 }
263}
264
265impl CoreArrayProvider for QualifiedName {
266 type Raw = BNQualifiedName;
267 type Context = ();
268 type Wrapped<'a> = Self;
269}
270
271unsafe impl CoreArrayProviderInner for QualifiedName {
272 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
273 BNFreeTypeNameList(raw, count);
274 }
275
276 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
277 QualifiedName::from_raw(raw)
278 }
279}