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 remove_alternate_name(&self, value: &str) {
188 let value = value.to_cstr();
189 unsafe { BNRemoveTypeLibraryAlternateName(self.as_raw(), value.as_ptr()) }
190 }
191
192 pub fn platform_names(&self) -> Array<BnString> {
197 let mut count = 0;
198 let result = unsafe { BNGetTypeLibraryPlatforms(self.as_raw(), &mut count) };
199 assert!(!result.is_null());
200 unsafe { Array::new(result, count, ()) }
201 }
202
203 pub fn add_platform(&self, plat: &Platform) {
210 unsafe { BNAddTypeLibraryPlatform(self.as_raw(), plat.handle) }
211 }
212
213 pub fn clear_platforms(&self) {
215 unsafe { BNClearTypeLibraryPlatforms(self.as_raw()) }
216 }
217
218 pub fn finalize(&self) -> bool {
221 unsafe { BNFinalizeTypeLibrary(self.as_raw()) }
222 }
223
224 pub fn register(&self) {
226 unsafe { BNRegisterTypeLibrary(self.as_raw()) }
227 }
228
229 pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
231 let key = key.to_cstr();
232 let result = unsafe { BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ptr()) };
233 (!result.is_null()).then(|| unsafe { Metadata::ref_from_raw(result) })
234 }
235
236 pub fn store_metadata(&self, key: &str, md: &Metadata) {
241 let key = key.to_cstr();
242 unsafe { BNTypeLibraryStoreMetadata(self.as_raw(), key.as_ptr(), md.handle) }
243 }
244
245 pub fn remove_metadata(&self, key: &str) {
247 let key = key.to_cstr();
248 unsafe { BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ptr()) }
249 }
250
251 pub fn metadata(&self) -> Ref<Metadata> {
253 let md_handle = unsafe { BNTypeLibraryGetMetadata(self.as_raw()) };
254 assert!(!md_handle.is_null());
255 unsafe { Metadata::ref_from_raw(md_handle) }
256 }
257
258 pub fn type_container(&self) -> TypeContainer {
259 let result = unsafe { BNGetTypeLibraryTypeContainer(self.as_raw()) };
260 unsafe { TypeContainer::from_raw(NonNull::new(result).unwrap()) }
261 }
262
263 pub fn add_named_object(&self, name: QualifiedName, type_: &Type) {
271 let mut raw_name = QualifiedName::into_raw(name);
272 unsafe { BNAddTypeLibraryNamedObject(self.as_raw(), &mut raw_name, type_.handle) }
273 QualifiedName::free_raw(raw_name);
274 }
275
276 pub fn remove_named_object(&self, name: QualifiedName) {
277 let mut raw_name = QualifiedName::into_raw(name);
278 unsafe { BNRemoveTypeLibraryNamedObject(self.as_raw(), &mut raw_name) }
279 QualifiedName::free_raw(raw_name);
280 }
281
282 pub fn add_named_type(&self, name: QualifiedName, type_: &Type) {
290 let mut raw_name = QualifiedName::into_raw(name);
291 unsafe { BNAddTypeLibraryNamedType(self.as_raw(), &mut raw_name, type_.handle) }
292 QualifiedName::free_raw(raw_name);
293 }
294
295 pub fn remove_named_type(&self, name: QualifiedName) {
296 let mut raw_name = QualifiedName::into_raw(name);
297 unsafe { BNRemoveTypeLibraryNamedType(self.as_raw(), &mut raw_name) }
298 QualifiedName::free_raw(raw_name);
299 }
300
301 pub fn add_type_source(&self, name: QualifiedName, source: &str) {
306 let source = source.to_cstr();
307 let mut raw_name = QualifiedName::into_raw(name);
308 unsafe { BNAddTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name, source.as_ptr()) }
309 QualifiedName::free_raw(raw_name);
310 }
311
312 pub fn get_named_type_source(&self, name: QualifiedName) -> Option<String> {
314 let mut raw_name = QualifiedName::into_raw(name);
315 let result = unsafe { BNGetTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name) };
316 QualifiedName::free_raw(raw_name);
317 let str = unsafe { BnString::into_string(result) };
318 if str.is_empty() {
319 None
320 } else {
321 Some(str)
322 }
323 }
324
325 pub fn get_named_object(&self, name: QualifiedName) -> Option<Ref<Type>> {
329 let mut raw_name = QualifiedName::into_raw(name);
330 let t = unsafe { BNGetTypeLibraryNamedObject(self.as_raw(), &mut raw_name) };
331 QualifiedName::free_raw(raw_name);
332 (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
333 }
334
335 pub fn get_named_type(&self, name: QualifiedName) -> Option<Ref<Type>> {
339 let mut raw_name = QualifiedName::into_raw(name);
340 let t = unsafe { BNGetTypeLibraryNamedType(self.as_raw(), &mut raw_name) };
341 QualifiedName::free_raw(raw_name);
342 (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
343 }
344
345 pub fn named_objects(&self) -> Array<QualifiedNameAndType> {
347 let mut count = 0;
348 let result = unsafe { BNGetTypeLibraryNamedObjects(self.as_raw(), &mut count) };
349 assert!(!result.is_null());
350 unsafe { Array::new(result, count, ()) }
351 }
352
353 pub fn named_types(&self) -> Array<QualifiedNameAndType> {
355 let mut count = 0;
356 let result = unsafe { BNGetTypeLibraryNamedTypes(self.as_raw(), &mut count) };
357 assert!(!result.is_null());
358 unsafe { Array::new(result, count, ()) }
359 }
360}
361
362impl Debug for TypeLibrary {
363 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
364 f.debug_struct("TypeLibrary")
365 .field("name", &self.name())
366 .field("dependency_name", &self.dependency_name())
367 .field("arch", &self.arch())
368 .field("guid", &self.guid())
369 .field("alternate_names", &self.alternate_names().to_vec())
370 .field("platform_names", &self.platform_names().to_vec())
371 .field("metadata", &self.metadata())
372 .finish()
376 }
377}
378
379impl PartialEq for TypeLibrary {
380 fn eq(&self, other: &Self) -> bool {
381 self.guid() == other.guid()
382 }
383}
384
385impl Eq for TypeLibrary {}
386
387impl Hash for TypeLibrary {
388 fn hash<H: Hasher>(&self, state: &mut H) {
389 self.guid().hash(state);
390 }
391}
392
393unsafe impl RefCountable for TypeLibrary {
394 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
395 Ref::new(Self {
396 handle: NonNull::new(BNNewTypeLibraryReference(handle.handle.as_ptr())).unwrap(),
397 })
398 }
399
400 unsafe fn dec_ref(handle: &Self) {
401 BNFreeTypeLibrary(handle.handle.as_ptr());
402 }
403}
404
405impl ToOwned for TypeLibrary {
406 type Owned = Ref<Self>;
407
408 fn to_owned(&self) -> Self::Owned {
409 unsafe { RefCountable::inc_ref(self) }
410 }
411}
412
413impl CoreArrayProvider for TypeLibrary {
414 type Raw = *mut BNTypeLibrary;
415 type Context = ();
416 type Wrapped<'a> = Guard<'a, Self>;
417}
418
419unsafe impl CoreArrayProviderInner for TypeLibrary {
420 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
421 BNFreeTypeLibraryList(raw, count)
422 }
423
424 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
425 Guard::new(Self::from_raw(NonNull::new(*raw).unwrap()), context)
426 }
427}
428
429unsafe impl Send for TypeLibrary {}
430unsafe impl Sync for TypeLibrary {}