binaryninja/
repository.rs

1//! Interaction with plugin repositories to install and manage plugins.
2
3mod 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::repository::plugin::RepositoryPlugin;
15use crate::string::{BnString, IntoCStr};
16
17pub use manager::RepositoryManager;
18
19pub type PluginType = BNPluginType;
20pub type PluginStatus = BNPluginStatus;
21
22#[repr(transparent)]
23pub struct Repository {
24    handle: NonNull<BNRepository>,
25}
26
27impl Repository {
28    pub(crate) unsafe fn from_raw(handle: NonNull<BNRepository>) -> Self {
29        Self { handle }
30    }
31
32    pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNRepository>) -> Ref<Self> {
33        Ref::new(Self { handle })
34    }
35
36    /// String URL of the git repository where the plugin repository's are stored
37    pub fn url(&self) -> String {
38        let result = unsafe { BNRepositoryGetUrl(self.handle.as_ptr()) };
39        assert!(!result.is_null());
40        unsafe { BnString::into_string(result as *mut c_char) }
41    }
42
43    /// String local path to store the given plugin repository
44    pub fn path(&self) -> PathBuf {
45        let result = unsafe { BNRepositoryGetRepoPath(self.handle.as_ptr()) };
46        assert!(!result.is_null());
47        let result_str = unsafe { BnString::into_string(result as *mut c_char) };
48        PathBuf::from(result_str)
49    }
50
51    /// List of RepoPlugin objects contained within this repository
52    pub fn plugins(&self) -> Array<RepositoryPlugin> {
53        let mut count = 0;
54        let result = unsafe { BNRepositoryGetPlugins(self.handle.as_ptr(), &mut count) };
55        assert!(!result.is_null());
56        unsafe { Array::new(result, count, ()) }
57    }
58
59    pub fn plugin_by_path(&self, path: &Path) -> Option<Ref<RepositoryPlugin>> {
60        let path = path.to_cstr();
61        let result = unsafe { BNRepositoryGetPluginByPath(self.handle.as_ptr(), path.as_ptr()) };
62        NonNull::new(result).map(|h| unsafe { RepositoryPlugin::ref_from_raw(h) })
63    }
64
65    /// String full path the repository
66    pub fn full_path(&self) -> PathBuf {
67        let result = unsafe { BNRepositoryGetPluginsPath(self.handle.as_ptr()) };
68        assert!(!result.is_null());
69        let result_str = unsafe { BnString::into_string(result as *mut c_char) };
70        PathBuf::from(result_str)
71    }
72}
73
74impl Debug for Repository {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        f.debug_struct("Repository")
77            .field("url", &self.url())
78            .field("path", &self.path())
79            .field("full_path", &self.full_path())
80            .field("plugins", &self.plugins().to_vec())
81            .finish()
82    }
83}
84
85impl ToOwned for Repository {
86    type Owned = Ref<Self>;
87
88    fn to_owned(&self) -> Self::Owned {
89        unsafe { <Self as RefCountable>::inc_ref(self) }
90    }
91}
92
93unsafe impl RefCountable for Repository {
94    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
95        Self::ref_from_raw(NonNull::new(BNNewRepositoryReference(handle.handle.as_ptr())).unwrap())
96    }
97
98    unsafe fn dec_ref(handle: &Self) {
99        BNFreeRepository(handle.handle.as_ptr())
100    }
101}
102
103impl CoreArrayProvider for Repository {
104    type Raw = *mut BNRepository;
105    type Context = ();
106    type Wrapped<'a> = Guard<'a, Self>;
107}
108
109unsafe impl CoreArrayProviderInner for Repository {
110    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
111        BNFreeRepositoryManagerRepositoriesList(raw)
112    }
113
114    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
115        Guard::new(Self::from_raw(NonNull::new(*raw).unwrap()), context)
116    }
117}
118
119impl CoreArrayProvider for PluginType {
120    type Raw = BNPluginType;
121    type Context = ();
122    type Wrapped<'a> = Self;
123}
124
125unsafe impl CoreArrayProviderInner for PluginType {
126    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
127        BNFreePluginTypes(raw)
128    }
129
130    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
131        *raw
132    }
133}