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