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