Skip to content

Commit 430db86

Browse files
Treehugger RobotGerrit Code Review
authored andcommitted
Merge "Add methods to get vectors." into main
2 parents 52b4e75 + ba4ca76 commit 430db86

2 files changed

Lines changed: 122 additions & 9 deletions

File tree

libs/binder/rust/src/persistable_bundle.rs

Lines changed: 117 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@ use crate::{
2222
};
2323
use binder_ndk_sys::{
2424
APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
25-
APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getDouble,
26-
APersistableBundle_getInt, APersistableBundle_getLong, APersistableBundle_getPersistableBundle,
27-
APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_putBoolean,
28-
APersistableBundle_putBooleanVector, APersistableBundle_putDouble,
29-
APersistableBundle_putDoubleVector, APersistableBundle_putInt, APersistableBundle_putIntVector,
30-
APersistableBundle_putLong, APersistableBundle_putLongVector,
25+
APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanVector,
26+
APersistableBundle_getDouble, APersistableBundle_getDoubleVector, APersistableBundle_getInt,
27+
APersistableBundle_getIntVector, APersistableBundle_getLong, APersistableBundle_getLongVector,
28+
APersistableBundle_getPersistableBundle, APersistableBundle_isEqual, APersistableBundle_new,
29+
APersistableBundle_putBoolean, APersistableBundle_putBooleanVector,
30+
APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt,
31+
APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector,
3132
APersistableBundle_putPersistableBundle, APersistableBundle_putString,
3233
APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size,
33-
APersistableBundle_writeToParcel,
34+
APersistableBundle_writeToParcel, APERSISTABLEBUNDLE_KEY_NOT_FOUND,
3435
};
35-
use std::ffi::{CString, NulError};
36+
use std::ffi::{c_char, CString, NulError};
3637
use std::ptr::{null_mut, NonNull};
3738

3839
/// A mapping from string keys to values of various types.
@@ -373,6 +374,104 @@ impl PersistableBundle {
373374
}
374375
}
375376

