binaryninja/collaboration/
undo.rs

1use 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    /// Owning Snapshot
32    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    /// Owning File
39    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    /// Owning Project
46    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    /// Owning Remote
53    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    /// Web api endpoint url
60    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    /// Unique id
67    pub fn id(&self) -> RemoteUndoEntryId {
68        RemoteUndoEntryId(unsafe { BNCollaborationUndoEntryGetId(self.handle.as_ptr()) })
69    }
70
71    /// Id of parent undo entry
72    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    /// Undo entry contents data
80    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    /// Parent Undo Entry object
91    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}