@@ -22,17 +22,18 @@ use crate::{
2222} ;
2323use 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 } ;
3637use 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]
0 commit comments