377+
/// Gets the vector of `T` associated with the given key.
378+
///
379+
/// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
380+
/// in the bundle.
381+
///
382+
/// `get_func` should be one of the `APersistableBundle_get*Vector` functions from
383+
/// `binder_ndk_sys`.
384+
///
385+
/// # Safety
386+
///
387+
/// `get_func` must only require that the pointers it takes are valid for the duration of the
388+
/// call. It must allow a null pointer for the buffer, and must return the size in bytes of
389+
/// buffer it requires. If it is given a non-null buffer pointer it must write that number of
390+
/// bytes to the buffer, which must be a whole number of valid `T` values.
391+
unsafe fn get_vec<T: Clone + Default>(
392+
&self,
393+
key: &str,
394+
get_func: unsafe extern "C" fn(
395+
*const APersistableBundle,
396+
*const c_char,
397+
*mut T,
398+
i32,
399+
) -> i32,
400+
) -> Result<Option<Vec<T>>, NulError> {
401+
let key = CString::new(key)?;
402+
// SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
403+
// lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
404+
// to be valid for the lifetime of `key`. A null pointer is allowed for the buffer.
405+
match unsafe { get_func(self.0.as_ptr(), key.as_ptr(), null_mut(), 0) } {
406+
APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None),
407+
required_buffer_size => {
408+
let mut value = vec![
409+
T::default();
410+
usize::try_from(required_buffer_size).expect(
411+
"APersistableBundle_get*Vector returned invalid size"
412+
) / size_of::<T>()
413+
];
414+
// SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
415+
// the lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()`
416+
// is guaranteed to be valid for the lifetime of `key`. The value buffer pointer is
417+
// valid as it comes from the Vec we just allocated.
418+
match unsafe {
419+
get_func(
420+
self.0.as_ptr(),
421+
key.as_ptr(),
422+
value.as_mut_ptr(),
423+
(value.len() * size_of::<T>()).try_into().unwrap(),
424+
)
425+
} {
426+
APERSISTABLEBUNDLE_KEY_NOT_FOUND => {
427+
panic!("APersistableBundle_get*Vector failed to find key after first finding it");
428+
}
429+
_ => Ok(Some(value)),
430+
}
431+
}
432+
}
433+
}
434+
435+
/// Gets the boolean vector value associated with the given key.
436+
///
437+
/// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
438+
/// in the bundle.
439+
pub fn get_bool_vec(&self, key: &str) -> Result<Option<Vec<bool>>, NulError> {
440+
// SAFETY: APersistableBundle_getBooleanVector fulfils all the safety requirements of
441+
// `get_vec`.
442+
unsafe { self.get_vec(key, APersistableBundle_getBooleanVector) }
443+
}
444+
445+
/// Gets the i32 vector value associated with the given key.
446+
///
447+
/// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
448+
/// in the bundle.
449+
pub fn get_int_vec(&self, key: &str) -> Result<Option<Vec<i32>>, NulError> {
450+
// SAFETY: APersistableBundle_getIntVector fulfils all the safety requirements of
451+
// `get_vec`.
452+
unsafe { self.get_vec(key, APersistableBundle_getIntVector) }
453+
}
454+
455+
/// Gets the i64 vector value associated with the given key.
456+
///
457+
/// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
458+
/// in the bundle.
459+
pub fn get_long_vec(&self, key: &str) -> Result<Option<Vec<i64>>, NulError> {
460+
// SAFETY: APersistableBundle_getLongVector fulfils all the safety requirements of
461+
// `get_vec`.
462+
unsafe { self.get_vec(key, APersistableBundle_getLongVector) }
463+
}
464+
465+
/// Gets the f64 vector value associated with the given key.
466+
///
467+
/// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
468+
/// in the bundle.
469+
pub fn get_double_vec(&self, key: &str) -> Result<Option<Vec<f64>>, NulError> {
470+
// SAFETY: APersistableBundle_getDoubleVector fulfils all the safety requirements of
471+
// `get_vec`.
472+
unsafe { self.get_vec(key, APersistableBundle_getDoubleVector) }
473+
}
474+
376475
/// Gets the `PersistableBundle` value associated with the given key.
377476
///
378477
/// 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 {
486585
assert_eq!(bundle.get_int("foo"), Ok(None));
487586
assert_eq!(bundle.get_long("foo"), Ok(None));
488587
assert_eq!(bundle.get_double("foo"), Ok(None));
588+
assert_eq!(bundle.get_bool_vec("foo"), Ok(None));
589+
assert_eq!(bundle.get_int_vec("foo"), Ok(None));
590+
assert_eq!(bundle.get_long_vec("foo"), Ok(None));
591+
assert_eq!(bundle.get_double_vec("foo"), Ok(None));
489592
}
490593

491594
#[test]
@@ -543,7 +646,7 @@ mod test {
543646
}
544647

545648
#[test]
546-
fn insert_vec() {
649+
fn insert_get_vec() {
547650
let mut bundle = PersistableBundle::new();
548651

549652
assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(()));
@@ -567,6 +670,11 @@ mod test {
567670
);
568671

569672
assert_eq!(bundle.size(), 5);
673+
674+
assert_eq!(bundle.get_bool_vec("bool"), Ok(Some(vec![])));
675+
assert_eq!(bundle.get_int_vec("int"), Ok(Some(vec![42])));
676+
assert_eq!(bundle.get_long_vec("long"), Ok(Some(vec![66, 67, 68])));
677+
assert_eq!(bundle.get_double_vec("double"), Ok(Some(vec![123.4])));
570678
}
571679

572680
#[test]

libs/binder/rust/sys/BinderBindings.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ enum {
9292
#endif
9393
};
9494

95+
enum {
96+
APERSISTABLEBUNDLE_KEY_NOT_FOUND = APERSISTABLEBUNDLE_KEY_NOT_FOUND,
97+
APERSISTABLEBUNDLE_ALLOCATOR_FAILED = APERSISTABLEBUNDLE_ALLOCATOR_FAILED,
98+
};
99+
95100
} // namespace consts
96101

97102
} // namespace c_interface

0 commit comments

Comments
 (0)