summaryrefslogtreecommitdiff
path: root/rust/src/metadata.rs
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2022-07-18 19:53:47 -0400
committerGlenn Smith <glenn@vector35.com>2022-09-29 21:02:21 -0400
commitad27532d344d3bf2995f623002753d2845c6ce20 (patch)
tree772db0ae0fc09993fcd3f13f62628cba3414d95b /rust/src/metadata.rs
parent90a3729620e85f66b8fa5d385ead21ac581a1cc5 (diff)
[Rust API] Add support for Metadata
Diffstat (limited to 'rust/src/metadata.rs')
-rw-r--r--rust/src/metadata.rs652
1 files changed, 652 insertions, 0 deletions
diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs
new file mode 100644
index 00000000..f7d5e45e
--- /dev/null
+++ b/rust/src/metadata.rs
@@ -0,0 +1,652 @@
+#[allow(non_snake_case)]
+use crate::rc::{
+ Array, CoreArrayProvider, CoreArrayWrapper, CoreOwnedArrayProvider, Guard, Ref, RefCountable,
+};
+use crate::string::{BnStrCompatible, BnString};
+use binaryninjacore_sys::*;
+use std::collections::HashMap;
+use std::convert::TryFrom;
+use std::ffi::CStr;
+use std::ops::Index;
+use std::os::raw::c_char;
+use std::slice;
+
+pub type MetadataType = BNMetadataType;
+
+pub struct Metadata {
+ handle: *mut BNMetadata,
+}
+
+impl Metadata {
+ pub(crate) unsafe fn from_raw(handle: *mut BNMetadata) -> Self {
+ debug_assert!(!handle.is_null());
+
+ Self { handle }
+ }
+
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNMetadata) -> Ref<Self> {
+ Ref::new(Self::from_raw(handle))
+ }
+
+ pub fn get_type(&self) -> MetadataType {
+ unsafe { BNMetadataGetType(self.handle) }
+ }
+
+ pub fn get_boolean(&self) -> Result<bool, ()> {
+ match self.get_type() {
+ MetadataType::BooleanDataType => Ok(unsafe { BNMetadataGetBoolean(self.handle) }),
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_unsigned_integer(&self) -> Result<u64, ()> {
+ match self.get_type() {
+ MetadataType::UnsignedIntegerDataType => {
+ Ok(unsafe { BNMetadataGetUnsignedInteger(self.handle) })
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_signed_integer(&self) -> Result<i64, ()> {
+ match self.get_type() {
+ MetadataType::SignedIntegerDataType => {
+ Ok(unsafe { BNMetadataGetSignedInteger(self.handle) })
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_double(&self) -> Result<f64, ()> {
+ match self.get_type() {
+ MetadataType::DoubleDataType => Ok(unsafe { BNMetadataGetDouble(self.handle) }),
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_string(&self) -> Result<BnString, ()> {
+ match self.get_type() {
+ MetadataType::StringDataType => {
+ let ptr: *mut c_char = unsafe { BNMetadataGetString(self.handle) };
+ if ptr.is_null() {
+ return Err(());
+ }
+ Ok(unsafe { BnString::from_raw(ptr) })
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_boolean_list(&self) -> Result<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(());
+ }
+ let list = unsafe { slice::from_raw_parts(ptr, size) };
+ let vec = Vec::from(list);
+ unsafe { BNFreeMetadataBooleanList(ptr, size) };
+ Ok(vec)
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_unsigned_integer_list(&self) -> Result<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(());
+ }
+ let list = unsafe { slice::from_raw_parts(ptr, size) };
+ let vec = Vec::from(list);
+ unsafe { BNFreeMetadataUnsignedIntegerList(ptr, size) };
+ Ok(vec)
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_signed_integer_list(&self) -> Result<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(());
+ }
+ let list = unsafe { slice::from_raw_parts(ptr, size) };
+ let vec = Vec::from(list);
+ unsafe { BNFreeMetadataSignedIntegerList(ptr, size) };
+ Ok(vec)
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_double_list(&self) -> Result<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(());
+ }
+ let list = unsafe { slice::from_raw_parts(ptr, size) };
+ let vec = Vec::from(list);
+ unsafe { BNFreeMetadataDoubleList(ptr, size) };
+ Ok(vec)
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_string_list(&self) -> Result<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(());
+ }
+ let list = unsafe { slice::from_raw_parts(ptr, size) };
+ let vec = list
+ .iter()
+ .map(|ptr| unsafe { BnString::from_raw(*ptr) })
+ .collect::<Vec<_>>();
+ unsafe { BNFreeMetadataStringList(ptr, size) };
+ Ok(vec)
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_raw(&self) -> Result<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(());
+ }
+
+ let list = unsafe { slice::from_raw_parts(ptr, size) };
+ let vec = Vec::from(list);
+ unsafe { BNFreeMetadataRaw(ptr) };
+ Ok(vec)
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_array(&self) -> Result<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(());
+ }
+
+ Ok(unsafe { Array::new(ptr, size, ()) })
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn get_value_store(&self) -> Result<HashMap<BnString, Ref<Metadata>>, ()> {
+ match self.get_type() {
+ MetadataType::KeyValueDataType => {
+ let ptr: *mut BNMetadataValueStore =
+ unsafe { BNMetadataGetValueStore(self.handle) };
+ if ptr.is_null() {
+ return Err(());
+ }
+
+ let size = unsafe { (*ptr).size };
+ let keys_ptr: *mut *mut c_char = unsafe { (*ptr).keys };
+ let keys = unsafe { slice::from_raw_parts(keys_ptr, size) };
+ let values_ptr: *mut *mut BNMetadata = unsafe { (*ptr).values };
+ let values: &[*mut BNMetadata] = unsafe { slice::from_raw_parts(values_ptr, size) };
+
+ let mut map = HashMap::new();
+ for i in 0..size {
+ let key = unsafe { BnString::from_raw(keys[i]) };
+
+ let value = unsafe {
+ Ref::<Metadata>::new(Self {
+ handle: BNNewMetadataReference(values[i]),
+ })
+ };
+ map.insert(key, value);
+ }
+
+ Ok(map)
+ }
+ _ => Err(()),
+ }
+ }
+
+ pub fn len(&self) -> usize {
+ unsafe { BNMetadataSize(self.handle) }
+ }
+
+ pub fn index(&self, index: usize) -> Result<Option<Ref<Metadata>>, ()> {
+ if self.get_type() != MetadataType::ArrayDataType {
+ return Err(());
+ }
+ let ptr: *mut BNMetadata = unsafe { BNMetadataGetForIndex(self.handle, index) };
+ if ptr.is_null() {
+ return Ok(None);
+ }
+ Ok(Some(unsafe { Self::ref_from_raw(ptr) }))
+ }
+
+ pub fn get<S: BnStrCompatible>(&self, key: S) -> Result<Option<Ref<Metadata>>, ()> {
+ if self.get_type() != MetadataType::KeyValueDataType {
+ return Err(());
+ }
+ let ptr: *mut BNMetadata = unsafe {
+ BNMetadataGetForKey(
+ self.handle,
+ key.as_bytes_with_nul().as_ref().as_ptr() as *const c_char,
+ )
+ };
+ if ptr.is_null() {
+ return Ok(None);
+ }
+ Ok(Some(unsafe { Self::ref_from_raw(ptr) }))
+ }
+
+ pub fn push(&self, value: &Metadata) -> Result<(), ()> {
+ if self.get_type() != MetadataType::ArrayDataType {
+ return Err(());
+ }
+ unsafe { BNMetadataArrayAppend(self.handle, value.handle) };
+ Ok(())
+ }
+
+ pub fn insert<S: BnStrCompatible>(&self, key: S, value: &Metadata) -> Result<(), ()> {
+ if self.get_type() != MetadataType::KeyValueDataType {
+ return Err(());
+ }
+
+ unsafe {
+ BNMetadataSetValueForKey(
+ self.handle,
+ key.as_bytes_with_nul().as_ref().as_ptr() as *const c_char,
+ value.handle,
+ )
+ };
+ Ok(())
+ }
+
+ pub fn remove_index(&self, index: usize) -> Result<(), ()> {
+ if self.get_type() != MetadataType::ArrayDataType {
+ return Err(());
+ }
+
+ unsafe { BNMetadataRemoveIndex(self.handle, index) };
+ Ok(())
+ }
+
+ pub fn remove_key<S: BnStrCompatible>(&self, key: S) -> Result<(), ()> {
+ if self.get_type() != MetadataType::KeyValueDataType {
+ return Err(());
+ }
+
+ unsafe {
+ BNMetadataRemoveKey(
+ self.handle,
+ key.as_bytes_with_nul().as_ref().as_ptr() as *const c_char,
+ )
+ };
+ Ok(())
+ }
+}
+
+unsafe impl Sync for Metadata {}
+unsafe impl Send for Metadata {}
+
+unsafe impl RefCountable for Metadata {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: BNNewMetadataReference(handle.handle),
+ })
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeMetadata(handle.handle);
+ }
+}
+
+impl CoreArrayProvider for Metadata {
+ type Raw = *mut BNMetadata;
+ type Context = ();
+}
+
+unsafe impl CoreOwnedArrayProvider for Metadata {
+ unsafe fn free(raw: *mut *mut BNMetadata, _count: usize, _context: &()) {
+ BNFreeMetadataArray(raw);
+ }
+}
+
+unsafe impl<'a> CoreArrayWrapper<'a> for Metadata {
+ type Wrapped = Guard<'a, Metadata>;
+
+ unsafe fn wrap_raw(raw: &'a *mut BNMetadata, context: &'a ()) -> Guard<'a, Metadata> {
+ Guard::new(Metadata::from_raw(*raw), context)
+ }
+}
+
+impl AsRef<Metadata> for Metadata {
+ fn as_ref(&self) -> &Self {
+ self
+ }
+}
+
+impl ToOwned for Metadata {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+impl From<bool> for Ref<Metadata> {
+ fn from(value: bool) -> Self {
+ unsafe { Metadata::ref_from_raw(BNCreateMetadataBooleanData(value)) }
+ }
+}
+
+impl From<u64> for Ref<Metadata> {
+ fn from(value: u64) -> Self {
+ unsafe { Metadata::ref_from_raw(BNCreateMetadataUnsignedIntegerData(value)) }
+ }
+}
+
+impl From<i64> for Ref<Metadata> {
+ fn from(value: i64) -> Self {
+ unsafe { Metadata::ref_from_raw(BNCreateMetadataSignedIntegerData(value)) }
+ }
+}
+
+impl From<f64> for Ref<Metadata> {
+ fn from(value: f64) -> Self {
+ unsafe { Metadata::ref_from_raw(BNCreateMetadataDoubleData(value)) }
+ }
+}
+
+impl<S: BnStrCompatible> From<S> for Ref<Metadata> {
+ fn from(value: S) -> Self {
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataStringData(
+ value.as_bytes_with_nul().as_ref().as_ptr() as *const c_char,
+ ))
+ }
+ }
+}
+
+impl From<&Vec<u8>> for Ref<Metadata> {
+ fn from(value: &Vec<u8>) -> Self {
+ unsafe { Metadata::ref_from_raw(BNCreateMetadataRawData(value.as_ptr(), value.len())) }
+ }
+}
+
+impl From<&Vec<Ref<Metadata>>> for Ref<Metadata> {
+ fn from(value: &Vec<Ref<Metadata>>) -> Self {
+ let mut pointers: Vec<*mut BNMetadata> = vec![];
+ for v in value.iter() {
+ pointers.push(v.as_ref().handle);
+ }
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataArray(pointers.as_mut_ptr(), pointers.len()))
+ }
+ }
+}
+
+impl From<&Array<Metadata>> for Ref<Metadata> {
+ fn from(value: &Array<Metadata>) -> Self {
+ let mut pointers: Vec<*mut BNMetadata> = vec![];
+ for v in value.iter() {
+ pointers.push(v.as_ref().handle);
+ }
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataArray(pointers.as_mut_ptr(), pointers.len()))
+ }
+ }
+}
+
+impl<S: BnStrCompatible> From<HashMap<S, Ref<Metadata>>> for Ref<Metadata> {
+ fn from(value: HashMap<S, Ref<Metadata>>) -> Self {
+ let mut key_refs: Vec<S::Result> = vec![];
+ let mut keys: Vec<*const c_char> = vec![];
+ let mut values: Vec<*mut BNMetadata> = vec![];
+ for (k, v) in value.into_iter() {
+ key_refs.push(k.as_bytes_with_nul());
+ values.push(v.as_ref().handle);
+ }
+ for k in &key_refs {
+ keys.push(k.as_ref().as_ptr() as *const c_char);
+ }
+
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataValueStore(
+ keys.as_mut_ptr(),
+ values.as_mut_ptr(),
+ keys.len(),
+ ))
+ }
+ }
+}
+
+impl From<&Vec<bool>> for Ref<Metadata> {
+ fn from(value: &Vec<bool>) -> Self {
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataBooleanListData(
+ value.as_ptr() as *mut bool,
+ value.len(),
+ ))
+ }
+ }
+}
+
+impl From<&Vec<u64>> for Ref<Metadata> {
+ fn from(value: &Vec<u64>) -> Self {
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataUnsignedIntegerListData(
+ value.as_ptr() as *mut u64,
+ value.len(),
+ ))
+ }
+ }
+}
+
+impl From<&Vec<i64>> for Ref<Metadata> {
+ fn from(value: &Vec<i64>) -> Self {
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataSignedIntegerListData(
+ value.as_ptr() as *mut i64,
+ value.len(),
+ ))
+ }
+ }
+}
+
+impl From<&Vec<f64>> for Ref<Metadata> {
+ fn from(value: &Vec<f64>) -> Self {
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataDoubleListData(
+ value.as_ptr() as *mut f64,
+ value.len(),
+ ))
+ }
+ }
+}
+
+impl<S: BnStrCompatible> From<Vec<S>> for Ref<Metadata> {
+ fn from(value: Vec<S>) -> Self {
+ let mut refs = vec![];
+ for v in value {
+ refs.push(v.as_bytes_with_nul());
+ }
+ let mut pointers = vec![];
+ for r in &refs {
+ pointers.push(r.as_ref().as_ptr() as *const c_char);
+ }
+ unsafe {
+ Metadata::ref_from_raw(BNCreateMetadataStringListData(
+ pointers.as_ptr() as *mut *const c_char,
+ pointers.len(),
+ ))
+ }
+ }
+}
+
+impl PartialEq<Self> for Ref<Metadata> {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe { BNMetadataIsEqual(self.as_ref().handle, other.as_ref().handle) }
+ }
+}
+
+impl Eq for Ref<Metadata> {}
+
+impl TryFrom<&Metadata> for bool {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_boolean()
+ }
+}
+
+impl TryFrom<&Metadata> for u64 {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_unsigned_integer()
+ }
+}
+
+impl TryFrom<&Metadata> for i64 {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_signed_integer()
+ }
+}
+
+impl TryFrom<&Metadata> for f64 {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_double()
+ }
+}
+
+impl TryFrom<&Metadata> for BnString {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_string()
+ }
+}
+
+impl TryFrom<&Metadata> for String {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_string().map(|s| s.to_string())
+ }
+}
+
+impl TryFrom<&Metadata> for Vec<bool> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_boolean_list()
+ }
+}
+
+impl TryFrom<&Metadata> for Vec<u64> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_unsigned_integer_list()
+ }
+}
+
+impl TryFrom<&Metadata> for Vec<i64> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_signed_integer_list()
+ }
+}
+
+impl TryFrom<&Metadata> for Vec<f64> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_double_list()
+ }
+}
+
+impl TryFrom<&Metadata> for Vec<BnString> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_string_list()
+ }
+}
+
+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()).collect())
+ }
+}
+
+impl TryFrom<&Metadata> for Vec<u8> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_raw()
+ }
+}
+
+impl TryFrom<&Metadata> for Array<Metadata> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_array()
+ }
+}
+
+impl TryFrom<&Metadata> for HashMap<BnString, Ref<Metadata>> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value.get_value_store()
+ }
+}
+
+impl TryFrom<&Metadata> for HashMap<String, Ref<Metadata>> {
+ type Error = ();
+
+ fn try_from(value: &Metadata) -> Result<Self, Self::Error> {
+ value
+ .get_value_store()
+ .map(|m| m.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
+ }
+}