summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-05-07 23:22:48 -0400
committerMason Reed <35282038+emesare@users.noreply.github.com>2025-05-12 17:45:24 -0400
commit3992860ca7d636661d7b2671d5fe7cf028987be1 (patch)
treec5613a3ce749a6866f40a734571752b248258e7b /rust/src
parentd5c4ea4018432750999e5ef11f83736bc8612a03 (diff)
[Rust] Metadata API improvements
- Don't use Result for some or none values - Fix freeing of key value store objects - Improve ergonomics a little bit - Add unit tests
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/metadata.rs173
1 files changed, 88 insertions, 85 deletions
diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs
index 6cf1cbce..e541577d 100644
--- a/rust/src/metadata.rs
+++ b/rust/src/metadata.rs
@@ -1,5 +1,5 @@
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
-use crate::string::{BnString, IntoCStr, IntoJson};
+use crate::string::{raw_to_string, BnString, IntoCStr, IntoJson};
use binaryninjacore_sys::*;
use std::collections::HashMap;
use std::os::raw::c_char;
@@ -30,129 +30,129 @@ impl Metadata {
unsafe { BNMetadataGetType(self.handle) }
}
- pub fn get_boolean(&self) -> Result<bool, ()> {
+ pub fn get_boolean(&self) -> Option<bool> {
match self.get_type() {
- MetadataType::BooleanDataType => Ok(unsafe { BNMetadataGetBoolean(self.handle) }),
- _ => Err(()),
+ MetadataType::BooleanDataType => Some(unsafe { BNMetadataGetBoolean(self.handle) }),
+ _ => None,
}
}
- pub fn get_unsigned_integer(&self) -> Result<u64, ()> {
+ pub fn get_unsigned_integer(&self) -> Option<u64> {
match self.get_type() {
MetadataType::UnsignedIntegerDataType => {
- Ok(unsafe { BNMetadataGetUnsignedInteger(self.handle) })
+ Some(unsafe { BNMetadataGetUnsignedInteger(self.handle) })
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_signed_integer(&self) -> Result<i64, ()> {
+ pub fn get_signed_integer(&self) -> Option<i64> {
match self.get_type() {
MetadataType::SignedIntegerDataType => {
- Ok(unsafe { BNMetadataGetSignedInteger(self.handle) })
+ Some(unsafe { BNMetadataGetSignedInteger(self.handle) })
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_double(&self) -> Result<f64, ()> {
+ pub fn get_double(&self) -> Option<f64> {
match self.get_type() {
- MetadataType::DoubleDataType => Ok(unsafe { BNMetadataGetDouble(self.handle) }),
- _ => Err(()),
+ MetadataType::DoubleDataType => Some(unsafe { BNMetadataGetDouble(self.handle) }),
+ _ => None,
}
}
- pub fn get_string(&self) -> Result<BnString, ()> {
+ pub fn get_string(&self) -> Option<BnString> {
match self.get_type() {
MetadataType::StringDataType => {
let ptr: *mut c_char = unsafe { BNMetadataGetString(self.handle) };
if ptr.is_null() {
- return Err(());
+ return None;
}
- Ok(unsafe { BnString::from_raw(ptr) })
+ Some(unsafe { BnString::from_raw(ptr) })
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_boolean_list(&self) -> Result<Vec<bool>, ()> {
+ pub fn get_boolean_list(&self) -> Option<Vec<bool>> {
match self.get_type() {
MetadataType::ArrayDataType => {
let mut size: usize = 0;
let ptr: *mut bool = unsafe { BNMetadataGetBooleanList(self.handle, &mut size) };
if ptr.is_null() {
- return Err(());
+ return None;
}
let list = unsafe { slice::from_raw_parts(ptr, size) };
let vec = Vec::from(list);
unsafe { BNFreeMetadataBooleanList(ptr, size) };
- Ok(vec)
+ Some(vec)
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_unsigned_integer_list(&self) -> Result<Vec<u64>, ()> {
+ pub fn get_unsigned_integer_list(&self) -> Option<Vec<u64>> {
match self.get_type() {
MetadataType::ArrayDataType => {
let mut size: usize = 0;
let ptr: *mut u64 =
unsafe { BNMetadataGetUnsignedIntegerList(self.handle, &mut size) };
if ptr.is_null() {
- return Err(());
+ return None;
}
let list = unsafe { slice::from_raw_parts(ptr, size) };
let vec = Vec::from(list);
unsafe { BNFreeMetadataUnsignedIntegerList(ptr, size) };
- Ok(vec)
+ Some(vec)
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_signed_integer_list(&self) -> Result<Vec<i64>, ()> {
+ pub fn get_signed_integer_list(&self) -> Option<Vec<i64>> {
match self.get_type() {
MetadataType::ArrayDataType => {
let mut size: usize = 0;
let ptr: *mut i64 =
unsafe { BNMetadataGetSignedIntegerList(self.handle, &mut size) };
if ptr.is_null() {
- return Err(());
+ return None;
}
let list = unsafe { slice::from_raw_parts(ptr, size) };
let vec = Vec::from(list);
unsafe { BNFreeMetadataSignedIntegerList(ptr, size) };
- Ok(vec)
+ Some(vec)
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_double_list(&self) -> Result<Vec<f64>, ()> {
+ pub fn get_double_list(&self) -> Option<Vec<f64>> {
match self.get_type() {
MetadataType::ArrayDataType => {
let mut size: usize = 0;
let ptr: *mut f64 = unsafe { BNMetadataGetDoubleList(self.handle, &mut size) };
if ptr.is_null() {
- return Err(());
+ return None;
}
let list = unsafe { slice::from_raw_parts(ptr, size) };
let vec = Vec::from(list);
unsafe { BNFreeMetadataDoubleList(ptr, size) };
- Ok(vec)
+ Some(vec)
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_string_list(&self) -> Result<Vec<BnString>, ()> {
+ pub fn get_string_list(&self) -> Option<Vec<BnString>> {
match self.get_type() {
MetadataType::ArrayDataType => {
let mut size: usize = 0;
let ptr: *mut *mut c_char =
unsafe { BNMetadataGetStringList(self.handle, &mut size) };
if ptr.is_null() {
- return Err(());
+ return None;
}
let list = unsafe { slice::from_raw_parts(ptr, size) };
let vec = list
@@ -160,66 +160,66 @@ impl Metadata {
.map(|ptr| unsafe { BnString::from_raw(*ptr) })
.collect::<Vec<_>>();
unsafe { BNFreeMetadataStringList(ptr, size) };
- Ok(vec)
+ Some(vec)
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_json_string(&self) -> Result<BnString, ()> {
+ pub fn get_json_string(&self) -> Option<BnString> {
match self.get_type() {
MetadataType::StringDataType => {
let ptr: *mut c_char = unsafe { BNMetadataGetJsonString(self.handle) };
if ptr.is_null() {
- return Err(());
+ return None;
}
- Ok(unsafe { BnString::from_raw(ptr) })
+ Some(unsafe { BnString::from_raw(ptr) })
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_raw(&self) -> Result<Vec<u8>, ()> {
+ pub fn get_raw(&self) -> Option<Vec<u8>> {
match self.get_type() {
MetadataType::RawDataType => {
let mut size: usize = 0;
let ptr: *mut u8 = unsafe { BNMetadataGetRaw(self.handle, &mut size) };
if ptr.is_null() {
- return Err(());
+ return None;
}
let list = unsafe { slice::from_raw_parts(ptr, size) };
let vec = Vec::from(list);
unsafe { BNFreeMetadataRaw(ptr) };
- Ok(vec)
+ Some(vec)
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_array(&self) -> Result<Array<Metadata>, ()> {
+ pub fn get_array(&self) -> Option<Array<Metadata>> {
match self.get_type() {
MetadataType::ArrayDataType => {
let mut size: usize = 0;
let ptr: *mut *mut BNMetadata =
unsafe { BNMetadataGetArray(self.handle, &mut size) };
if ptr.is_null() {
- return Err(());
+ return None;
}
- Ok(unsafe { Array::new(ptr, size, ()) })
+ Some(unsafe { Array::new(ptr, size, ()) })
}
- _ => Err(()),
+ _ => None,
}
}
- pub fn get_value_store(&self) -> Result<HashMap<String, Ref<Metadata>>, ()> {
+ pub fn get_value_store(&self) -> Option<HashMap<String, Ref<Metadata>>> {
match self.get_type() {
MetadataType::KeyValueDataType => {
let ptr: *mut BNMetadataValueStore =
unsafe { BNMetadataGetValueStore(self.handle) };
if ptr.is_null() {
- return Err(());
+ return None;
}
let size = unsafe { (*ptr).size };
@@ -230,21 +230,16 @@ impl Metadata {
let mut map = HashMap::new();
for i in 0..size {
- let key = unsafe { BnString::into_string(keys[i]) };
-
- let value = unsafe {
- Ref::<Metadata>::new(Self {
- handle: BNNewMetadataReference(values[i]),
- })
- };
+ let key = raw_to_string(keys[i]).unwrap();
+ let value = unsafe { Ref::<Metadata>::new(Self { handle: values[i] }) };
map.insert(key, value);
}
unsafe { BNFreeMetadataValueStore(ptr) };
- Ok(map)
+ Some(map)
}
- _ => Err(()),
+ _ => None,
}
}
@@ -424,10 +419,12 @@ impl From<&Array<Metadata>> for Ref<Metadata> {
}
}
-impl<S: IntoCStr> From<HashMap<S, Ref<Metadata>>> for Ref<Metadata> {
- fn from(value: HashMap<S, Ref<Metadata>>) -> Self {
- let data: Vec<(S::Result, Ref<Metadata>)> =
- value.into_iter().map(|(k, v)| (k.to_cstr(), v)).collect();
+impl<S: IntoCStr, T: Into<Ref<Metadata>>> From<HashMap<S, T>> for Ref<Metadata> {
+ fn from(value: HashMap<S, T>) -> Self {
+ let data: Vec<(S::Result, Ref<Metadata>)> = value
+ .into_iter()
+ .map(|(k, v)| (k.to_cstr(), v.into()))
+ .collect();
let mut keys: Vec<*const c_char> = data.iter().map(|(k, _)| k.as_ptr()).collect();
let mut values: Vec<*mut BNMetadata> = data.iter().map(|(_, v)| v.handle).collect();
@@ -549,7 +546,7 @@ impl TryFrom<&Metadata> for bool {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_boolean()
+ value.get_boolean().ok_or(())
}
}
@@ -557,7 +554,7 @@ impl TryFrom<&Metadata> for u64 {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_unsigned_integer()
+ value.get_unsigned_integer().ok_or(())
}
}
@@ -565,7 +562,7 @@ impl TryFrom<&Metadata> for i64 {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_signed_integer()
+ value.get_signed_integer().ok_or(())
}
}
@@ -573,7 +570,7 @@ impl TryFrom<&Metadata> for f64 {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_double()
+ value.get_double().ok_or(())
}
}
@@ -581,7 +578,7 @@ impl TryFrom<&Metadata> for BnString {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_string()
+ value.get_string().ok_or(())
}
}
@@ -589,7 +586,10 @@ impl TryFrom<&Metadata> for String {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_string().map(|s| s.to_string_lossy().to_string())
+ value
+ .get_string()
+ .map(|s| s.to_string_lossy().to_string())
+ .ok_or(())
}
}
@@ -597,7 +597,7 @@ impl TryFrom<&Metadata> for Vec<bool> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_boolean_list()
+ value.get_boolean_list().ok_or(())
}
}
@@ -605,7 +605,7 @@ impl TryFrom<&Metadata> for Vec<u64> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_unsigned_integer_list()
+ value.get_unsigned_integer_list().ok_or(())
}
}
@@ -613,7 +613,7 @@ impl TryFrom<&Metadata> for Vec<i64> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_signed_integer_list()
+ value.get_signed_integer_list().ok_or(())
}
}
@@ -621,7 +621,7 @@ impl TryFrom<&Metadata> for Vec<f64> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_double_list()
+ value.get_double_list().ok_or(())
}
}
@@ -629,7 +629,7 @@ impl TryFrom<&Metadata> for Vec<BnString> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_string_list()
+ value.get_string_list().ok_or(())
}
}
@@ -637,11 +637,14 @@ impl TryFrom<&Metadata> for Vec<String> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_string_list().map(|v| {
- v.into_iter()
- .map(|s| s.to_string_lossy().to_string())
- .collect()
- })
+ value
+ .get_string_list()
+ .map(|v| {
+ v.into_iter()
+ .map(|s| s.to_string_lossy().to_string())
+ .collect()
+ })
+ .ok_or(())
}
}
@@ -649,7 +652,7 @@ impl TryFrom<&Metadata> for Vec<u8> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_raw()
+ value.get_raw().ok_or(())
}
}
@@ -657,7 +660,7 @@ impl TryFrom<&Metadata> for Array<Metadata> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_array()
+ value.get_array().ok_or(())
}
}
@@ -665,20 +668,20 @@ impl TryFrom<&Metadata> for HashMap<String, Ref<Metadata>> {
type Error = ();
fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
- value.get_value_store()
+ value.get_value_store().ok_or(())
}
}
impl IntoJson for &Metadata {
type Output = BnString;
fn get_json_string(self) -> Result<BnString, ()> {
- Metadata::get_json_string(self)
+ Metadata::get_json_string(self).ok_or(())
}
}
impl IntoJson for Ref<Metadata> {
type Output = BnString;
fn get_json_string(self) -> Result<BnString, ()> {
- Metadata::get_json_string(&self)
+ Metadata::get_json_string(&self).ok_or(())
}
}