binaryninja/collaboration/
group.rs1use super::Remote;
2use crate::collaboration::RemoteUser;
3use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
4use crate::string::{BnString, IntoCStr};
5use binaryninjacore_sys::*;
6use std::fmt;
7use std::fmt::{Display, Formatter};
8use std::ptr::NonNull;
9
10#[repr(transparent)]
11pub struct RemoteGroup {
12 pub(crate) handle: NonNull<BNCollaborationGroup>,
13}
14
15impl RemoteGroup {
16 pub(crate) unsafe fn from_raw(handle: NonNull<BNCollaborationGroup>) -> Self {
17 Self { handle }
18 }
19
20 pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNCollaborationGroup>) -> Ref<Self> {
21 Ref::new(Self { handle })
22 }
23
24 pub fn remote(&self) -> Result<Ref<Remote>, ()> {
26 let value = unsafe { BNCollaborationGroupGetRemote(self.handle.as_ptr()) };
27 NonNull::new(value)
28 .map(|handle| unsafe { Remote::ref_from_raw(handle) })
29 .ok_or(())
30 }
31
32 pub fn url(&self) -> String {
34 let value = unsafe { BNCollaborationGroupGetUrl(self.handle.as_ptr()) };
35 assert!(!value.is_null());
36 unsafe { BnString::into_string(value) }
37 }
38
39 pub fn id(&self) -> GroupId {
41 GroupId(unsafe { BNCollaborationGroupGetId(self.handle.as_ptr()) })
42 }
43
44 pub fn name(&self) -> String {
46 let value = unsafe { BNCollaborationGroupGetName(self.handle.as_ptr()) };
47 assert!(!value.is_null());
48 unsafe { BnString::into_string(value) }
49 }
50
51 pub fn set_name(&self, name: &str) {
54 let name = name.to_cstr();
55 unsafe { BNCollaborationGroupSetName(self.handle.as_ptr(), name.as_ptr()) }
56 }
57
58 pub fn users(&self) -> Result<Array<RemoteUser>, ()> {
60 let mut count = 0;
61 let result = unsafe { BNCollaborationGroupGetUsers(self.handle.as_ptr(), &mut count) };
64 (!result.is_null())
65 .then(|| unsafe { Array::new(result, count, ()) })
66 .ok_or(())
67 }
68
69 pub fn set_users<I>(&self, users: I) -> Result<(), ()>
73 where
74 I: IntoIterator<Item = Ref<RemoteUser>>,
75 {
76 let mut users_raw: Vec<_> = users.into_iter().map(|s| s.handle.as_ptr()).collect();
77 let success = unsafe {
81 BNCollaborationGroupSetUsers(
82 self.handle.as_ptr(),
83 users_raw.as_mut_ptr(),
84 users_raw.len(),
85 )
86 };
87 success.then_some(()).ok_or(())
88 }
89
90 pub fn contains_user(&self, user: Ref<RemoteUser>) -> bool {
92 unsafe { BNCollaborationGroupContainsUser(self.handle.as_ptr(), user.handle.as_ptr()) }
93 }
94}
95
96impl PartialEq for RemoteGroup {
97 fn eq(&self, other: &Self) -> bool {
98 self.id() == other.id()
99 }
100}
101impl Eq for RemoteGroup {}
102
103impl ToOwned for RemoteGroup {
104 type Owned = Ref<Self>;
105
106 fn to_owned(&self) -> Self::Owned {
107 unsafe { RefCountable::inc_ref(self) }
108 }
109}
110
111unsafe impl RefCountable for RemoteGroup {
112 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
113 Ref::new(Self {
114 handle: NonNull::new(BNNewCollaborationGroupReference(handle.handle.as_ptr())).unwrap(),
115 })
116 }
117
118 unsafe fn dec_ref(handle: &Self) {
119 BNFreeCollaborationGroup(handle.handle.as_ptr());
120 }
121}
122
123impl CoreArrayProvider for RemoteGroup {
124 type Raw = *mut BNCollaborationGroup;
125 type Context = ();
126 type Wrapped<'a> = Guard<'a, Self>;
127}
128
129unsafe impl CoreArrayProviderInner for RemoteGroup {
130 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
131 BNFreeCollaborationGroupList(raw, count)
132 }
133
134 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
135 let raw_ptr = NonNull::new(*raw).unwrap();
136 Guard::new(Self::from_raw(raw_ptr), context)
137 }
138}
139
140#[repr(transparent)]
141#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
142pub struct GroupId(pub u64);
143
144impl Display for GroupId {
145 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
146 f.write_fmt(format_args!("{}", self.0))
147 }
148}
149
150impl CoreArrayProvider for GroupId {
151 type Raw = u64;
152 type Context = ();
153 type Wrapped<'a> = GroupId;
154}
155
156unsafe impl CoreArrayProviderInner for GroupId {
157 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
158 BNCollaborationFreeIdList(raw, count)
159 }
160
161 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
162 GroupId(*raw)
163 }
164}