binaryninja/project/
folder.rs1use crate::progress::{NoProgressCallback, ProgressCallback};
2use crate::project::file::ProjectFile;
3use crate::project::Project;
4use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
5use crate::string::{BnString, IntoCStr};
6use binaryninjacore_sys::{
7 BNFreeProjectFolder, BNFreeProjectFolderList, BNNewProjectFolderReference, BNProjectFolder,
8 BNProjectFolderExport, BNProjectFolderGetDescription, BNProjectFolderGetFiles,
9 BNProjectFolderGetId, BNProjectFolderGetName, BNProjectFolderGetParent,
10 BNProjectFolderGetProject, BNProjectFolderSetDescription, BNProjectFolderSetName,
11 BNProjectFolderSetParent,
12};
13use std::ffi::c_void;
14use std::fmt::Debug;
15use std::path::Path;
16use std::ptr::{null_mut, NonNull};
17
18#[repr(transparent)]
19pub struct ProjectFolder {
20 pub(crate) handle: NonNull<BNProjectFolder>,
21}
22
23impl ProjectFolder {
24 pub(crate) unsafe fn from_raw(handle: NonNull<BNProjectFolder>) -> Self {
25 Self { handle }
26 }
27
28 pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNProjectFolder>) -> Ref<Self> {
29 Ref::new(Self { handle })
30 }
31
32 pub fn project(&self) -> Ref<Project> {
34 unsafe {
35 Project::ref_from_raw(
36 NonNull::new(BNProjectFolderGetProject(self.handle.as_ptr())).unwrap(),
37 )
38 }
39 }
40
41 pub fn id(&self) -> String {
43 unsafe { BnString::into_string(BNProjectFolderGetId(self.handle.as_ptr())) }
44 }
45
46 pub fn name(&self) -> String {
48 unsafe { BnString::into_string(BNProjectFolderGetName(self.handle.as_ptr())) }
49 }
50
51 pub fn set_name(&self, value: &str) -> bool {
53 let value_raw = value.to_cstr();
54 unsafe { BNProjectFolderSetName(self.handle.as_ptr(), value_raw.as_ptr()) }
55 }
56
57 pub fn description(&self) -> String {
59 unsafe { BnString::into_string(BNProjectFolderGetDescription(self.handle.as_ptr())) }
60 }
61
62 pub fn set_description(&self, value: &str) -> bool {
64 let value_raw = value.to_cstr();
65 unsafe { BNProjectFolderSetDescription(self.handle.as_ptr(), value_raw.as_ptr()) }
66 }
67
68 pub fn parent(&self) -> Option<Ref<ProjectFolder>> {
70 let result = unsafe { BNProjectFolderGetParent(self.handle.as_ptr()) };
71 NonNull::new(result).map(|handle| unsafe { ProjectFolder::ref_from_raw(handle) })
72 }
73
74 pub fn set_folder(&self, folder: Option<&ProjectFolder>) -> bool {
76 let folder_handle = folder.map(|x| x.handle.as_ptr()).unwrap_or(null_mut());
77 unsafe { BNProjectFolderSetParent(self.handle.as_ptr(), folder_handle) }
78 }
79
80 pub fn export(&self, dest: &Path) -> bool {
84 self.export_with_progress(dest, NoProgressCallback)
85 }
86
87 pub fn export_with_progress<P>(&self, dest: &Path, mut progress: P) -> bool
92 where
93 P: ProgressCallback,
94 {
95 let dest_raw = dest.to_cstr();
96 unsafe {
97 BNProjectFolderExport(
98 self.handle.as_ptr(),
99 dest_raw.as_ptr(),
100 &mut progress as *mut P as *mut c_void,
101 Some(P::cb_progress_callback),
102 )
103 }
104 }
105
106 pub fn files(&self) -> Array<ProjectFile> {
108 let mut count = 0;
109 let result = unsafe { BNProjectFolderGetFiles(self.handle.as_ptr(), &mut count) };
110 unsafe { Array::new(result, count, ()) }
111 }
112}
113
114impl PartialEq for ProjectFolder {
115 fn eq(&self, other: &Self) -> bool {
116 self.id() == other.id()
117 }
118}
119
120impl Debug for ProjectFolder {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 f.debug_struct("ProjectFolder")
123 .field("id", &self.id())
124 .field("name", &self.name())
125 .field("description", &self.description())
126 .finish()
127 }
128}
129
130unsafe impl Send for ProjectFolder {}
131unsafe impl Sync for ProjectFolder {}
132
133impl ToOwned for ProjectFolder {
134 type Owned = Ref<Self>;
135
136 fn to_owned(&self) -> Self::Owned {
137 unsafe { RefCountable::inc_ref(self) }
138 }
139}
140
141unsafe impl RefCountable for ProjectFolder {
142 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
143 Ref::new(Self {
144 handle: NonNull::new(BNNewProjectFolderReference(handle.handle.as_ptr())).unwrap(),
145 })
146 }
147
148 unsafe fn dec_ref(handle: &Self) {
149 BNFreeProjectFolder(handle.handle.as_ptr());
150 }
151}
152
153impl CoreArrayProvider for ProjectFolder {
154 type Raw = *mut BNProjectFolder;
155 type Context = ();
156 type Wrapped<'a> = Guard<'a, Self>;
157}
158
159unsafe impl CoreArrayProviderInner for ProjectFolder {
160 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
161 BNFreeProjectFolderList(raw, count)
162 }
163
164 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
165 let raw_ptr = NonNull::new(*raw).unwrap();
166 Guard::new(Self::from_raw(raw_ptr), context)
167 }
168}