1use crate::rc::{Guard, RefCountable};
2use crate::types::TypeContainer;
3use crate::{
4 architecture::CoreArchitecture,
5 metadata::Metadata,
6 platform::Platform,
7 rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref},
8 string::{BnString, IntoCStr},
9 types::{QualifiedName, QualifiedNameAndType, Type},
10};
11use binaryninjacore_sys::*;
12use std::fmt::{Debug, Formatter};
13use std::hash::{Hash, Hasher};
14use std::path::Path;
15use std::ptr::NonNull;
16
17#[allow(unused_imports)]
19use crate::binary_view::BinaryView;
20
21#[repr(transparent)]
32pub struct TypeLibrary {
33 handle: NonNull<BNTypeLibrary>,
34}
35
36impl TypeLibrary {
37 pub(crate) unsafe fn from_raw(handle: NonNull<BNTypeLibrary>) -> Self {
38 Self { handle }
39 }
40
41 pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNTypeLibrary>) -> Ref<Self> {
42 Ref::new(Self { handle })
43 }
44
45 #[allow(clippy::mut_from_ref)]
46 pub(crate) unsafe fn as_raw(&self) -> &mut BNTypeLibrary {
47 &mut *self.handle.as_ptr()
48 }
49
50 pub fn duplicate(&self) -> Ref<Self> {
56 unsafe { Self::ref_from_raw(NonNull::new(BNDuplicateTypeLibrary(self.as_raw())).unwrap()) }
57 }
58
59 pub fn new(arch: CoreArchitecture, name: &str) -> Ref<TypeLibrary> {
61 let name = name.to_cstr();
62 let new_lib = unsafe { BNNewTypeLibrary(arch.handle, name.as_ptr()) };
63 unsafe { TypeLibrary::ref_from_raw(NonNull::new(new_lib).unwrap()) }
64 }
65
66 pub fn all(arch: CoreArchitecture) -> Array<TypeLibrary> {
67 let mut count = 0;
68 let result = unsafe { BNGetArchitectureTypeLibraries(arch.handle, &mut count) };
69 assert!(!result.is_null());
70 unsafe { Array::new(result, count, ()) }
71 }
72
73 pub fn load_from_file(path: &Path) -> Option<Ref<TypeLibrary>> {
77 let path = path.to_cstr();
78 let handle = unsafe { BNLoadTypeLibraryFromFile(path.as_ptr()) };
79 NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
80 }
81
82 pub fn write_to_file(&self, path: &Path) -> bool {
86 let path = path.to_cstr();
87 unsafe { BNWriteTypeLibraryToFile(self.as_raw(), path.as_ptr()) }
88 }
89
90 pub fn decompress_to_file(&self, output_path: &Path) -> bool {
92 let path = output_path.to_cstr();
93 unsafe { BNTypeLibraryDecompressToFile(self.handle.as_ptr(), path.as_ptr()) }
94 }
95
96 pub fn from_name(arch: CoreArchitecture, name: &str) -> Option<Ref<TypeLibrary>> {
103 let name = name.to_cstr();
104 let handle = unsafe { BNLookupTypeLibraryByName(arch.handle, name.as_ptr()) };
105 NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
106 }
107
108 pub fn from_guid(arch: CoreArchitecture, guid: &str) -> Option<Ref<TypeLibrary>> {
113 let guid = guid.to_cstr();
114 let handle = unsafe { BNLookupTypeLibraryByGuid(arch.handle, guid.as_ptr()) };
115 NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
116 }
117
118 pub fn arch(&self) -> CoreArchitecture {
123 let arch = unsafe { BNGetTypeLibraryArchitecture(self.as_raw()) };
124 assert!(!arch.is_null());
125 unsafe { CoreArchitecture::from_raw(arch) }
126 }
127
128 pub fn name(&self) -> String {
131 let result = unsafe { BNGetTypeLibraryName(self.as_raw()) };
132 assert!(!result.is_null());
133 unsafe { BnString::into_string(result) }
134 }
135
136 pub fn set_name(&self, value: &str) {
138 let value = value.to_cstr();
139 unsafe { BNSetTypeLibraryName(self.as_raw(), value.as_ptr()) }
140 }
141
142 pub fn dependency_name(&self) -> String {
148 let result = unsafe { BNGetTypeLibraryDependencyName(self.as_raw()) };
149 assert!(!result.is_null());
150 unsafe { BnString::into_string(result) }
151 }
152
153 pub fn set_dependency_name(&self, value: &str) {
155 let value = value.to_cstr();
156 unsafe { BNSetTypeLibraryDependencyName(self.as_raw(), value.as_ptr()) }
157 }
158
159 pub fn guid(&self) -> String {
161 let result = unsafe { BNGetTypeLibraryGuid(self.as_raw()) };
162 assert!(!result.is_null());
163 unsafe { BnString::into_string(result) }
164 }
165
166 pub fn set_guid(&self, value: &str) {
168 let value = value.to_cstr();
169 unsafe { BNSetTypeLibraryGuid(self.as_raw(), value.as_ptr()) }
170 }
171
172 pub fn alternate_names(&self) -> Array<BnString> {
174 let mut count = 0;
175 let result = unsafe { BNGetTypeLibraryAlternateNames(self.as_raw(), &mut count) };
176 assert!(!result.is_null());
177 unsafe { Array::new(result, count, ()) }
178 }
179
180 pub fn add_alternate_name(&self, value: &str) {
182 let value = value.to_cstr();
183 unsafe { BNAddTypeLibraryAlternateName(self.as_raw(), value.as_ptr()) }
184 }
185
186 pub fn platform_names(&self) -> Array<BnString> {
191 let mut count = 0;
192 let result = unsafe { BNGetTypeLibraryPlatforms(self.as_raw(), &mut count) };
193 assert!(!result.is_null());
194 unsafe { Array::new(result, count, ()) }
195 }
196
197 pub fn add_platform(&self, plat: &Platform) {
204 unsafe { BNAddTypeLibraryPlatform(self.as_raw(), plat.handle) }
205 }
206
207 pub fn clear_platforms(&self) {
209 unsafe { BNClearTypeLibraryPlatforms(self.as_raw()) }
210 }
211
212 pub fn finalize(&self) -> bool {
215 unsafe { BNFinalizeTypeLibrary(self.as_raw()) }
216 }
217
218 pub fn register(&self) {
220 unsafe { BNRegisterTypeLibrary(self.as_raw()) }
221 }
222
223 pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
225 let key = key.to_cstr();
226 let result = unsafe { BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ptr()) };
227 (!result.is_null()).then(|| unsafe { Metadata::ref_from_raw(result) })
228 }
229
230 pub fn store_metadata(&self, key: &str, md: &Metadata) {
235 let key = key.to_cstr();
236 unsafe { BNTypeLibraryStoreMetadata(self.as_raw(), key.as_ptr(), md.handle) }
237 }
238
239 pub fn remove_metadata(&self, key: &str) {
241 let key = key.to_cstr();
242 unsafe { BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ptr()) }
243 }
244
245 pub fn metadata(&self) -> Ref<Metadata> {
247 let md_handle = unsafe { BNTypeLibraryGetMetadata(self.as_raw()) };
248 assert!(!md_handle.is_null());
249 unsafe { Metadata::ref_from_raw(md_handle) }
250 }
251
252 pub fn type_container(&self) -> TypeContainer {
253 let result = unsafe { BNGetTypeLibraryTypeContainer(self.as_raw()) };
254 unsafe { TypeContainer::from_raw(NonNull::new(result).unwrap()) }
255 }
256
257 pub fn add_named_object(&self, name: QualifiedName, type_: &Type) {
265 let mut raw_name = QualifiedName::into_raw(name);
266 unsafe { BNAddTypeLibraryNamedObject(self.as_raw(), &mut raw_name, type_.handle) }
267 QualifiedName::free_raw(raw_name);
268 }
269
270 pub fn remove_named_object(&self, name: QualifiedName) {
271 let mut raw_name = QualifiedName::into_raw(name);
272 unsafe { BNRemoveTypeLibraryNamedObject(self.as_raw(), &mut raw_name) }
273 QualifiedName::free_raw(raw_name);
274 }
275
276 pub fn add_named_type(&self, name: QualifiedName, type_: &Type) {
284 let mut raw_name = QualifiedName::into_raw(name);
285 unsafe { BNAddTypeLibraryNamedType(self.as_raw(), &mut raw_name, type_.handle) }
286 QualifiedName::free_raw(raw_name);
287 }
288
289 pub fn remove_named_type(&self, name: QualifiedName) {
290 let mut raw_name = QualifiedName::into_raw(name);
291 unsafe { BNRemoveTypeLibraryNamedType(self.as_raw(), &mut raw_name) }
292 QualifiedName::free_raw(raw_name);
293 }
294
295 pub fn add_type_source(&self, name: QualifiedName, source: &str) {
300 let source = source.to_cstr();
301 let mut raw_name = QualifiedName::into_raw(name);
302 unsafe { BNAddTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name, source.as_ptr()) }
303 QualifiedName::free_raw(raw_name);
304 }
305
306 pub fn get_named_type_source(&self, name: QualifiedName) -> Option<String> {
308 let mut raw_name = QualifiedName::into_raw(name);
309 let result = unsafe { BNGetTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name) };
310 QualifiedName::free_raw(raw_name);
311 let str = unsafe { BnString::into_string(result) };
312 if str.is_empty() {
313 None
314 } else {
315 Some(str)
316 }
317 }
318
319 pub fn get_named_object(&self, name: QualifiedName) -> Option<Ref<Type>> {
323 let mut raw_name = QualifiedName::into_raw(name);
324 let t = unsafe { BNGetTypeLibraryNamedObject(self.as_raw(), &mut raw_name) };
325 QualifiedName::free_raw(raw_name);
326 (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
327 }
328
329 pub fn get_named_type(&self, name: QualifiedName) -> Option<Ref<Type>> {
333 let mut raw_name = QualifiedName::into_raw(name);
334 let t = unsafe { BNGetTypeLibraryNamedType(self.as_raw(), &mut raw_name) };
335 QualifiedName::free_raw(raw_name);
336 (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
337 }
338
339 pub fn named_objects(&self) -> Array<QualifiedNameAndType> {
341 let mut count = 0;
342 let result = unsafe { BNGetTypeLibraryNamedObjects(self.as_raw(), &mut count) };
343 assert!(!result.is_null());
344 unsafe { Array::new(result, count, ()) }
345 }
346
347 pub fn named_types(&self) -> Array<QualifiedNameAndType> {
349 let mut count = 0;
350 let result = unsafe { BNGetTypeLibraryNamedTypes(self.as_raw(), &mut count) };
351 assert!(!result.is_null());
352 unsafe { Array::new(result, count, ()) }
353 }
354}
355
356impl Debug for TypeLibrary {
357 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
358 f.debug_struct("TypeLibrary")
359 .field("name", &self.name())
360 .field("dependency_name", &self.dependency_name())
361 .field("arch", &self.arch())
362 .field("guid", &self.guid())
363 .field("alternate_names", &self.alternate_names().to_vec())
364 .field("platform_names", &self.platform_names().to_vec())
365 .field("metadata", &self.metadata())
366 .finish()
370 }
371}
372
373impl PartialEq for TypeLibrary {
374 fn eq(&self, other: &Self) -> bool {
375 self.guid() == other.guid()
376 }
377}
378
379impl Eq for TypeLibrary {}
380
381impl Hash for TypeLibrary {
382 fn hash<H: Hasher>(&self, state: &mut H) {
383 self.guid().hash(state);
384 }
385}
386
387unsafe impl RefCountable for TypeLibrary {
388 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
389 Ref::new(Self {
390 handle: NonNull::new(BNNewTypeLibraryReference(handle.handle.as_ptr())).unwrap(),
391 })
392 }
393
394 unsafe fn dec_ref(handle: &Self) {
395 BNFreeTypeLibrary(handle.handle.as_ptr());
396 }
397}
398
399impl ToOwned for TypeLibrary {
400 type Owned = Ref<Self>;
401
402 fn to_owned(&self) -> Self::Owned {
403 unsafe { RefCountable::inc_ref(self) }
404 }
405}
406
407impl CoreArrayProvider for TypeLibrary {
408 type Raw = *mut BNTypeLibrary;
409 type Context = ();
410 type Wrapped<'a> = Guard<'a, Self>;
411}
412
413unsafe impl CoreArrayProviderInner for TypeLibrary {
414 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
415 BNFreeTypeLibraryList(raw, count)
416 }
417
418 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
419 Guard::new(Self::from_raw(NonNull::new(*raw).unwrap()), context)
420 }
421}
422
423unsafe impl Send for TypeLibrary {}
424unsafe impl Sync for TypeLibrary {}