diff options
| author | 2025-01-16 14:55:36 +0000 | |
|---|---|---|
| committer | 2025-01-20 18:39:11 +0000 | |
| commit | ba4ca763b33c6aa6657304a3d16bf3ae324d1063 (patch) | |
| tree | 5df304310ea6d02109c958213b2ca0e897d81460 | |
| parent | 19183730c838ea622b51e5e65adf9ac642264fe0 (diff) | |
Add methods to get vectors.
Bug: 389074518
Test: atest libbinder_rs-internal_test
Change-Id: Id26f265e6f3bea4a0149e28fa7dba6092b958dda
| -rw-r--r-- | libs/binder/rust/src/persistable_bundle.rs | 126 | ||||
| -rw-r--r-- | libs/binder/rust/sys/BinderBindings.hpp | 5 |
2 files changed, 122 insertions, 9 deletions
diff --git a/libs/binder/rust/src/persistable_bundle.rs b/libs/binder/rust/src/persistable_bundle.rs index 367f334803..d71ed73532 100644 --- a/libs/binder/rust/src/persistable_bundle.rs +++ b/libs/binder/rust/src/persistable_bundle.rs @@ -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. @@ -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 @@ -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] @@ -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(())); @@ -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] diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp index deeaa37b94..c19e375a97 100644 --- a/libs/binder/rust/sys/BinderBindings.hpp +++ b/libs/binder/rust/sys/BinderBindings.hpp @@ -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 |