binaryninja/collaboration/
folder.rs1use super::{Remote, RemoteProject};
2use binaryninjacore_sys::*;
3use std::fmt::Debug;
4use std::ptr::NonNull;
5
6use crate::project::folder::ProjectFolder;
7use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
8use crate::string::{BnString, IntoCStr};
9
10#[repr(transparent)]
11pub struct RemoteFolder {
12 pub(crate) handle: NonNull<BNRemoteFolder>,
13}
14
15impl RemoteFolder {
16 pub(crate) unsafe fn from_raw(handle: NonNull<BNRemoteFolder>) -> Self {
17 Self { handle }
18 }
19
20 pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNRemoteFolder>) -> Ref<Self> {
21 Ref::new(Self { handle })
22 }
23
24 pub fn core_folder(&self) -> Result<Ref<ProjectFolder>, ()> {
28 let result = unsafe { BNRemoteFolderGetCoreFolder(self.handle.as_ptr()) };
29 NonNull::new(result)
30 .map(|handle| unsafe { ProjectFolder::ref_from_raw(handle) })
31 .ok_or(())
32 }
33
34 pub fn project(&self) -> Result<Ref<RemoteProject>, ()> {
37 let result = unsafe { BNRemoteFolderGetProject(self.handle.as_ptr()) };
38 NonNull::new(result)
39 .map(|handle| unsafe { RemoteProject::ref_from_raw(handle) })
40 .ok_or(())
41 }
42
43 pub fn remote(&self) -> Result<Ref<Remote>, ()> {
46 let result = unsafe { BNRemoteFolderGetRemote(self.handle.as_ptr()) };
47 NonNull::new(result)
48 .map(|handle| unsafe { Remote::ref_from_raw(handle) })
49 .ok_or(())
50 }
51
52 pub fn parent(&self) -> Result<Option<Ref<RemoteFolder>>, ()> {
56 let project = self.project()?;
57 if !project.has_pulled_folders() {
59 project.pull_folders()?;
60 }
61 let mut parent_handle = std::ptr::null_mut();
62 let success = unsafe { BNRemoteFolderGetParent(self.handle.as_ptr(), &mut parent_handle) };
63 success
64 .then(|| {
65 NonNull::new(parent_handle)
66 .map(|handle| unsafe { RemoteFolder::ref_from_raw(handle) })
67 })
68 .ok_or(())
69 }
70
71 pub fn set_parent(&self, parent: Option<&RemoteFolder>) -> Result<(), ()> {
73 let parent_handle = parent.map_or(std::ptr::null_mut(), |p| p.handle.as_ptr());
74 let success = unsafe { BNRemoteFolderSetParent(self.handle.as_ptr(), parent_handle) };
75 success.then_some(()).ok_or(())
76 }
77
78 pub fn url(&self) -> String {
80 let result = unsafe { BNRemoteFolderGetUrl(self.handle.as_ptr()) };
81 assert!(!result.is_null());
82 unsafe { BnString::into_string(result) }
83 }
84
85 pub fn id(&self) -> String {
87 let result = unsafe { BNRemoteFolderGetId(self.handle.as_ptr()) };
88 assert!(!result.is_null());
89 unsafe { BnString::into_string(result) }
90 }
91
92 pub fn parent_id(&self) -> Option<BnString> {
94 let mut parent_id = std::ptr::null_mut();
95 let have = unsafe { BNRemoteFolderGetParentId(self.handle.as_ptr(), &mut parent_id) };
96 have.then(|| unsafe { BnString::from_raw(parent_id) })
97 }
98
99 pub fn name(&self) -> String {
101 let result = unsafe { BNRemoteFolderGetName(self.handle.as_ptr()) };
102 assert!(!result.is_null());
103 unsafe { BnString::into_string(result) }
104 }
105
106 pub fn set_name(&self, name: &str) -> Result<(), ()> {
108 let name = name.to_cstr();
109 let success = unsafe { BNRemoteFolderSetName(self.handle.as_ptr(), name.as_ptr()) };
110 success.then_some(()).ok_or(())
111 }
112
113 pub fn description(&self) -> String {
115 let result = unsafe { BNRemoteFolderGetDescription(self.handle.as_ptr()) };
116 assert!(!result.is_null());
117 unsafe { BnString::into_string(result) }
118 }
119
120 pub fn set_description(&self, description: &str) -> Result<(), ()> {
122 let description = description.to_cstr();
123 let success =
124 unsafe { BNRemoteFolderSetDescription(self.handle.as_ptr(), description.as_ptr()) };
125 success.then_some(()).ok_or(())
126 }
127}
128
129impl Debug for RemoteFolder {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 f.debug_struct("RemoteFolder")
132 .field("id", &self.id())
133 .field("name", &self.name())
134 .field("description", &self.description())
135 .finish()
136 }
137}
138
139impl PartialEq for RemoteFolder {
140 fn eq(&self, other: &Self) -> bool {
141 self.id() == other.id()
142 }
143}
144
145impl Eq for RemoteFolder {}
146
147impl ToOwned for RemoteFolder {
148 type Owned = Ref<Self>;
149
150 fn to_owned(&self) -> Self::Owned {
151 unsafe { RefCountable::inc_ref(self) }
152 }
153}
154
155unsafe impl Send for RemoteFolder {}
156unsafe impl Sync for RemoteFolder {}
157
158unsafe impl RefCountable for RemoteFolder {
159 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
160 Ref::new(Self {
161 handle: NonNull::new(BNNewRemoteFolderReference(handle.handle.as_ptr())).unwrap(),
162 })
163 }
164
165 unsafe fn dec_ref(handle: &Self) {
166 BNFreeRemoteFolder(handle.handle.as_ptr());
167 }
168}
169
170impl CoreArrayProvider for RemoteFolder {
171 type Raw = *mut BNRemoteFolder;
172 type Context = ();
173 type Wrapped<'a> = Guard<'a, Self>;
174}
175
176unsafe impl CoreArrayProviderInner for RemoteFolder {
177 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
178 BNFreeRemoteFolderList(raw, count)
179 }
180
181 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
182 let raw_ptr = NonNull::new(*raw).unwrap();
183 Guard::new(Self::from_raw(raw_ptr), context)
184 }
185}