summaryrefslogtreecommitdiff
path: root/rust/src/string.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/string.rs')
-rw-r--r--rust/src/string.rs92
1 files changed, 62 insertions, 30 deletions
diff --git a/rust/src/string.rs b/rust/src/string.rs
index bfb998d5..dde8f550 100644
--- a/rust/src/string.rs
+++ b/rust/src/string.rs
@@ -14,18 +14,18 @@
//! String wrappers for core-owned strings and strings being passed to the core
+use crate::rc::*;
+use crate::types::QualifiedName;
use std::borrow::Cow;
-use std::ffi::{CStr, CString};
+use std::ffi::{c_char, CStr, CString};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::Deref;
-use std::os::raw;
-
-use crate::rc::*;
-use crate::types::QualifiedName;
+use std::path::{Path, PathBuf};
-pub(crate) fn raw_to_string(ptr: *const raw::c_char) -> Option<String> {
+// TODO: Remove or refactor this.
+pub(crate) fn raw_to_string(ptr: *const c_char) -> Option<String> {
if ptr.is_null() {
None
} else {
@@ -33,11 +33,21 @@ pub(crate) fn raw_to_string(ptr: *const raw::c_char) -> Option<String> {
}
}
-/// Is the quivalent of `core::ffi::CString` but using the allocation and free
-/// functions provided by binaryninja_sys.
+// TODO: Make this pass in an iterator over something more generic...
+pub(crate) fn strings_to_string_list(strings: &[String]) -> *mut *mut c_char {
+ use binaryninjacore_sys::BNAllocStringList;
+ let bn_str_list = strings
+ .iter()
+ .map(|s| BnString::new(s.as_str()))
+ .collect::<Vec<_>>();
+ let mut raw_str_list = bn_str_list.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
+ unsafe { BNAllocStringList(raw_str_list.as_mut_ptr(), raw_str_list.len()) }
+}
+
+/// Is the equivalent of `core::ffi::CString` but using the alloc and free from `binaryninjacore-sys`.
#[repr(transparent)]
pub struct BnString {
- raw: *mut raw::c_char,
+ raw: *mut c_char,
}
/// A nul-terminated C string allocated by the core.
@@ -52,37 +62,32 @@ pub struct BnString {
impl BnString {
pub fn new<S: BnStrCompatible>(s: S) -> Self {
use binaryninjacore_sys::BNAllocString;
-
let raw = s.into_bytes_with_nul();
-
unsafe {
let ptr = raw.as_ref().as_ptr() as *mut _;
-
- Self {
- raw: BNAllocString(ptr),
- }
+ Self::from_raw(BNAllocString(ptr))
}
}
/// Construct a BnString from an owned const char* allocated by BNAllocString
- pub(crate) unsafe fn from_raw(raw: *mut raw::c_char) -> Self {
+ pub(crate) unsafe fn from_raw(raw: *mut c_char) -> Self {
Self { raw }
}
- pub(crate) fn into_raw(self) -> *mut raw::c_char {
- let res = self.raw;
-
+ /// Consumes the `BnString`, returning a raw pointer to the string.
+ ///
+ /// After calling this function, the caller is responsible for the
+ /// memory previously managed by the `BnString`.
+ ///
+ /// This is typically used to pass a string back through the core where the core is expected to free.
+ pub fn into_raw(value: Self) -> *mut c_char {
+ let res = value.raw;
// we're surrendering ownership over the *mut c_char to
// the core, so ensure we don't free it
- mem::forget(self);
-
+ mem::forget(value);
res
}
- pub(crate) fn as_raw(&self) -> &raw::c_char {
- unsafe { &*self.raw }
- }
-
pub fn as_str(&self) -> &str {
unsafe { CStr::from_ptr(self.raw).to_str().unwrap() }
}
@@ -107,7 +112,6 @@ impl BnString {
impl Drop for BnString {
fn drop(&mut self) {
use binaryninjacore_sys::BNFreeString;
-
unsafe {
BNFreeString(self.raw);
}
@@ -166,7 +170,7 @@ impl fmt::Debug for BnString {
}
impl CoreArrayProvider for BnString {
- type Raw = *mut raw::c_char;
+ type Raw = *mut c_char;
type Context = ();
type Wrapped<'a> = &'a str;
}
@@ -176,6 +180,7 @@ unsafe impl CoreArrayProviderInner for BnString {
use binaryninjacore_sys::BNFreeStringList;
BNFreeStringList(raw, count);
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
CStr::from_ptr(*raw).to_str().unwrap()
}
@@ -183,6 +188,7 @@ unsafe impl CoreArrayProviderInner for BnString {
pub unsafe trait BnStrCompatible {
type Result: AsRef<[u8]>;
+
fn into_bytes_with_nul(self) -> Self::Result;
}
@@ -210,7 +216,7 @@ unsafe impl BnStrCompatible for CString {
}
}
-unsafe impl<'a> BnStrCompatible for &'a str {
+unsafe impl BnStrCompatible for &str {
type Result = Vec<u8>;
fn into_bytes_with_nul(self) -> Self::Result {
@@ -227,7 +233,7 @@ unsafe impl BnStrCompatible for String {
}
}
-unsafe impl<'a> BnStrCompatible for &'a String {
+unsafe impl BnStrCompatible for &String {
type Result = Vec<u8>;
fn into_bytes_with_nul(self) -> Self::Result {
@@ -243,21 +249,47 @@ unsafe impl<'a> BnStrCompatible for &'a Cow<'a, str> {
}
}
+unsafe impl BnStrCompatible for Cow<'_, str> {
+ type Result = Vec<u8>;
+
+ fn into_bytes_with_nul(self) -> Self::Result {
+ self.to_string().into_bytes_with_nul()
+ }
+}
+
unsafe impl BnStrCompatible for &QualifiedName {
type Result = Vec<u8>;
fn into_bytes_with_nul(self) -> Self::Result {
- self.string().into_bytes_with_nul()
+ self.to_string().into_bytes_with_nul()
+ }
+}
+
+unsafe impl BnStrCompatible for PathBuf {
+ type Result = Vec<u8>;
+
+ fn into_bytes_with_nul(self) -> Self::Result {
+ self.as_path().into_bytes_with_nul()
+ }
+}
+
+unsafe impl BnStrCompatible for &Path {
+ type Result = Vec<u8>;
+
+ fn into_bytes_with_nul(self) -> Self::Result {
+ self.as_os_str().as_encoded_bytes().to_vec()
}
}
pub trait IntoJson {
type Output: BnStrCompatible;
+
fn get_json_string(self) -> Result<Self::Output, ()>;
}
impl<S: BnStrCompatible> IntoJson for S {
type Output = S;
+
fn get_json_string(self) -> Result<Self::Output, ()> {
Ok(self)
}