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#[allow(unused_imports)]
21use crate::binary_view::BinaryViewExt;
22
23#[repr(transparent)]
34pub struct TypeLibrary {
35 handle: NonNull<BNTypeLibrary>,
36}
37
38impl TypeLibrary {
39 pub(crate) unsafe fn from_raw(handle: NonNull<BNTypeLibrary>) -> Self {
40 Self { handle }
41 }
42
43 pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNTypeLibrary>) -> Ref<Self> {
44 Ref::new(Self { handle })
45 }
46
47 #[allow(clippy::mut_from_ref)]
48 pub(crate) unsafe fn as_raw(&self) -> &mut BNTypeLibrary {
49 &mut *self.handle.as_ptr()
50 }
51
52 pub fn duplicate(&self) -> Ref<Self> {
58 unsafe { Self::ref_from_raw(NonNull::new(BNDuplicateTypeLibrary(self.as_raw())).unwrap()) }
59 }
60
61 pub fn new(arch: CoreArchitecture, name: &str) -> Ref<TypeLibrary> {
63 let name = name.to_cstr();
64 let new_lib = unsafe { BNNewTypeLibrary(arch.handle, name.as_ptr()) };
65 unsafe { TypeLibrary::ref_from_raw(NonNull::new(new_lib).unwrap()) }
66 }
67
68 pub fn all(arch: CoreArchitecture) -> Array<TypeLibrary> {
69 let mut count = 0;
70 let result = unsafe { BNGetArchitectureTypeLibraries(arch.handle, &mut count) };
71 assert!(!result.is_null());
72 unsafe { Array::new(result, count, ()) }
73 }
74
75 pub fn load_from_file(path: &Path) -> Option<Ref<TypeLibrary>> {
79 let path = path.to_cstr();
80 let handle = unsafe { BNLoadTypeLibraryFromFile(path.as_ptr()) };
81 NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
82 }
83
84 pub fn write_to_file(&self, path: &Path) -> bool {
88 let path = path.to_cstr();
89 unsafe { BNWriteTypeLibraryToFile(self.as_raw(), path.as_ptr()) }
90 }
91
92 pub fn decompress_to_file(&self, output_path: &Path) -> bool {
94 let path = output_path.to_cstr();
95 unsafe { BNTypeLibraryDecompressToFile(self.handle.as_ptr(), path.as_ptr()) }
96 }
97
98 pub fn from_name(arch: CoreArchitecture, name: &str) -> Option<Ref<TypeLibrary>> {
105 let name = name.to_cstr();
106 let handle = unsafe { BNLookupTypeLibraryByName(arch.handle, name.as_ptr()) };
107 NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
108 }
109
110 pub fn from_guid(arch: CoreArchitecture, guid: &str) -> Option<Ref<TypeLibrary>> {
115 let guid = guid.to_cstr();
116 let handle = unsafe { BNLookupTypeLibraryByGuid(arch.handle, guid.as_ptr()) };
117 NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
118 }
119
120 pub fn arch(&self) -> CoreArchitecture {
125 let arch = unsafe { BNGetTypeLibraryArchitecture(self.as_raw()) };
126 assert!(!arch.is_null());
127 unsafe { CoreArchitecture::from_raw(arch) }
128 }
129
130 pub fn name(&self) -> String {
133 let result = unsafe { BNGetTypeLibraryName(self.as_raw()) };
134 assert!(!result.is_null());
135 unsafe { BnString::into_string(result) }
136 }
137
138 pub fn set_name(&self, value: &str) {
140 let value = value.to_cstr();
141 unsafe { BNSetTypeLibraryName(self.as_raw(), value.as_ptr()) }
142 }
143
144 pub fn dependency_name(&self) -> String {
150 let result = unsafe { BNGetTypeLibraryDependencyName(self.as_raw()) };
151 assert!(!result.is_null());
152 unsafe { BnString::into_string(result) }
153 }
154
155 pub fn set_dependency_name(&self, value: &str) {
157 let value = value.to_cstr();
158 unsafe { BNSetTypeLibraryDependencyName(self.as_raw(), value.as_ptr()) }
159 }
160
161 pub fn guid(&self) -> String {
163 let result = unsafe { BNGetTypeLibraryGuid(self.as_raw()) };
164 assert!(!result.is_null());
165 unsafe { BnString::into_string(result) }
166 }
167
168 pub fn set_guid(&self, value: &str) {
170 let value = value.to_cstr();
171 unsafe { BNSetTypeLibraryGuid(self.as_raw(), value.as_ptr()) }
172 }
173
174 pub fn alternate_names(&self) -> Array<BnString> {
176 let mut count = 0;
177 let result = unsafe { BNGetTypeLibraryAlternateNames(self.as_raw(), &mut count) };
178 assert!(!result.is_null());
179 unsafe { Array::new(result, count, ()) }
180 }
181
182 pub fn add_alternate_name(&self, value: &str) {
184 let value = value.to_cstr();
185 unsafe { BNAddTypeLibraryAlternateName(self.as_raw(), value.as_ptr()) }
186 }
187
188 pub fn platform_names(&self) -> Array<BnString> {
193 let mut count = 0;
194 let result = unsafe { BNGetTypeLibraryPlatforms(self.as_raw(), &mut count) };
195 assert!(!result.is_null());
196 unsafe { Array::new(result, count, ()) }
197 }
198
199 pub fn add_platform(&self, plat: &Platform) {
206 unsafe { BNAddTypeLibraryPlatform(self.as_raw(), plat.handle) }
207 }
208
209 pub fn clear_platforms(&self) {
211 unsafe { BNClearTypeLibraryPlatforms(self.as_raw()) }
212 }
213
214 pub fn finalize(&self) -> bool {
217 unsafe { BNFinalizeTypeLibrary(self.as_raw()) }
218 }
219
220 pub fn register(&self) {
222 unsafe { BNRegisterTypeLibrary(self.as_raw()) }
223 }
224
225 pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
227 let key = key.to_cstr();
228 let result = unsafe { BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ptr()) };
229 (!result.is_null()).then(|| unsafe { Metadata::ref_from_raw(result) })
230 }
231
232 pub fn store_metadata(&self, key: &str, md: &Metadata) {
237 let key = key.to_cstr();
238 unsafe { BNTypeLibraryStoreMetadata(self.as_raw(), key.as_ptr(), md.handle) }
239 }
240
241 pub fn remove_metadata(&self, key: &str) {
243 let key = key.to_cstr();
244 unsafe { BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ptr()) }
245 }
246
247 pub fn metadata(&self) -> Ref<Metadata> {
249 let md_handle = unsafe { BNTypeLibraryGetMetadata(self.as_raw()) };
250 assert!(!md_handle.is_null());
251 unsafe { Metadata::ref_from_raw(md_handle) }
252 }
253
254 pub fn type_container(&self) -> TypeContainer {
255 let result = unsafe { BNGetTypeLibraryTypeContainer(self.as_raw()) };
256 unsafe { TypeContainer::from_raw(NonNull::new(result).unwrap()) }
257 }
258
259 pub fn add_named_object(&self, name: QualifiedName, type_: &Type) {
267 let mut raw_name = QualifiedName::into_raw(name);
268 unsafe { BNAddTypeLibraryNamedObject(self.as_raw(), &mut raw_name, type_.handle) }
269 QualifiedName::free_raw(raw_name);
270 }
271
272 pub fn remove_named_object(&self, name: QualifiedName) {
273 let mut raw_name = QualifiedName::into_raw(name);
274 unsafe { BNRemoveTypeLibraryNamedObject(self.as_raw(), &mut raw_name) }
275 QualifiedName::free_raw(raw_name);
276 }
277
278 pub fn add_named_type(&self, name: QualifiedName, type_: &Type) {
286 let mut raw_name = QualifiedName::into_raw(name);
287 unsafe { BNAddTypeLibraryNamedType(self.as_raw(), &mut raw_name, type_.handle) }
288 QualifiedName::free_raw(raw_name);
289 }
290
291 pub fn remove_named_type(&self, name: QualifiedName) {
292 let mut raw_name = QualifiedName::into_raw(name);
293 unsafe { BNRemoveTypeLibraryNamedType(self.as_raw(), &mut raw_name) }
294 QualifiedName::free_raw(raw_name);
295 }
296
297 pub fn add_type_source(&self, name: QualifiedName, source: &str) {
302 let source = source.to_cstr();
303 let mut raw_name = QualifiedName::into_raw(name);
304 unsafe { BNAddTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name, source.as_ptr()) }
305 QualifiedName::free_raw(raw_name);
306 }
307
308 pub fn get_named_type_source(&self, name: QualifiedName) -> Option<String> {
310 let mut raw_name = QualifiedName::into_raw(name);
311 let result = unsafe { BNGetTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name) };
312 QualifiedName::free_raw(raw_name);
313 let str = unsafe { BnString::into_string(result) };
314 if str.is_empty() {
315 None
316 } else {
317 Some(str)
318 }
319 }
320
321 pub fn get_named_object(&self, name: QualifiedName) -> Option<Ref<Type>> {
325 let mut raw_name = QualifiedName::into_raw(name);
326 let t = unsafe { BNGetTypeLibraryNamedObject(self.as_raw(), &mut raw_name) };
327 QualifiedName::free_raw(raw_name);
328 (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
329 }
330
331 pub fn get_named_type(&self, name: QualifiedName) -> Option<Ref<Type>> {
335 let mut raw_name = QualifiedName::into_raw(name);
336 let t = unsafe { BNGetTypeLibraryNamedType(self.as_raw(), &mut raw_name) };
337 QualifiedName::free_raw(raw_name);
338 (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
339 }
340
341 pub fn named_objects(&self) -> Array<QualifiedNameAndType> {
343 let mut count = 0;
344 let result = unsafe { BNGetTypeLibraryNamedObjects(self.as_raw(), &mut count) };
345 assert!(!result.is_null());
346 unsafe { Array::new(result, count, ()) }
347 }
348
349 pub fn named_types(&self) -> Array<QualifiedNameAndType> {
351 let mut count = 0;
352 let result = unsafe { BNGetTypeLibraryNamedTypes(self.as_raw(), &mut count) };
353 assert!(!result.is_null());
354 unsafe { Array::new(result, count, ()) }
355 }
356}
357
358impl Debug for TypeLibrary {
359 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
360 f.debug_struct("TypeLibrary")
361 .field("name", &self.name())
362 .field("dependency_name", &self.dependency_name())
363 .field("arch", &self.arch())
364 .field("guid", &self.guid())
365 .field("alternate_names", &self.alternate_names().to_vec())
366 .field("platform_names", &self.platform_names().to_vec())
367 .field("metadata", &self.metadata())
368 .finish()
372 }
373}
374
375impl PartialEq for TypeLibrary {
376 fn eq(&self, other: &Self) -> bool {
377 self.guid() == other.guid()
378 }
379}
380
381impl Eq for TypeLibrary {}
382
383impl Hash for TypeLibrary {
384 fn hash<H: Hasher>(&self, state: &mut H) {
385 self.guid().hash(state);
386 }
387}
388
389unsafe impl RefCountable for TypeLibrary {
390 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
391 Ref::new(Self {
392 handle: NonNull::new(BNNewTypeLibraryReference(handle.handle.as_ptr())).unwrap(),
393 })
394 }
395
396 unsafe fn dec_ref(handle: &Self) {
397 BNFreeTypeLibrary(handle.handle.as_ptr());
398 }
399}
400
401impl ToOwned for TypeLibrary {
402 type Owned = Ref<Self>;
403
404 fn to_owned(&self) -> Self::Owned {
405 unsafe { RefCountable::inc_ref(self) }
406 }
407}
408
409impl CoreArrayProvider for TypeLibrary {
410 type Raw = *mut BNTypeLibrary;
411 type Context = ();
412 type Wrapped<'a> = Guard<'a, Self>;
413}
414
415unsafe impl CoreArrayProviderInner for TypeLibrary {
416 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
417 BNFreeTypeLibraryList(raw, count)
418 }
419
420 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
421 Guard::new(Self::from_raw(NonNull::new(*raw).unwrap()), context)
422 }
423}
424
425unsafe impl Send for TypeLibrary {}
426unsafe impl Sync for TypeLibrary {}