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<&str> for QualifiedName {
197 fn from(value: &str) -> Self {
198 Self::from(value.to_string())
199 }
200}
201
202impl From<&String> for QualifiedName {
203 fn from(value: &String) -> Self {
204 Self::from(value.to_owned())
205 }
206}
207
208impl From<Cow<'_, str>> for QualifiedName {
209 fn from(value: Cow<'_, str>) -> Self {
210 Self::from(value.to_string())
211 }
212}
213
214impl From<Vec<String>> for QualifiedName {
215 fn from(value: Vec<String>) -> Self {
216 Self::new(value)
217 }
218}
219
220impl From<Vec<&str>> for QualifiedName {
221 fn from(value: Vec<&str>) -> Self {
222 value
223 .iter()
224 .map(ToString::to_string)
225 .collect::<Vec<_>>()
226 .into()
227 }
228}
229
230impl From<QualifiedName> for String {
231 fn from(value: QualifiedName) -> Self {
232 value.to_string()
233 }
234}
235
236impl Index<usize> for QualifiedName {
237 type Output = String;
238
239 fn index(&self, index: usize) -> &Self::Output {
240 &self.items[index]
241 }
242}
243
244impl IndexMut<usize> for QualifiedName {
245 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
246 &mut self.items[index]
247 }
248}
249
250impl Display for QualifiedName {
251 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
252 write!(f, "{}", self.items.join(&self.separator))
253 }
254}
255
256impl CoreArrayProvider for QualifiedName {
257 type Raw = BNQualifiedName;
258 type Context = ();
259 type Wrapped<'a> = Self;
260}
261
262unsafe impl CoreArrayProviderInner for QualifiedName {
263 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
264 BNFreeTypeNameList(raw, count);
265 }
266
267 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
268 QualifiedName::from_raw(raw)
269 }
270}