binaryninja/
repository.rs1mod manager;
4mod plugin;
5
6use std::ffi::c_char;
7use std::fmt::Debug;
8use std::path::{Path, PathBuf};
9use std::ptr::NonNull;
10
11use binaryninjacore_sys::*;
12
13use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
14use crate::string::{BnString, IntoCStr};
15
16pub use manager::RepositoryManager;
17pub use plugin::{
18 Extension, ExtensionVersion, ExtensionVersionPlatform, PluginDependencyConflict,
19 PluginDependencyConflictStatus, PluginDependencyRequirement,
20};
21
22pub type PluginType = BNPluginType;
23pub type PluginStatus = BNPluginStatus;
24
25#[repr(transparent)]
26pub struct Repository {
27 handle: NonNull<BNRepository>,
28}
29
30impl Repository {
31 pub(crate) unsafe fn from_raw(handle: NonNull<BNRepository>) -> Self {
32 Self { handle }
33 }
34
35 pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNRepository>) -> Ref<Self> {
36 Ref::new(Self { handle })
37 }
38
39 pub fn url(&self) -> String {
41 let result = unsafe { BNRepositoryGetUrl(self.handle.as_ptr()) };
42 assert!(!result.is_null());
43 unsafe { BnString::into_string(result as *mut c_char) }
44 }
45
46 pub fn path(&self) -> PathBuf {
48 let result = unsafe { BNRepositoryGetRepoPath(self.handle.as_ptr()) };
49 assert!(!result.is_null());
50 let result_str = unsafe { BnString::into_string(result as *mut c_char) };
51 PathBuf::from(result_str)
52 }
53
54 pub fn plugins(&self) -> Array<Extension> {
56 let mut count = 0;
57 let result = unsafe { BNRepositoryGetPlugins(self.handle.as_ptr(), &mut count) };
58 assert!(!result.is_null());
59 unsafe { Array::new(result, count, ()) }
60 }
61
62 pub fn plugin_by_path(&self, path: &Path) -> Option<Ref<Extension>> {
63 let path = path.to_cstr();
64 let result = unsafe { BNRepositoryGetPluginByPath(self.handle.as_ptr(), path.as_ptr()) };
65 NonNull::new(result).map(|h| unsafe { Extension::ref_from_raw(h) })
66 }
67
68 pub fn full_path(&self) -> PathBuf {
70 let result = unsafe { BNRepositoryGetPluginsPath(self.handle.as_ptr()) };
71 assert!(!result.is_null());
72 let result_str = unsafe { BnString::into_string(result as *mut c_char) };
73 PathBuf::from(result_str)
74 }
75}
76
77impl Debug for Repository {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 f.debug_struct("Repository")
80 .field("url", &self.url())
81 .field("path", &self.path())
82 .field("full_path", &self.full_path())
83 .field("plugins", &self.plugins().to_vec())
84 .finish()
85 }
86}
87
88impl ToOwned for Repository {
89 type Owned = Ref<Self>;
90
91 fn to_owned(&self) -> Self::Owned {
92 unsafe { <Self as RefCountable>::inc_ref(self) }
93 }
94}
95
96unsafe impl RefCountable for Repository {
97 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
98 Self::ref_from_raw(NonNull::new(BNNewRepositoryReference(handle.handle.as_ptr())).unwrap())
99 }
100
101 unsafe fn dec_ref(handle: &Self) {
102 BNFreeRepository(handle.handle.as_ptr())
103 }
104}
105
106impl CoreArrayProvider for Repository {
107 type Raw = *mut BNRepository;
108 type Context = ();
109 type Wrapped<'a> = Guard<'a, Self>;
110}
111
112unsafe impl CoreArrayProviderInner for Repository {
113 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
114 BNFreeRepositoryManagerRepositoriesList(raw)
115 }
116
117 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
118 Guard::new(Self::from_raw(NonNull::new(*raw).unwrap()), context)
119 }
120}
121
122impl CoreArrayProvider for PluginType {
123 type Raw = BNPluginType;
124 type Context = ();
125 type Wrapped<'a> = Self;
126}
127
128unsafe impl CoreArrayProviderInner for PluginType {
129 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
130 BNFreePluginTypes(raw)
131 }
132
133 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
134 *raw
135 }
136}