binaryninja/collaboration/
undo.rs1use crate::collaboration::{Remote, RemoteFile, RemoteProject, RemoteSnapshot};
2use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
3use crate::string::BnString;
4use binaryninjacore_sys::{
5 BNCollaborationFreeIdList, BNCollaborationUndoEntry, BNCollaborationUndoEntryGetData,
6 BNCollaborationUndoEntryGetFile, BNCollaborationUndoEntryGetId,
7 BNCollaborationUndoEntryGetParent, BNCollaborationUndoEntryGetParentId,
8 BNCollaborationUndoEntryGetProject, BNCollaborationUndoEntryGetRemote,
9 BNCollaborationUndoEntryGetSnapshot, BNCollaborationUndoEntryGetUrl,
10 BNFreeCollaborationUndoEntry, BNFreeCollaborationUndoEntryList,
11 BNNewCollaborationUndoEntryReference,
12};
13use std::fmt;
14use std::fmt::{Display, Formatter};
15use std::ptr::NonNull;
16
17#[repr(transparent)]
18pub struct RemoteUndoEntry {
19 handle: NonNull<BNCollaborationUndoEntry>,
20}
21
22impl RemoteUndoEntry {
23 pub(crate) unsafe fn from_raw(handle: NonNull<BNCollaborationUndoEntry>) -> Self {
24 Self { handle }
25 }
26
27 pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNCollaborationUndoEntry>) -> Ref<Self> {
28 Ref::new(Self { handle })
29 }
30
31 pub fn snapshot(&self) -> Result<Ref<RemoteSnapshot>, ()> {
33 let value = unsafe { BNCollaborationUndoEntryGetSnapshot(self.handle.as_ptr()) };
34 let handle = NonNull::new(value).ok_or(())?;
35 Ok(unsafe { RemoteSnapshot::ref_from_raw(handle) })
36 }
37
38 pub fn file(&self) -> Result<Ref<RemoteFile>, ()> {
40 let value = unsafe { BNCollaborationUndoEntryGetFile(self.handle.as_ptr()) };
41 let handle = NonNull::new(value).ok_or(())?;
42 Ok(unsafe { RemoteFile::ref_from_raw(handle) })
43 }
44
45 pub fn project(&self) -> Result<Ref<RemoteProject>, ()> {
47 let value = unsafe { BNCollaborationUndoEntryGetProject(self.handle.as_ptr()) };
48 let handle = NonNull::new(value).ok_or(())?;
49 Ok(unsafe { RemoteProject::ref_from_raw(handle) })
50 }
51
52 pub fn remote(&self) -> Result<Ref<Remote>, ()> {
54 let value = unsafe { BNCollaborationUndoEntryGetRemote(self.handle.as_ptr()) };
55 let handle = NonNull::new(value).ok_or(())?;
56 Ok(unsafe { Remote::ref_from_raw(handle) })
57 }
58
59 pub fn url(&self) -> String {
61 let value = unsafe { BNCollaborationUndoEntryGetUrl(self.handle.as_ptr()) };
62 assert!(!value.is_null());
63 unsafe { BnString::into_string(value) }
64 }
65
66 pub fn id(&self) -> RemoteUndoEntryId {
68 RemoteUndoEntryId(unsafe { BNCollaborationUndoEntryGetId(self.handle.as_ptr()) })
69 }
70
71 pub fn parent_id(&self) -> Option<RemoteUndoEntryId> {
73 let mut value = 0;
74 let success =
75 unsafe { BNCollaborationUndoEntryGetParentId(self.handle.as_ptr(), &mut value) };
76 success.then_some(RemoteUndoEntryId(value))
77 }
78
79 pub fn data(&self) -> Result<BnString, ()> {
81 let mut value = std::ptr::null_mut();
82 let success = unsafe { BNCollaborationUndoEntryGetData(self.handle.as_ptr(), &mut value) };
83 if !success {
84 return Err(());
85 }
86 assert!(!value.is_null());
87 Ok(unsafe { BnString::from_raw(value) })
88 }
89
90 pub fn parent(&self) -> Option<Ref<RemoteUndoEntry>> {
92 let value = unsafe { BNCollaborationUndoEntryGetParent(self.handle.as_ptr()) };
93 NonNull::new(value).map(|handle| unsafe { RemoteUndoEntry::ref_from_raw(handle) })
94 }
95}
96
97impl PartialEq for RemoteUndoEntry {
98 fn eq(&self, other: &Self) -> bool {
99 self.id() == other.id()
100 }
101}
102impl Eq for RemoteUndoEntry {}
103
104impl ToOwned for RemoteUndoEntry {
105 type Owned = Ref<Self>;
106
107 fn to_owned(&self) -> Self::Owned {
108 unsafe { RefCountable::inc_ref(self) }
109 }
110}
111
112unsafe impl RefCountable for RemoteUndoEntry {
113 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
114 Ref::new(Self {
115 handle: NonNull::new(BNNewCollaborationUndoEntryReference(handle.handle.as_ptr()))
116 .unwrap(),
117 })
118 }
119
120 unsafe fn dec_ref(handle: &Self) {
121 BNFreeCollaborationUndoEntry(handle.handle.as_ptr());
122 }
123}
124
125impl CoreArrayProvider for RemoteUndoEntry {
126 type Raw = *mut BNCollaborationUndoEntry;
127 type Context = ();
128 type Wrapped<'a> = Guard<'a, Self>;
129}
130
131unsafe impl CoreArrayProviderInner for RemoteUndoEntry {
132 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
133 BNFreeCollaborationUndoEntryList(raw, count)
134 }
135
136 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
137 let raw_ptr = NonNull::new(*raw).unwrap();
138 Guard::new(Self::from_raw(raw_ptr), context)
139 }
140}
141
142#[repr(transparent)]
143#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
144pub struct RemoteUndoEntryId(pub u64);
145
146impl Display for RemoteUndoEntryId {
147 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
148 f.write_fmt(format_args!("{}", self.0))
149 }
150}
151
152impl CoreArrayProvider for RemoteUndoEntryId {
153 type Raw = u64;
154 type Context = ();
155 type Wrapped<'a> = RemoteUndoEntryId;
156}
157
158unsafe impl CoreArrayProviderInner for RemoteUndoEntryId {
159 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
160 BNCollaborationFreeIdList(raw, count)
161 }
162
163 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
164 RemoteUndoEntryId(*raw)
165 }
166}