Skip to content

Commit 652a1d5

Browse files
committed
Update collaboration API
Makes collaboration more in line with the refactor. Still a lot of work to do. Namely still need: - Proper errors - _with_opts functions - More ergonomic api - Better connection procedure - Updated documentation - A LOT of unit tests - An example - Typed id's for everything (i dont want BnString as the id!!!) - NEED to refactor the progress callbacks into the new progress api, but we should pull in some of the stuff the collab progress has - Elimination of apis that are dumb helpers
1 parent 048cf6b commit 652a1d5

File tree

19 files changed

+1228
-1073
lines changed

19 files changed

+1228
-1073
lines changed

rust/src/collaboration/mod.rs renamed to rust/src/collaboration.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
mod changeset;
2-
mod databasesync;
32
mod file;
43
mod folder;
54
mod group;
@@ -8,10 +7,10 @@ mod permission;
87
mod project;
98
mod remote;
109
mod snapshot;
10+
mod sync;
1111
mod user;
1212

1313
pub use changeset::*;
14-
pub use databasesync::*;
1514
pub use file::*;
1615
pub use folder::*;
1716
pub use group::*;
@@ -20,27 +19,28 @@ pub use permission::*;
2019
pub use project::*;
2120
pub use remote::*;
2221
pub use snapshot::*;
22+
pub use sync::*;
2323
pub use user::*;
2424

2525
use core::{ffi, ptr};
2626

2727
use binaryninjacore_sys::*;
2828

29-
use crate::rc::Array;
29+
use crate::rc::{Array, Ref};
3030
use crate::string::{BnStrCompatible, BnString};
3131

3232
// TODO it's unclear where should preventivelly call things like `open`, `pull_files`, `pull_folders`, etc
3333
// and where should let the user do it.
3434

