From a826c589dfc10c542deba7ca3343a462e02d6bde Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Sun, 4 May 2025 19:10:56 -0400 Subject: [Rust] Simplify `BnStrCompatible` trait Followup to https://github.com/Vector35/binaryninja-api/pull/5897/ This simplifies usage of the trait in user code, should just be able to `to_cstr` to get the cstr repr and then call `as_ptr`. Co-authored-by: Michael Krasnitski --- rust/src/collaboration/changeset.rs | 6 +-- rust/src/collaboration/file.rs | 44 +++++++--------- rust/src/collaboration/folder.rs | 10 ++-- rust/src/collaboration/group.rs | 17 +++--- rust/src/collaboration/merge.rs | 18 +++---- rust/src/collaboration/project.rs | 101 ++++++++++++++++-------------------- rust/src/collaboration/remote.rs | 95 +++++++++++++++------------------ rust/src/collaboration/snapshot.rs | 6 +-- rust/src/collaboration/sync.rs | 35 ++++++------- rust/src/collaboration/user.rs | 10 ++-- 10 files changed, 156 insertions(+), 186 deletions(-) (limited to 'rust/src/collaboration') diff --git a/rust/src/collaboration/changeset.rs b/rust/src/collaboration/changeset.rs index fd862df6..1cc30d76 100644 --- a/rust/src/collaboration/changeset.rs +++ b/rust/src/collaboration/changeset.rs @@ -7,7 +7,7 @@ use super::{RemoteFile, RemoteUser}; use crate::database::snapshot::SnapshotId; use crate::database::Database; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; /// A collection of snapshots in a local database #[repr(transparent)] @@ -66,8 +66,8 @@ impl Changeset { } /// Set the name of the changeset, e.g. in a name changeset function. - pub fn set_name(&self, value: S) -> bool { - let value = value.into_bytes_with_nul(); + pub fn set_name(&self, value: S) -> bool { + let value = value.to_cstr(); unsafe { BNCollaborationChangesetSetName( self.handle.as_ptr(), diff --git a/rust/src/collaboration/file.rs b/rust/src/collaboration/file.rs index 678c0c15..2089fbb7 100644 --- a/rust/src/collaboration/file.rs +++ b/rust/src/collaboration/file.rs @@ -16,7 +16,7 @@ use crate::file_metadata::FileMetadata; use crate::progress::{NoProgressCallback, ProgressCallback, SplitProgressBuilder}; use crate::project::file::ProjectFile; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub type RemoteFileType = BNRemoteFileType; @@ -94,8 +94,8 @@ impl RemoteFile { success.then_some(()).ok_or(()) } - pub fn set_metadata(&self, folder: S) -> Result<(), ()> { - let folder_raw = folder.into_bytes_with_nul(); + pub fn set_metadata(&self, folder: S) -> Result<(), ()> { + let folder_raw = folder.to_cstr(); let success = unsafe { BNRemoteFileSetMetadata( self.handle.as_ptr(), @@ -190,8 +190,8 @@ impl RemoteFile { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_name(&self, name: S) -> Result<(), ()> { - let name = name.into_bytes_with_nul(); + pub fn set_name(&self, name: S) -> Result<(), ()> { + let name = name.to_cstr(); let success = unsafe { BNRemoteFileSetName( self.handle.as_ptr(), @@ -209,8 +209,8 @@ impl RemoteFile { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_description(&self, description: S) -> Result<(), ()> { - let description = description.into_bytes_with_nul(); + pub fn set_description(&self, description: S) -> Result<(), ()> { + let description = description.to_cstr(); let success = unsafe { BNRemoteFileSetDescription( self.handle.as_ptr(), @@ -263,15 +263,12 @@ impl RemoteFile { /// Get a specific Snapshot in the File by its id /// /// NOTE: If snapshots have not been pulled, they will be pulled upon calling this. - pub fn snapshot_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn snapshot_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_snapshots() { self.pull_snapshots()?; } - let id = id.into_bytes_with_nul(); + let id = id.to_cstr(); let result = unsafe { BNRemoteFileGetSnapshotById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) }; @@ -314,9 +311,9 @@ impl RemoteFile { parent_ids: I, ) -> Result, ()> where - S: BnStrCompatible, + S: AsCStr, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { self.create_snapshot_with_progress( name, @@ -346,16 +343,13 @@ impl RemoteFile { mut progress: P, ) -> Result, ()> where - S: BnStrCompatible, + S: AsCStr, P: ProgressCallback, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let name = name.into_bytes_with_nul(); - let parent_ids: Vec<_> = parent_ids - .into_iter() - .map(|id| id.into_bytes_with_nul()) - .collect(); + let name = name.to_cstr(); + let parent_ids: Vec<_> = parent_ids.into_iter().map(|id| id.to_cstr()).collect(); let mut parent_ids_raw: Vec<_> = parent_ids .iter() .map(|x| x.as_ref().as_ptr() as *const c_char) @@ -430,7 +424,7 @@ impl RemoteFile { /// * `progress_function` - Function to call for progress updates pub fn download(&self, db_path: S) -> Result, ()> where - S: BnStrCompatible, + S: AsCStr, { sync::download_file(self, db_path) } @@ -447,14 +441,14 @@ impl RemoteFile { progress_function: F, ) -> Result, ()> where - S: BnStrCompatible, + S: AsCStr, F: ProgressCallback, { sync::download_file_with_progress(self, db_path, progress_function) } /// Download a remote file and save it to a BNDB at the given `path`, returning the associated [`FileMetadata`]. - pub fn download_database(&self, path: S) -> Result, ()> { + pub fn download_database(&self, path: S) -> Result, ()> { let file = self.download(path)?; let database = file.database().ok_or(())?; self.sync(&database, DatabaseConflictHandlerFail, NoNameChangeset)?; @@ -464,7 +458,7 @@ impl RemoteFile { // TODO: This might be a bad helper... maybe remove... // TODO: AsRef /// Download a remote file and save it to a BNDB at the given `path`. - pub fn download_database_with_progress( + pub fn download_database_with_progress( &self, path: S, progress: impl ProgressCallback, diff --git a/rust/src/collaboration/folder.rs b/rust/src/collaboration/folder.rs index eb4fd9f8..0fd2bf87 100644 --- a/rust/src/collaboration/folder.rs +++ b/rust/src/collaboration/folder.rs @@ -5,7 +5,7 @@ use std::ptr::NonNull; use crate::project::folder::ProjectFolder; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct RemoteFolder { @@ -104,8 +104,8 @@ impl RemoteFolder { } /// Set the display name of the folder. You will need to push the folder to update the remote version. - pub fn set_name(&self, name: S) -> Result<(), ()> { - let name = name.into_bytes_with_nul(); + pub fn set_name(&self, name: S) -> Result<(), ()> { + let name = name.to_cstr(); let success = unsafe { BNRemoteFolderSetName( self.handle.as_ptr(), @@ -123,8 +123,8 @@ impl RemoteFolder { } /// Set the description of the folder. You will need to push the folder to update the remote version. - pub fn set_description(&self, description: S) -> Result<(), ()> { - let description = description.into_bytes_with_nul(); + pub fn set_description(&self, description: S) -> Result<(), ()> { + let description = description.to_cstr(); let success = unsafe { BNRemoteFolderSetDescription( self.handle.as_ptr(), diff --git a/rust/src/collaboration/group.rs b/rust/src/collaboration/group.rs index 9fb287a7..94253519 100644 --- a/rust/src/collaboration/group.rs +++ b/rust/src/collaboration/group.rs @@ -1,6 +1,6 @@ use super::Remote; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::*; use std::ffi::c_char; use std::fmt; @@ -50,8 +50,8 @@ impl RemoteGroup { /// Set group name /// You will need to push the group to update the Remote. - pub fn set_name(&self, name: U) { - let name = name.into_bytes_with_nul(); + pub fn set_name(&self, name: U) { + let name = name.to_cstr(); unsafe { BNCollaborationGroupSetName( self.handle.as_ptr(), @@ -90,12 +90,9 @@ impl RemoteGroup { pub fn set_users(&self, usernames: I) -> Result<(), ()> where I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let usernames: Vec<_> = usernames - .into_iter() - .map(|u| u.into_bytes_with_nul()) - .collect(); + let usernames: Vec<_> = usernames.into_iter().map(|u| u.to_cstr()).collect(); let mut usernames_raw: Vec<_> = usernames .iter() .map(|s| s.as_ref().as_ptr() as *const c_char) @@ -114,8 +111,8 @@ impl RemoteGroup { } /// Test if a group has a user with the given username - pub fn contains_user(&self, username: U) -> bool { - let username = username.into_bytes_with_nul(); + pub fn contains_user(&self, username: U) -> bool { + let username = username.to_cstr(); unsafe { BNCollaborationGroupContainsUser( self.handle.as_ptr(), diff --git a/rust/src/collaboration/merge.rs b/rust/src/collaboration/merge.rs index 68bfdc02..84aa6192 100644 --- a/rust/src/collaboration/merge.rs +++ b/rust/src/collaboration/merge.rs @@ -5,7 +5,7 @@ use std::ptr::NonNull; use crate::database::{snapshot::Snapshot, Database}; use crate::file_metadata::FileMetadata; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub type MergeConflictDataType = BNMergeConflictDataType; @@ -49,8 +49,8 @@ impl MergeConflict { NonNull::new(result).map(|handle| unsafe { Snapshot::from_raw(handle) }) } - pub fn path_item_string(&self, path: S) -> Result { - let path = path.into_bytes_with_nul(); + pub fn path_item_string(&self, path: S) -> Result { + let path = path.to_cstr(); let result = unsafe { BNAnalysisMergeConflictGetPathItemString( self.handle.as_ptr(), @@ -123,8 +123,8 @@ impl MergeConflict { } /// Call this when you've resolved the conflict to save the result - pub fn success(&self, value: S) -> Result<(), ()> { - let value = value.into_bytes_with_nul(); + pub fn success(&self, value: S) -> Result<(), ()> { + let value = value.to_cstr(); let success = unsafe { BNAnalysisMergeConflictSuccess( self.handle.as_ptr(), @@ -135,8 +135,8 @@ impl MergeConflict { } // TODO: Make a safe version of this that checks the path and if it holds a number - pub unsafe fn get_path_item_number(&self, path_key: S) -> Option { - let path_key = path_key.into_bytes_with_nul(); + pub unsafe fn get_path_item_number(&self, path_key: S) -> Option { + let path_key = path_key.to_cstr(); let value = unsafe { BNAnalysisMergeConflictGetPathItem( self.handle.as_ptr(), @@ -150,8 +150,8 @@ impl MergeConflict { } } - pub unsafe fn get_path_item_string(&self, path_key: S) -> Option { - let path_key = path_key.into_bytes_with_nul(); + pub unsafe fn get_path_item_string(&self, path_key: S) -> Option { + let path_key = path_key.to_cstr(); let value = unsafe { BNAnalysisMergeConflictGetPathItemString( self.handle.as_ptr(), diff --git a/rust/src/collaboration/project.rs b/rust/src/collaboration/project.rs index b3c6513d..8c04080b 100644 --- a/rust/src/collaboration/project.rs +++ b/rust/src/collaboration/project.rs @@ -15,7 +15,7 @@ use crate::file_metadata::FileMetadata; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::project::Project; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct RemoteProject { @@ -136,8 +136,8 @@ impl RemoteProject { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_name(&self, name: S) -> Result<(), ()> { - let name = name.into_bytes_with_nul(); + pub fn set_name(&self, name: S) -> Result<(), ()> { + let name = name.to_cstr(); let success = unsafe { BNRemoteProjectSetName( self.handle.as_ptr(), @@ -155,8 +155,8 @@ impl RemoteProject { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_description(&self, description: S) -> Result<(), ()> { - let description = description.into_bytes_with_nul(); + pub fn set_description(&self, description: S) -> Result<(), ()> { + let description = description.to_cstr(); let success = unsafe { BNRemoteProjectSetDescription( self.handle.as_ptr(), @@ -230,12 +230,12 @@ impl RemoteProject { /// /// NOTE: If the project has not been opened, it will be opened upon calling this. /// NOTE: If files have not been pulled, they will be pulled upon calling this. - pub fn get_file_by_id(&self, id: S) -> Result>, ()> { + pub fn get_file_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_files() { self.pull_files()?; } - let id = id.into_bytes_with_nul(); + let id = id.to_cstr(); let result = unsafe { BNRemoteProjectGetFileById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) }; @@ -246,15 +246,12 @@ impl RemoteProject { /// /// NOTE: If the project has not been opened, it will be opened upon calling this. /// NOTE: If files have not been pulled, they will be pulled upon calling this. - pub fn get_file_by_name( - &self, - name: S, - ) -> Result>, ()> { + pub fn get_file_by_name(&self, name: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_files() { self.pull_files()?; } - let id = name.into_bytes_with_nul(); + let id = name.to_cstr(); let result = unsafe { BNRemoteProjectGetFileByName( self.handle.as_ptr(), @@ -311,9 +308,9 @@ impl RemoteProject { file_type: RemoteFileType, ) -> Result, ()> where - F: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, + F: AsCStr, + N: AsCStr, + D: AsCStr, { self.create_file_with_progress( filename, @@ -348,17 +345,17 @@ impl RemoteProject { mut progress: P, ) -> Result, ()> where - F: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, + F: AsCStr, + N: AsCStr, + D: AsCStr, P: ProgressCallback, { // TODO: This sync should be removed? self.open()?; - let filename = filename.into_bytes_with_nul(); - let name = name.into_bytes_with_nul(); - let description = description.into_bytes_with_nul(); + let filename = filename.to_cstr(); + let name = name.to_cstr(); + let description = description.to_cstr(); let folder_handle = parent_folder.map_or(std::ptr::null_mut(), |f| f.handle.as_ptr()); let file_ptr = unsafe { BNRemoteProjectCreateFile( @@ -386,15 +383,15 @@ impl RemoteProject { pub fn push_file(&self, file: &RemoteFile, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { // TODO: This sync should be removed? self.open()?; let (keys, values): (Vec<_>, Vec<_>) = extra_fields .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) + .map(|(k, v)| (k.to_cstr(), v.to_cstr())) .unzip(); let mut keys_raw = keys .iter() @@ -446,15 +443,12 @@ impl RemoteProject { /// /// NOTE: If the project has not been opened, it will be opened upon calling this. /// NOTE: If folders have not been pulled, they will be pulled upon calling this. - pub fn get_folder_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn get_folder_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_folders() { self.pull_folders()?; } - let id = id.into_bytes_with_nul(); + let id = id.to_cstr(); let result = unsafe { BNRemoteProjectGetFolderById( self.handle.as_ptr(), @@ -505,8 +499,8 @@ impl RemoteProject { parent_folder: Option<&RemoteFolder>, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, { self.create_folder_with_progress(name, description, parent_folder, NoProgressCallback) } @@ -527,15 +521,15 @@ impl RemoteProject { mut progress: P, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, P: ProgressCallback, { // TODO: This sync should be removed? self.open()?; - let name = name.into_bytes_with_nul(); - let description = description.into_bytes_with_nul(); + let name = name.to_cstr(); + let description = description.to_cstr(); let folder_handle = parent_folder.map_or(std::ptr::null_mut(), |f| f.handle.as_ptr()); let file_ptr = unsafe { BNRemoteProjectCreateFolder( @@ -562,15 +556,15 @@ impl RemoteProject { pub fn push_folder(&self, folder: &RemoteFolder, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { // TODO: This sync should be removed? self.open()?; let (keys, values): (Vec<_>, Vec<_>) = extra_fields .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) + .map(|(k, v)| (k.to_cstr(), v.to_cstr())) .unzip(); let mut keys_raw = keys .iter() @@ -637,10 +631,7 @@ impl RemoteProject { /// Get a specific permission in the Project by its id. /// /// NOTE: If group or user permissions have not been pulled, they will be pulled upon calling this. - pub fn get_permission_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn get_permission_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_user_permissions() { self.pull_user_permissions()?; @@ -650,7 +641,7 @@ impl RemoteProject { self.pull_group_permissions()?; } - let id = id.into_bytes_with_nul(); + let id = id.to_cstr(); let value = unsafe { BNRemoteProjectGetPermissionById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const _) }; @@ -745,7 +736,7 @@ impl RemoteProject { /// /// * `user_id` - User id /// * `level` - Permission level - pub fn create_user_permission( + pub fn create_user_permission( &self, user_id: S, level: CollaborationPermissionLevel, @@ -760,13 +751,13 @@ impl RemoteProject { /// * `user_id` - User id /// * `level` - Permission level /// * `progress` - The progress callback to call - pub fn create_user_permission_with_progress( + pub fn create_user_permission_with_progress( &self, user_id: S, level: CollaborationPermissionLevel, mut progress: F, ) -> Result, ()> { - let user_id = user_id.into_bytes_with_nul(); + let user_id = user_id.to_cstr(); let value = unsafe { BNRemoteProjectCreateUserPermission( self.handle.as_ptr(), @@ -795,12 +786,12 @@ impl RemoteProject { ) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { let (keys, values): (Vec<_>, Vec<_>) = extra_fields .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) + .map(|(k, v)| (k.to_cstr(), v.to_cstr())) .unzip(); let mut keys_raw = keys .iter() @@ -836,8 +827,8 @@ impl RemoteProject { /// # Arguments /// /// * `username` - Username of user to check - pub fn can_user_view(&self, username: S) -> bool { - let username = username.into_bytes_with_nul(); + pub fn can_user_view(&self, username: S) -> bool { + let username = username.to_cstr(); unsafe { BNRemoteProjectCanUserView( self.handle.as_ptr(), @@ -851,8 +842,8 @@ impl RemoteProject { /// # Arguments /// /// * `username` - Username of user to check - pub fn can_user_edit(&self, username: S) -> bool { - let username = username.into_bytes_with_nul(); + pub fn can_user_edit(&self, username: S) -> bool { + let username = username.to_cstr(); unsafe { BNRemoteProjectCanUserEdit( self.handle.as_ptr(), @@ -866,8 +857,8 @@ impl RemoteProject { /// # Arguments /// /// * `username` - Username of user to check - pub fn can_user_admin(&self, username: S) -> bool { - let username = username.into_bytes_with_nul(); + pub fn can_user_admin(&self, username: S) -> bool { + let username = username.to_cstr(); unsafe { BNRemoteProjectCanUserAdmin( self.handle.as_ptr(), diff --git a/rust/src/collaboration/remote.rs b/rust/src/collaboration/remote.rs index 98784ddb..3a1f021c 100644 --- a/rust/src/collaboration/remote.rs +++ b/rust/src/collaboration/remote.rs @@ -10,7 +10,7 @@ use crate::enterprise; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::project::Project; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct Remote { @@ -27,9 +27,9 @@ impl Remote { } /// Create a Remote and add it to the list of known remotes (saved to Settings) - pub fn new(name: N, address: A) -> Ref { - let name = name.into_bytes_with_nul(); - let address = address.into_bytes_with_nul(); + pub fn new(name: N, address: A) -> Ref { + let name = name.to_cstr(); + let address = address.to_cstr(); let result = unsafe { BNCollaborationCreateRemote( name.as_ref().as_ptr() as *const c_char, @@ -168,13 +168,13 @@ impl Remote { } /// Requests an authentication token using a username and password. - pub fn request_authentication_token( + pub fn request_authentication_token( &self, username: U, password: P, ) -> Option { - let username = username.into_bytes_with_nul(); - let password = password.into_bytes_with_nul(); + let username = username.to_cstr(); + let password = password.to_cstr(); let token = unsafe { BNRemoteRequestAuthenticationToken( self.handle.as_ptr(), @@ -229,9 +229,9 @@ impl Remote { token.unwrap().to_string() } }; - let username = options.username.into_bytes_with_nul(); + let username = options.username.to_cstr(); let username_ptr = username.as_ptr() as *const c_char; - let token = token.into_bytes_with_nul(); + let token = token.to_cstr(); let token_ptr = token.as_ptr() as *const c_char; let success = unsafe { BNRemoteConnect(self.handle.as_ptr(), username_ptr, token_ptr) }; success.then_some(()).ok_or(()) @@ -281,15 +281,12 @@ impl Remote { /// Gets a specific project in the Remote by its id. /// /// NOTE: If projects have not been pulled, they will be pulled upon calling this. - pub fn get_project_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn get_project_by_id(&self, id: S) -> Result>, ()> { if !self.has_pulled_projects() { self.pull_projects()?; } - let id = id.into_bytes_with_nul(); + let id = id.to_cstr(); let value = unsafe { BNRemoteGetProjectById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) }; @@ -299,7 +296,7 @@ impl Remote { /// Gets a specific project in the Remote by its name. /// /// NOTE: If projects have not been pulled, they will be pulled upon calling this. - pub fn get_project_by_name( + pub fn get_project_by_name( &self, name: S, ) -> Result>, ()> { @@ -307,7 +304,7 @@ impl Remote { self.pull_projects()?; } - let name = name.into_bytes_with_nul(); + let name = name.to_cstr(); let value = unsafe { BNRemoteGetProjectByName( self.handle.as_ptr(), @@ -347,7 +344,7 @@ impl Remote { /// /// * `name` - Project name /// * `description` - Project description - pub fn create_project( + pub fn create_project( &self, name: N, description: D, @@ -358,8 +355,8 @@ impl Remote { if !self.has_pulled_projects() { self.pull_projects()?; } - let name = name.into_bytes_with_nul(); - let description = description.into_bytes_with_nul(); + let name = name.to_cstr(); + let description = description.to_cstr(); let value = unsafe { BNRemoteCreateProject( self.handle.as_ptr(), @@ -403,12 +400,12 @@ impl Remote { pub fn push_project(&self, project: &RemoteProject, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { let (keys, values): (Vec<_>, Vec<_>) = extra_fields .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) + .map(|(k, v)| (k.to_cstr(), v.to_cstr())) .unzip(); let mut keys_raw = keys .iter() @@ -472,15 +469,12 @@ impl Remote { /// /// If groups have not been pulled, they will be pulled upon calling this. /// This function is only available to accounts with admin status on the Remote. - pub fn get_group_by_name( - &self, - name: S, - ) -> Result>, ()> { + pub fn get_group_by_name(&self, name: S) -> Result>, ()> { if !self.has_pulled_groups() { self.pull_groups()?; } - let name = name.into_bytes_with_nul(); + let name = name.to_cstr(); let value = unsafe { BNRemoteGetGroupByName( self.handle.as_ptr(), @@ -496,11 +490,11 @@ impl Remote { /// # Arguments /// /// * `prefix` - Prefix of name for groups - pub fn search_groups( + pub fn search_groups( &self, prefix: S, ) -> Result<(Array, Array), ()> { - let prefix = prefix.into_bytes_with_nul(); + let prefix = prefix.to_cstr(); let mut count = 0; let mut group_ids = std::ptr::null_mut(); let mut group_names = std::ptr::null_mut(); @@ -560,15 +554,12 @@ impl Remote { /// * `usernames` - List of usernames of users in the group pub fn create_group(&self, name: N, usernames: I) -> Result, ()> where - N: BnStrCompatible, + N: AsCStr, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let name = name.into_bytes_with_nul(); - let usernames: Vec<_> = usernames - .into_iter() - .map(|s| s.into_bytes_with_nul()) - .collect(); + let name = name.to_cstr(); + let usernames: Vec<_> = usernames.into_iter().map(|s| s.to_cstr()).collect(); let mut username_ptrs: Vec<_> = usernames .iter() .map(|s| s.as_ref().as_ptr() as *const c_char) @@ -597,12 +588,12 @@ impl Remote { pub fn push_group(&self, group: &RemoteGroup, extra_fields: I) -> Result<(), ()> where I: IntoIterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { let (keys, values): (Vec<_>, Vec<_>) = extra_fields .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) + .map(|(k, v)| (k.to_cstr(), v.to_cstr())) .unzip(); let mut keys_raw: Vec<_> = keys .iter() @@ -663,11 +654,11 @@ impl Remote { /// # Arguments /// /// * `id` - The identifier of the user to retrieve. - pub fn get_user_by_id(&self, id: S) -> Result>, ()> { + pub fn get_user_by_id(&self, id: S) -> Result>, ()> { if !self.has_pulled_users() { self.pull_users()?; } - let id = id.into_bytes_with_nul(); + let id = id.to_cstr(); let value = unsafe { BNRemoteGetUserById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) }; @@ -683,14 +674,14 @@ impl Remote { /// # Arguments /// /// * `username` - The username of the user to retrieve. - pub fn get_user_by_username( + pub fn get_user_by_username( &self, username: S, ) -> Result>, ()> { if !self.has_pulled_users() { self.pull_users()?; } - let username = username.into_bytes_with_nul(); + let username = username.to_cstr(); let value = unsafe { BNRemoteGetUserByUsername( self.handle.as_ptr(), @@ -718,11 +709,11 @@ impl Remote { /// # Arguments /// /// * `prefix` - The prefix to search for in usernames. - pub fn search_users( + pub fn search_users( &self, prefix: S, ) -> Result<(Array, Array), ()> { - let prefix = prefix.into_bytes_with_nul(); + let prefix = prefix.to_cstr(); let mut count = 0; let mut user_ids = std::ptr::null_mut(); let mut usernames = std::ptr::null_mut(); @@ -783,7 +774,7 @@ impl Remote { /// # Arguments /// /// * Various details about the new user to be created. - pub fn create_user( + pub fn create_user( &self, username: U, email: E, @@ -792,9 +783,9 @@ impl Remote { group_ids: &[u64], user_permission_ids: &[u64], ) -> Result, ()> { - let username = username.into_bytes_with_nul(); - let email = email.into_bytes_with_nul(); - let password = password.into_bytes_with_nul(); + let username = username.to_cstr(); + let email = email.to_cstr(); + let password = password.to_cstr(); let value = unsafe { BNRemoteCreateUser( @@ -825,12 +816,12 @@ impl Remote { pub fn push_user(&self, user: &RemoteUser, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { let (keys, values): (Vec<_>, Vec<_>) = extra_fields .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) + .map(|(k, v)| (k.to_cstr(), v.to_cstr())) .unzip(); let mut keys_raw: Vec<_> = keys .iter() diff --git a/rust/src/collaboration/snapshot.rs b/rust/src/collaboration/snapshot.rs index 935b1c2f..465ae46a 100644 --- a/rust/src/collaboration/snapshot.rs +++ b/rust/src/collaboration/snapshot.rs @@ -8,7 +8,7 @@ use crate::collaboration::undo::{RemoteUndoEntry, RemoteUndoEntryId}; use crate::database::snapshot::Snapshot; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::*; // TODO: RemoteSnapshotId ? @@ -226,12 +226,12 @@ impl RemoteSnapshot { } /// Create a new Undo Entry in this snapshot. - pub fn create_undo_entry( + pub fn create_undo_entry( &self, parent: Option, data: S, ) -> Result, ()> { - let data = data.into_bytes_with_nul(); + let data = data.to_cstr(); let value = unsafe { BNCollaborationSnapshotCreateUndoEntry( self.handle.as_ptr(), diff --git a/rust/src/collaboration/sync.rs b/rust/src/collaboration/sync.rs index 6fc85d31..4c112336 100644 --- a/rust/src/collaboration/sync.rs +++ b/rust/src/collaboration/sync.rs @@ -11,7 +11,7 @@ use crate::file_metadata::FileMetadata; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::project::file::ProjectFile; use crate::rc::Ref; -use crate::string::{raw_to_string, BnStrCompatible, BnString}; +use crate::string::{raw_to_string, AsCStr, BnString}; use crate::type_archive::{TypeArchive, TypeArchiveMergeConflict}; // TODO: PathBuf @@ -43,10 +43,7 @@ pub fn default_file_path(file: &RemoteFile) -> Result { /// /// * `file` - Remote File to download and open /// * `db_path` - File path for saved database -pub fn download_file( - file: &RemoteFile, - db_path: S, -) -> Result, ()> { +pub fn download_file(file: &RemoteFile, db_path: S) -> Result, ()> { download_file_with_progress(file, db_path, NoProgressCallback) } @@ -57,12 +54,12 @@ pub fn download_file( /// * `file` - Remote File to download and open /// * `db_path` - File path for saved database /// * `progress` - Function to call for progress updates -pub fn download_file_with_progress( +pub fn download_file_with_progress( file: &RemoteFile, db_path: S, mut progress: F, ) -> Result, ()> { - let db_path = db_path.into_bytes_with_nul(); + let db_path = db_path.to_cstr(); let result = unsafe { BNCollaborationDownloadFile( file.handle.as_ptr(), @@ -223,7 +220,7 @@ pub fn get_local_snapshot_for_remote( pub fn download_database(file: &RemoteFile, location: S, force: bool) -> Result<(), ()> where - S: BnStrCompatible, + S: AsCStr, { download_database_with_progress(file, location, force, NoProgressCallback) } @@ -235,10 +232,10 @@ pub fn download_database_with_progress( mut progress: F, ) -> Result<(), ()> where - S: BnStrCompatible, + S: AsCStr, F: ProgressCallback, { - let db_path = location.into_bytes_with_nul(); + let db_path = location.to_cstr(); let success = unsafe { BNCollaborationDownloadDatabaseForFile( file.handle.as_ptr(), @@ -478,12 +475,12 @@ pub fn get_snapshot_author( /// * `database` - Parent database /// * `snapshot` - Snapshot to edit /// * `author` - Target author -pub fn set_snapshot_author( +pub fn set_snapshot_author( database: &Database, snapshot: &Snapshot, author: S, ) -> Result<(), ()> { - let author = author.into_bytes_with_nul(); + let author = author.to_cstr(); let success = unsafe { BNCollaborationSetSnapshotAuthor( database.handle.as_ptr(), @@ -653,11 +650,11 @@ pub fn get_remote_file_for_local_type_archive(database: &TypeArchive) -> Option< } /// Get the remote snapshot associated with a local snapshot (if it exists) in a Type Archive -pub fn get_remote_snapshot_from_local_type_archive( +pub fn get_remote_snapshot_from_local_type_archive( type_archive: &TypeArchive, snapshot_id: S, ) -> Option> { - let snapshot_id = snapshot_id.into_bytes_with_nul(); + let snapshot_id = snapshot_id.to_cstr(); let value = unsafe { BNCollaborationGetRemoteSnapshotFromLocalTypeArchive( type_archive.handle.as_ptr(), @@ -682,11 +679,11 @@ pub fn get_local_snapshot_from_remote_type_archive( } /// Test if a snapshot is ignored from the archive -pub fn is_type_archive_snapshot_ignored( +pub fn is_type_archive_snapshot_ignored( type_archive: &TypeArchive, snapshot_id: S, ) -> bool { - let snapshot_id = snapshot_id.into_bytes_with_nul(); + let snapshot_id = snapshot_id.to_cstr(); unsafe { BNCollaborationIsTypeArchiveSnapshotIgnored( type_archive.handle.as_ptr(), @@ -697,7 +694,7 @@ pub fn is_type_archive_snapshot_ignored( /// Download a type archive from its remote, saving all snapshots to an archive in the /// specified `location`. Returns a [`TypeArchive`] for using later. -pub fn download_type_archive( +pub fn download_type_archive( file: &RemoteFile, location: S, ) -> Result>, ()> { @@ -706,13 +703,13 @@ pub fn download_type_archive( /// Download a type archive from its remote, saving all snapshots to an archive in the /// specified `location`. Returns a [`TypeArchive`] for using later. -pub fn download_type_archive_with_progress( +pub fn download_type_archive_with_progress( file: &RemoteFile, location: S, mut progress: F, ) -> Result>, ()> { let mut value = std::ptr::null_mut(); - let db_path = location.into_bytes_with_nul(); + let db_path = location.to_cstr(); let success = unsafe { BNCollaborationDownloadTypeArchive( file.handle.as_ptr(), diff --git a/rust/src/collaboration/user.rs b/rust/src/collaboration/user.rs index b08e9da4..43b4e854 100644 --- a/rust/src/collaboration/user.rs +++ b/rust/src/collaboration/user.rs @@ -4,7 +4,7 @@ use std::ffi::c_char; use std::ptr::NonNull; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct RemoteUser { @@ -49,8 +49,8 @@ impl RemoteUser { } /// Set user's username. You will need to push the user to update the Remote - pub fn set_username(&self, username: U) -> Result<(), ()> { - let username = username.into_bytes_with_nul(); + pub fn set_username(&self, username: U) -> Result<(), ()> { + let username = username.to_cstr(); let result = unsafe { BNCollaborationUserSetUsername( self.handle.as_ptr(), @@ -72,8 +72,8 @@ impl RemoteUser { } /// Set user's email. You will need to push the user to update the Remote - pub fn set_email(&self, email: U) -> Result<(), ()> { - let username = email.into_bytes_with_nul(); + pub fn set_email(&self, email: U) -> Result<(), ()> { + let username = email.to_cstr(); let result = unsafe { BNCollaborationUserSetEmail( self.handle.as_ptr(), -- cgit v1.3.1