Loading libs/binder/rust/src/persistable_bundle.rs +117 −9 Original line number Diff line number Diff line Loading @@ -22,17 +22,18 @@ use crate::{ }; use binder_ndk_sys::{ APersistableBundle, APersistableBundle_delete, APersistableBundle_dup, APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getDouble, APersistableBundle_getInt, APersistableBundle_getLong, APersistableBundle_getPersistableBundle, APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_putBoolean, APersistableBundle_putBooleanVector, APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt, APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector, APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanVector, APersistableBundle_getDouble, APersistableBundle_getDoubleVector, APersistableBundle_getInt, APersistableBundle_getIntVector, APersistableBundle_getLong, APersistableBundle_getLongVector, APersistableBundle_getPersistableBundle, APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_putBoolean, APersistableBundle_putBooleanVector, APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt, APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector, APersistableBundle_putPersistableBundle, APersistableBundle_putString, APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size, APersistableBundle_writeToParcel, APersistableBundle_writeToParcel, APERSISTABLEBUNDLE_KEY_NOT_FOUND, }; use std::ffi::{CString, NulError}; use std::ffi::{c_char, CString, NulError}; use std::ptr::{null_mut, NonNull}; /// A mapping from string keys to values of various types. Loading Loading @@ -373,6 +374,104 @@ impl PersistableBundle { } } /// Gets the vector of `T` associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. /// /// `get_func` should be one of the `APersistableBundle_get*Vector` functions from /// `binder_ndk_sys`. /// /// # Safety /// /// `get_func` must only require that the pointers it takes are valid for the duration of the /// call. It must allow a null pointer for the buffer, and must return the size in bytes of /// buffer it requires. If it is given a non-null buffer pointer it must write that number of /// bytes to the buffer, which must be a whole number of valid `T` values. unsafe fn get_vec<T: Clone + Default>( &self, key: &str, get_func: unsafe extern "C" fn( *const APersistableBundle, *const c_char, *mut T, i32, ) -> i32, ) -> Result<Option<Vec<T>>, NulError> { let key = CString::new(key)?; // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed // to be valid for the lifetime of `key`. A null pointer is allowed for the buffer. match unsafe { get_func(self.0.as_ptr(), key.as_ptr(), null_mut(), 0) } { APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None), required_buffer_size => { let mut value = vec![ T::default(); usize::try_from(required_buffer_size).expect( "APersistableBundle_get*Vector returned invalid size" ) / size_of::<T>() ]; // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for // the lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` // is guaranteed to be valid for the lifetime of `key`. The value buffer pointer is // valid as it comes from the Vec we just allocated. match unsafe { get_func( self.0.as_ptr(), key.as_ptr(), value.as_mut_ptr(), (value.len() * size_of::<T>()).try_into().unwrap(), ) } { APERSISTABLEBUNDLE_KEY_NOT_FOUND => { panic!("APersistableBundle_get*Vector failed to find key after first finding it"); } _ => Ok(Some(value)), } } } } /// Gets the boolean vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_bool_vec(&self, key: &str) -> Result<Option<Vec<bool>>, NulError> { // SAFETY: APersistableBundle_getBooleanVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getBooleanVector) } } /// Gets the i32 vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_int_vec(&self, key: &str) -> Result<Option<Vec<i32>>, NulError> { // SAFETY: APersistableBundle_getIntVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getIntVector) } } /// Gets the i64 vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_long_vec(&self, key: &str) -> Result<Option<Vec<i64>>, NulError> { // SAFETY: APersistableBundle_getLongVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getLongVector) } } /// Gets the f64 vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_double_vec(&self, key: &str) -> Result<Option<Vec<f64>>, NulError> { // SAFETY: APersistableBundle_getDoubleVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getDoubleVector) } } /// Gets the `PersistableBundle` value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist Loading Loading @@ -486,6 +585,10 @@ mod test { assert_eq!(bundle.get_int("foo"), Ok(None)); assert_eq!(bundle.get_long("foo"), Ok(None)); assert_eq!(bundle.get_double("foo"), Ok(None)); assert_eq!(bundle.get_bool_vec("foo"), Ok(None)); assert_eq!(bundle.get_int_vec("foo"), Ok(None)); assert_eq!(bundle.get_long_vec("foo"), Ok(None)); assert_eq!(bundle.get_double_vec("foo"), Ok(None)); } #[test] Loading Loading @@ -543,7 +646,7 @@ mod test { } #[test] fn insert_vec() { fn insert_get_vec() { let mut bundle = PersistableBundle::new(); assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(())); Loading @@ -567,6 +670,11 @@ mod test { ); assert_eq!(bundle.size(), 5); assert_eq!(bundle.get_bool_vec("bool"), Ok(Some(vec![]))); assert_eq!(bundle.get_int_vec("int"), Ok(Some(vec![42]))); assert_eq!(bundle.get_long_vec("long"), Ok(Some(vec![66, 67, 68]))); assert_eq!(bundle.get_double_vec("double"), Ok(Some(vec![123.4]))); } #[test] Loading libs/binder/rust/sys/BinderBindings.hpp +5 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,11 @@ enum { #endif }; enum { APERSISTABLEBUNDLE_KEY_NOT_FOUND = APERSISTABLEBUNDLE_KEY_NOT_FOUND, APERSISTABLEBUNDLE_ALLOCATOR_FAILED = APERSISTABLEBUNDLE_ALLOCATOR_FAILED, }; } // namespace consts } // namespace c_interface Loading Loading
libs/binder/rust/src/persistable_bundle.rs +117 −9 Original line number Diff line number Diff line Loading @@ -22,17 +22,18 @@ use crate::{ }; use binder_ndk_sys::{ APersistableBundle, APersistableBundle_delete, APersistableBundle_dup, APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getDouble, APersistableBundle_getInt, APersistableBundle_getLong, APersistableBundle_getPersistableBundle, APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_putBoolean, APersistableBundle_putBooleanVector, APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt, APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector, APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanVector, APersistableBundle_getDouble, APersistableBundle_getDoubleVector, APersistableBundle_getInt, APersistableBundle_getIntVector, APersistableBundle_getLong, APersistableBundle_getLongVector, APersistableBundle_getPersistableBundle, APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_putBoolean, APersistableBundle_putBooleanVector, APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt, APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector, APersistableBundle_putPersistableBundle, APersistableBundle_putString, APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size, APersistableBundle_writeToParcel, APersistableBundle_writeToParcel, APERSISTABLEBUNDLE_KEY_NOT_FOUND, }; use std::ffi::{CString, NulError}; use std::ffi::{c_char, CString, NulError}; use std::ptr::{null_mut, NonNull}; /// A mapping from string keys to values of various types. Loading Loading @@ -373,6 +374,104 @@ impl PersistableBundle { } } /// Gets the vector of `T` associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. /// /// `get_func` should be one of the `APersistableBundle_get*Vector` functions from /// `binder_ndk_sys`. /// /// # Safety /// /// `get_func` must only require that the pointers it takes are valid for the duration of the /// call. It must allow a null pointer for the buffer, and must return the size in bytes of /// buffer it requires. If it is given a non-null buffer pointer it must write that number of /// bytes to the buffer, which must be a whole number of valid `T` values. unsafe fn get_vec<T: Clone + Default>( &self, key: &str, get_func: unsafe extern "C" fn( *const APersistableBundle, *const c_char, *mut T, i32, ) -> i32, ) -> Result<Option<Vec<T>>, NulError> { let key = CString::new(key)?; // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed // to be valid for the lifetime of `key`. A null pointer is allowed for the buffer. match unsafe { get_func(self.0.as_ptr(), key.as_ptr(), null_mut(), 0) } { APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None), required_buffer_size => { let mut value = vec![ T::default(); usize::try_from(required_buffer_size).expect( "APersistableBundle_get*Vector returned invalid size" ) / size_of::<T>() ]; // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for // the lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` // is guaranteed to be valid for the lifetime of `key`. The value buffer pointer is // valid as it comes from the Vec we just allocated. match unsafe { get_func( self.0.as_ptr(), key.as_ptr(), value.as_mut_ptr(), (value.len() * size_of::<T>()).try_into().unwrap(), ) } { APERSISTABLEBUNDLE_KEY_NOT_FOUND => { panic!("APersistableBundle_get*Vector failed to find key after first finding it"); } _ => Ok(Some(value)), } } } } /// Gets the boolean vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_bool_vec(&self, key: &str) -> Result<Option<Vec<bool>>, NulError> { // SAFETY: APersistableBundle_getBooleanVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getBooleanVector) } } /// Gets the i32 vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_int_vec(&self, key: &str) -> Result<Option<Vec<i32>>, NulError> { // SAFETY: APersistableBundle_getIntVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getIntVector) } } /// Gets the i64 vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_long_vec(&self, key: &str) -> Result<Option<Vec<i64>>, NulError> { // SAFETY: APersistableBundle_getLongVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getLongVector) } } /// Gets the f64 vector value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist /// in the bundle. pub fn get_double_vec(&self, key: &str) -> Result<Option<Vec<f64>>, NulError> { // SAFETY: APersistableBundle_getDoubleVector fulfils all the safety requirements of // `get_vec`. unsafe { self.get_vec(key, APersistableBundle_getDoubleVector) } } /// Gets the `PersistableBundle` value associated with the given key. /// /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist Loading Loading @@ -486,6 +585,10 @@ mod test { assert_eq!(bundle.get_int("foo"), Ok(None)); assert_eq!(bundle.get_long("foo"), Ok(None)); assert_eq!(bundle.get_double("foo"), Ok(None)); assert_eq!(bundle.get_bool_vec("foo"), Ok(None)); assert_eq!(bundle.get_int_vec("foo"), Ok(None)); assert_eq!(bundle.get_long_vec("foo"), Ok(None)); assert_eq!(bundle.get_double_vec("foo"), Ok(None)); } #[test] Loading Loading @@ -543,7 +646,7 @@ mod test { } #[test] fn insert_vec() { fn insert_get_vec() { let mut bundle = PersistableBundle::new(); assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(())); Loading @@ -567,6 +670,11 @@ mod test { ); assert_eq!(bundle.size(), 5); assert_eq!(bundle.get_bool_vec("bool"), Ok(Some(vec![]))); assert_eq!(bundle.get_int_vec("int"), Ok(Some(vec![42]))); assert_eq!(bundle.get_long_vec("long"), Ok(Some(vec![66, 67, 68]))); assert_eq!(bundle.get_double_vec("double"), Ok(Some(vec![123.4]))); } #[test] Loading
libs/binder/rust/sys/BinderBindings.hpp +5 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,11 @@ enum { #endif }; enum { APERSISTABLEBUNDLE_KEY_NOT_FOUND = APERSISTABLEBUNDLE_KEY_NOT_FOUND, APERSISTABLEBUNDLE_ALLOCATOR_FAILED = APERSISTABLEBUNDLE_ALLOCATOR_FAILED, }; } // namespace consts } // namespace c_interface Loading