3535
/// Get the single actively connected Remote (for ux simplification), if any
36-
pub fn active_remote() -> Option<Remote> {
36+
pub fn active_remote() -> Option<Ref<Remote>> {
3737
let value = unsafe { BNCollaborationGetActiveRemote() };
38-
ptr::NonNull::new(value).map(|h| unsafe { Remote::from_raw(h) })
38+
ptr::NonNull::new(value).map(|h| unsafe { Remote::ref_from_raw(h) })
3939
}
4040

4141
/// Set the single actively connected Remote
4242
pub fn set_active_remote(remote: Option<&Remote>) {
43-
let remote_ptr = remote.map_or(ptr::null_mut(), |r| unsafe { r.as_raw() } as *mut _);
43+
let remote_ptr = remote.map_or(ptr::null_mut(), |r| r.handle.as_ptr());
4444
unsafe { BNCollaborationSetActiveRemote(remote_ptr) }
4545
}
4646

@@ -117,32 +117,32 @@ pub fn known_remotes() -> Array<Remote> {
117117
}
118118

119119
/// Get Remote by unique `id`
120-
pub fn get_remote_by_id<S: BnStrCompatible>(id: S) -> Option<Remote> {
120+
pub fn get_remote_by_id<S: BnStrCompatible>(id: S) -> Option<Ref<Remote>> {
121121
let id = id.into_bytes_with_nul();
122122
let value = unsafe { BNCollaborationGetRemoteById(id.as_ref().as_ptr() as *const ffi::c_char) };
123-
ptr::NonNull::new(value).map(|h| unsafe { Remote::from_raw(h) })
123+
ptr::NonNull::new(value).map(|h| unsafe { Remote::ref_from_raw(h) })
124124
}
125125

126126
/// Get Remote by `address`
127-
pub fn get_remote_by_address<S: BnStrCompatible>(address: S) -> Option<Remote> {
127+
pub fn get_remote_by_address<S: BnStrCompatible>(address: S) -> Option<Ref<Remote>> {
128128
let address = address.into_bytes_with_nul();
129129
let value = unsafe {
130130
BNCollaborationGetRemoteByAddress(address.as_ref().as_ptr() as *const ffi::c_char)
131131
};
132-
ptr::NonNull::new(value).map(|h| unsafe { Remote::from_raw(h) })
132+
ptr::NonNull::new(value).map(|h| unsafe { Remote::ref_from_raw(h) })
133133
}
134134

135135
/// Get Remote by `name`
136-
pub fn get_remote_by_name<S: BnStrCompatible>(name: S) -> Option<Remote> {
136+
pub fn get_remote_by_name<S: BnStrCompatible>(name: S) -> Option<Ref<Remote>> {
137137
let name = name.into_bytes_with_nul();
138138
let value =
139139
unsafe { BNCollaborationGetRemoteByName(name.as_ref().as_ptr() as *const ffi::c_char) };
140-
ptr::NonNull::new(value).map(|h| unsafe { Remote::from_raw(h) })
140+
ptr::NonNull::new(value).map(|h| unsafe { Remote::ref_from_raw(h) })
141141
}
142142

143143
/// Remove a Remote from the list of known remotes (saved to Settings)
144144
pub fn remove_known_remote(remote: &Remote) {
145-
unsafe { BNCollaborationRemoveRemote(remote.as_raw()) }
145+
unsafe { BNCollaborationRemoveRemote(remote.handle.as_ptr()) }
146146
}
147147

148148
/// Save the list of known Remotes to local Settings
Lines changed: 46 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,65 @@
1-
use core::{ffi, mem, ptr};
2-
31
use binaryninjacore_sys::*;
2+
use core::{ffi, mem, ptr};
3+
use std::ptr::NonNull;
44

5-
use super::{RemoteFile, User};
5+
use super::{RemoteFile, RemoteUser};
66

7+
use crate::database::snapshot::SnapshotId;
78
use crate::database::Database;
8-
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner};
9+
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
910
use crate::string::{BnStrCompatible, BnString};
1011

11-
/// Class representing a collection of snapshots in a local database
12+
/// A collection of snapshots in a local database
1213
#[repr(transparent)]
1314
pub struct Changeset {
14-
handle: ptr::NonNull<BNCollaborationChangeset>,
15-
}
16-
17-
impl Drop for Changeset {
18-
fn drop(&mut self) {
19-
unsafe { BNFreeCollaborationChangeset(self.as_raw()) }
20-
}
21-
}
22-
23-
impl Clone for Changeset {
24-
fn clone(&self) -> Self {
25-
unsafe {
26-
Self::from_raw(
27-
ptr::NonNull::new(BNNewCollaborationChangesetReference(self.as_raw())).unwrap(),
28-
)
29-
}
30-
}
15+
handle: NonNull<BNCollaborationChangeset>,
3116
}
3217

3318
impl Changeset {
34-
pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNCollaborationChangeset>) -> Self {
19+
pub(crate) unsafe fn from_raw(handle: NonNull<BNCollaborationChangeset>) -> Self {
3520
Self { handle }
3621
}
3722

38-
pub(crate) unsafe fn ref_from_raw(handle: &*mut BNCollaborationChangeset) -> &Self {
39-
assert!(!handle.is_null());
40-
mem::transmute(handle)
41-
}
42-
43-
#[allow(clippy::mut_from_ref)]
44-
pub(crate) unsafe fn as_raw(&self) -> &mut BNCollaborationChangeset {
45-
&mut *self.handle.as_ptr()
23+
pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNCollaborationChangeset>) -> Ref<Self> {
24+
Ref::new(Self { handle })
4625
}
4726

4827
/// Owning database for snapshots
4928
pub fn database(&self) -> Result<Database, ()> {
50-
let result = unsafe { BNCollaborationChangesetGetDatabase(self.as_raw()) };
51-
let raw = ptr::NonNull::new(result).ok_or(())?;
29+
let result = unsafe { BNCollaborationChangesetGetDatabase(self.handle.as_ptr()) };
30+
let raw = NonNull::new(result).ok_or(())?;
5231
Ok(unsafe { Database::from_raw(raw) })
5332
}
5433

5534
/// Relevant remote File object
56-
pub fn file(&self) -> Result<RemoteFile, ()> {
57-
let result = unsafe { BNCollaborationChangesetGetFile(self.as_raw()) };
58-
ptr::NonNull::new(result)
59-
.map(|raw| unsafe { RemoteFile::from_raw(raw) })
35+
pub fn file(&self) -> Result<Ref<RemoteFile>, ()> {
36+
let result = unsafe { BNCollaborationChangesetGetFile(self.handle.as_ptr()) };
37+
NonNull::new(result)
38+
.map(|raw| unsafe { RemoteFile::ref_from_raw(raw) })
6039
.ok_or(())
6140
}
6241

6342
/// List of snapshot ids in the database
6443
pub fn snapshot_ids(&self) -> Result<Array<SnapshotId>, ()> {
6544
let mut count = 0;
66-
let result = unsafe { BNCollaborationChangesetGetSnapshotIds(self.as_raw(), &mut count) };
45+
let result =
46+
unsafe { BNCollaborationChangesetGetSnapshotIds(self.handle.as_ptr(), &mut count) };
6747
(!result.is_null())
6848
.then(|| unsafe { Array::new(result, count, ()) })
6949
.ok_or(())
7050
}
7151

7252
/// Relevant remote author User
73-
pub fn author(&self) -> Result<User, ()> {
74-
let result = unsafe { BNCollaborationChangesetGetAuthor(self.as_raw()) };
75-
ptr::NonNull::new(result)
76-
.map(|raw| unsafe { User::from_raw(raw) })
53+
pub fn author(&self) -> Result<Ref<RemoteUser>, ()> {
54+
let result = unsafe { BNCollaborationChangesetGetAuthor(self.handle.as_ptr()) };
55+
NonNull::new(result)
56+
.map(|raw| unsafe { RemoteUser::ref_from_raw(raw) })
7757
.ok_or(())
7858
}
7959

8060
/// Changeset name
8161
pub fn name(&self) -> BnString {
82-
let result = unsafe { BNCollaborationChangesetGetName(self.as_raw()) };
62+
let result = unsafe { BNCollaborationChangesetGetName(self.handle.as_ptr()) };
8363
assert!(!result.is_null());
8464
unsafe { BnString::from_raw(result) }
8565
}
@@ -89,42 +69,47 @@ impl Changeset {
8969
let value = value.into_bytes_with_nul();
9070
unsafe {
9171
BNCollaborationChangesetSetName(
92-
self.as_raw(),
72+
self.handle.as_ptr(),
9373
value.as_ref().as_ptr() as *const ffi::c_char,
9474
)
9575
}
9676
}
9777
}
9878

99-
impl CoreArrayProvider for Changeset {
100-
type Raw = *mut BNCollaborationChangeset;
101-
type Context = ();
102-
type Wrapped<'a> = &'a Self;
79+
impl ToOwned for Changeset {
80+
type Owned = Ref<Self>;
81+
82+
fn to_owned(&self) -> Self::Owned {
83+
unsafe { RefCountable::inc_ref(self) }
84+
}
10385
}
10486

105-
unsafe impl CoreArrayProviderInner for Changeset {
106-
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
107-
BNFreeCollaborationChangesetList(raw, count)
87+
unsafe impl RefCountable for Changeset {
88+
unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
89+
Ref::new(Self {
90+
handle: NonNull::new(BNNewCollaborationChangesetReference(handle.handle.as_ptr()))
91+
.unwrap(),
92+
})
10893
}
10994

110-
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
111-
Self::ref_from_raw(raw)
95+
unsafe fn dec_ref(handle: &Self) {
96+
BNFreeCollaborationChangeset(handle.handle.as_ptr());
11297
}
11398
}
11499

115-
pub struct SnapshotId;
116-
impl CoreArrayProvider for SnapshotId {
117-
type Raw = i64;
100+
impl CoreArrayProvider for Changeset {
101+
type Raw = *mut BNCollaborationChangeset;
118102
type Context = ();
119-
type Wrapped<'a> = i64;
103+
type Wrapped<'a> = Guard<'a, Self>;
120104
}
121105

122-
unsafe impl CoreArrayProviderInner for SnapshotId {
106+
unsafe impl CoreArrayProviderInner for Changeset {
123107
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
124-
BNCollaborationFreeSnapshotIdList(raw, count)
108+
BNFreeCollaborationChangesetList(raw, count)
125109
}
126110

127-
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
128-
*raw
111+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
112+
let raw_ptr = NonNull::new(*raw).unwrap();
113+
Guard::new(Self::from_raw(raw_ptr), context)
129114
}
130115
}

0 commit comments

Comments
 (0)