@@ -22,11 +22,17 @@ use crate::{
2222} ;
2323use binder_ndk_sys:: {
2424 APersistableBundle , APersistableBundle_delete , APersistableBundle_dup ,
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_getString ,
29- APersistableBundle_getStringVector , APersistableBundle_isEqual , APersistableBundle_new ,
25+ APersistableBundle_erase , APersistableBundle_getBoolean , APersistableBundle_getBooleanKeys ,
26+ APersistableBundle_getBooleanVector , APersistableBundle_getBooleanVectorKeys ,
27+ APersistableBundle_getDouble , APersistableBundle_getDoubleKeys ,
28+ APersistableBundle_getDoubleVector , APersistableBundle_getDoubleVectorKeys ,
29+ APersistableBundle_getInt , APersistableBundle_getIntKeys , APersistableBundle_getIntVector ,
30+ APersistableBundle_getIntVectorKeys , APersistableBundle_getLong ,
31+ APersistableBundle_getLongKeys , APersistableBundle_getLongVector ,
32+ APersistableBundle_getLongVectorKeys , APersistableBundle_getPersistableBundle ,
33+ APersistableBundle_getPersistableBundleKeys , APersistableBundle_getString ,
34+ APersistableBundle_getStringKeys , APersistableBundle_getStringVector ,
35+ APersistableBundle_getStringVectorKeys , APersistableBundle_isEqual , APersistableBundle_new ,
3036 APersistableBundle_putBoolean , APersistableBundle_putBooleanVector ,
3137 APersistableBundle_putDouble , APersistableBundle_putDoubleVector , APersistableBundle_putInt ,
3238 APersistableBundle_putIntVector , APersistableBundle_putLong , APersistableBundle_putLongVector ,
@@ -588,6 +594,171 @@ impl PersistableBundle {
588594 Ok ( None )
589595 }
590596 }
597+
598+ /// Calls the appropriate `APersistableBundle_get*Keys` function for the given `value_type`,
599+ /// with our `string_allocator` and a null context pointer.
600+ ///
601+ /// # Safety
602+ ///
603+ /// `out_keys` must either be null or point to a buffer of at least `buffer_size_bytes` bytes,
604+ /// properly aligned for `T`, and not otherwise accessed for the duration of the call.
605+ unsafe fn get_keys_raw (
606+ & self ,
607+ value_type : ValueType ,
608+ out_keys : * mut * mut c_char ,
609+ buffer_size_bytes : i32 ,
610+ ) -> i32 {
611+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
612+ // lifetime of the `PersistableBundle`. Our caller guarantees an appropriate value for
613+ // `out_keys` and `buffer_size_bytes`.
614+ unsafe {
615+ match value_type {
616+ ValueType :: Boolean => APersistableBundle_getBooleanKeys (
617+ self . 0 . as_ptr ( ) ,
618+ out_keys,
619+ buffer_size_bytes,
620+ Some ( string_allocator) ,
621+ null_mut ( ) ,
622+ ) ,
623+ ValueType :: Integer => APersistableBundle_getIntKeys (
624+ self . 0 . as_ptr ( ) ,
625+ out_keys,
626+ buffer_size_bytes,
627+ Some ( string_allocator) ,
628+ null_mut ( ) ,
629+ ) ,
630+ ValueType :: Long => APersistableBundle_getLongKeys (
631+ self . 0 . as_ptr ( ) ,
632+ out_keys,
633+ buffer_size_bytes,
634+ Some ( string_allocator) ,
635+ null_mut ( ) ,
636+ ) ,
637+ ValueType :: Double => APersistableBundle_getDoubleKeys (
638+ self . 0 . as_ptr ( ) ,
639+ out_keys,
640+ buffer_size_bytes,
641+ Some ( string_allocator) ,
642+ null_mut ( ) ,
643+ ) ,
644+ ValueType :: String => APersistableBundle_getStringKeys (
645+ self . 0 . as_ptr ( ) ,
646+ out_keys,
647+ buffer_size_bytes,
648+ Some ( string_allocator) ,
649+ null_mut ( ) ,
650+ ) ,
651+ ValueType :: BooleanVector => APersistableBundle_getBooleanVectorKeys (
652+ self . 0 . as_ptr ( ) ,
653+ out_keys,
654+ buffer_size_bytes,
655+ Some ( string_allocator) ,
656+ null_mut ( ) ,
657+ ) ,
658+ ValueType :: IntegerVector => APersistableBundle_getIntVectorKeys (
659+ self . 0 . as_ptr ( ) ,
660+ out_keys,
661+ buffer_size_bytes,
662+ Some ( string_allocator) ,
663+ null_mut ( ) ,
664+ ) ,
665+ ValueType :: LongVector => APersistableBundle_getLongVectorKeys (
666+ self . 0 . as_ptr ( ) ,
667+ out_keys,
668+ buffer_size_bytes,
669+ Some ( string_allocator) ,
670+ null_mut ( ) ,
671+ ) ,
672+ ValueType :: DoubleVector => APersistableBundle_getDoubleVectorKeys (
673+ self . 0 . as_ptr ( ) ,
674+ out_keys,
675+ buffer_size_bytes,
676+ Some ( string_allocator) ,
677+ null_mut ( ) ,
678+ ) ,
679+ ValueType :: StringVector => APersistableBundle_getStringVectorKeys (
680+ self . 0 . as_ptr ( ) ,
681+ out_keys,
682+ buffer_size_bytes,
683+ Some ( string_allocator) ,
684+ null_mut ( ) ,
685+ ) ,
686+ ValueType :: PersistableBundle => APersistableBundle_getPersistableBundleKeys (
687+ self . 0 . as_ptr ( ) ,
688+ out_keys,
689+ buffer_size_bytes,
690+ Some ( string_allocator) ,
691+ null_mut ( ) ,
692+ ) ,
693+ }
694+ }
695+ }
696+
697+ /// Gets all the keys associated with values of the given type.
698+ pub fn keys_for_type ( & self , value_type : ValueType ) -> Vec < String > {
699+ // SAFETY: A null pointer is allowed for the buffer.
700+ match unsafe { self . get_keys_raw ( value_type, null_mut ( ) , 0 ) } {
701+ APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
702+ panic ! ( "APersistableBundle_get*Keys failed to allocate string" ) ;
703+ }
704+ required_buffer_size => {
705+ let required_buffer_size_usize = usize:: try_from ( required_buffer_size)
706+ . expect ( "APersistableBundle_get*Keys returned invalid size" ) ;
707+ assert_eq ! ( required_buffer_size_usize % size_of:: <* mut c_char>( ) , 0 ) ;
708+ let mut keys =
709+ vec ! [ null_mut( ) ; required_buffer_size_usize / size_of:: <* mut c_char>( ) ] ;
710+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
711+ // the lifetime of the `PersistableBundle`. The keys buffer pointer is valid as it
712+ // comes from the Vec we just allocated.
713+ if unsafe { self . get_keys_raw ( value_type, keys. as_mut_ptr ( ) , required_buffer_size) }
714+ == APERSISTABLEBUNDLE_ALLOCATOR_FAILED
715+ {
716+ panic ! ( "APersistableBundle_get*Keys failed to allocate string" ) ;
717+ }
718+ keys. into_iter ( )
719+ . map ( |key| {
720+ // SAFETY: The pointer was returned from `string_allocator`, which used
721+ // `Box::into_raw`, and `APersistableBundle_getStringVector` should have
722+ // written valid bytes to it including a NUL terminator in the last
723+ // position.
724+ let string_length = unsafe { CStr :: from_ptr ( key) } . count_bytes ( ) ;
725+ let raw_slice = slice_from_raw_parts_mut ( key. cast ( ) , string_length + 1 ) ;
726+ // SAFETY: The pointer was returned from `string_allocator`, which used
727+ // `Box::into_raw`, and we've got the appropriate size back by checking the
728+ // length of the string.
729+ let boxed_slice: Box < [ u8 ] > = unsafe { Box :: from_raw ( raw_slice) } ;
730+ let c_string = CString :: from_vec_with_nul ( boxed_slice. into ( ) )
731+ . expect ( "APersistableBundle_get*Keys returned string missing NUL byte" ) ;
732+ c_string
733+ . into_string ( )
734+ . expect ( "APersistableBundle_get*Keys returned invalid UTF-8" )
735+ } )
736+ . collect ( )
737+ }
738+ }
739+ }
740+
741+ /// Returns an iterator over all keys in the bundle, along with the type of their associated
742+ /// value.
743+ pub fn keys ( & self ) -> impl Iterator < Item = ( String , ValueType ) > + use < ' _ > {
744+ [
745+ ValueType :: Boolean ,
746+ ValueType :: Integer ,
747+ ValueType :: Long ,
748+ ValueType :: Double ,
749+ ValueType :: String ,
750+ ValueType :: BooleanVector ,
751+ ValueType :: IntegerVector ,
752+ ValueType :: LongVector ,
753+ ValueType :: DoubleVector ,
754+ ValueType :: StringVector ,
755+ ValueType :: PersistableBundle ,
756+ ]
757+ . iter ( )
758+ . flat_map ( |value_type| {
759+ self . keys_for_type ( * value_type) . into_iter ( ) . map ( |key| ( key, * value_type) )
760+ } )
761+ }
591762}
592763
593764/// Wrapper around `APersistableBundle_getStringVector` to pass `string_allocator` and a null
@@ -709,6 +880,33 @@ unsafe extern "C" fn string_allocator(size: i32, context: *mut c_void) -> *mut c
709880impl_deserialize_for_unstructured_parcelable ! ( PersistableBundle ) ;
710881impl_serialize_for_unstructured_parcelable ! ( PersistableBundle ) ;
711882
883+ /// The types which may be stored as values in a [`PersistableBundle`].
884+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
885+ pub enum ValueType {
886+ /// A `bool`.
887+ Boolean ,
888+ /// An `i32`.
889+ Integer ,
890+ /// An `i64`.
891+ Long ,
892+ /// An `f64`.
893+ Double ,
894+ /// A string.
895+ String ,
896+ /// A vector of `bool`s.
897+ BooleanVector ,
898+ /// A vector of `i32`s.
899+ IntegerVector ,
900+ /// A vector of `i64`s.
901+ LongVector ,
902+ /// A vector of `f64`s.
903+ DoubleVector ,
904+ /// A vector of strings.
905+ StringVector ,
906+ /// A nested `PersistableBundle`.
907+ PersistableBundle ,
908+ }
909+
712910#[ cfg( test) ]
713911mod test {
714912 use super :: * ;
@@ -846,4 +1044,33 @@ mod test {
8461044
8471045 assert_eq ! ( bundle. get_persistable_bundle( "bundle" ) , Ok ( Some ( sub_bundle) ) ) ;
8481046 }
1047+
1048+ #[ test]
1049+ fn get_keys ( ) {
1050+ let mut bundle = PersistableBundle :: new ( ) ;
1051+
1052+ assert_eq ! ( bundle. keys_for_type( ValueType :: Boolean ) , Vec :: <String >:: new( ) ) ;
1053+ assert_eq ! ( bundle. keys_for_type( ValueType :: Integer ) , Vec :: <String >:: new( ) ) ;
1054+ assert_eq ! ( bundle. keys_for_type( ValueType :: StringVector ) , Vec :: <String >:: new( ) ) ;
1055+
1056+ assert_eq ! ( bundle. insert_bool( "bool1" , false ) , Ok ( ( ) ) ) ;
1057+ assert_eq ! ( bundle. insert_bool( "bool2" , true ) , Ok ( ( ) ) ) ;
1058+ assert_eq ! ( bundle. insert_int( "int" , 42 ) , Ok ( ( ) ) ) ;
1059+
1060+ assert_eq ! (
1061+ bundle. keys_for_type( ValueType :: Boolean ) ,
1062+ vec![ "bool1" . to_string( ) , "bool2" . to_string( ) ]
1063+ ) ;
1064+ assert_eq ! ( bundle. keys_for_type( ValueType :: Integer ) , vec![ "int" . to_string( ) ] ) ;
1065+ assert_eq ! ( bundle. keys_for_type( ValueType :: StringVector ) , Vec :: <String >:: new( ) ) ;
1066+
1067+ assert_eq ! (
1068+ bundle. keys( ) . collect:: <Vec <_>>( ) ,
1069+ vec![
1070+ ( "bool1" . to_string( ) , ValueType :: Boolean ) ,
1071+ ( "bool2" . to_string( ) , ValueType :: Boolean ) ,
1072+ ( "int" . to_string( ) , ValueType :: Integer ) ,
1073+ ]
1074+ ) ;
1075+ }
8491076}
0 commit comments