@@ -22,9 +22,13 @@ use crate::{
2222} ;
2323use binder_ndk_sys:: {
2424 APersistableBundle , APersistableBundle_delete , APersistableBundle_dup ,
25- APersistableBundle_isEqual , APersistableBundle_new , APersistableBundle_readFromParcel ,
25+ APersistableBundle_erase , APersistableBundle_getBoolean , APersistableBundle_getDouble ,
26+ APersistableBundle_getInt , APersistableBundle_getLong , APersistableBundle_isEqual ,
27+ APersistableBundle_new , APersistableBundle_putBoolean , APersistableBundle_putDouble ,
28+ APersistableBundle_putInt , APersistableBundle_putLong , APersistableBundle_readFromParcel ,
2629 APersistableBundle_size , APersistableBundle_writeToParcel ,
2730} ;
31+ use std:: ffi:: { CString , NulError } ;
2832use std:: ptr:: { null_mut, NonNull } ;
2933
3034/// A mapping from string keys to values of various types.
@@ -47,6 +51,154 @@ impl PersistableBundle {
4751 . try_into ( )
4852 . expect ( "APersistableBundle_size returned a negative size" )
4953 }
54+
55+ /// Removes any entry with the given key.
56+ ///
57+ /// Returns an error if the given key contains a NUL character, otherwise returns whether there
58+ /// was any entry to remove.
59+ pub fn remove ( & mut self , key : & str ) -> Result < bool , NulError > {
60+ let key = CString :: new ( key) ?;
61+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
62+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
63+ // to be valid for the lifetime of `key`.
64+ Ok ( unsafe { APersistableBundle_erase ( self . 0 . as_ptr ( ) , key. as_ptr ( ) ) != 0 } )
65+ }
66+
67+ /// Inserts a key-value pair into the bundle.
68+ ///
69+ /// If the key is already present then its value will be overwritten by the given value.
70+ ///
71+ /// Returns an error if the key contains a NUL character.
72+ pub fn insert_bool ( & mut self , key : & str , value : bool ) -> Result < ( ) , NulError > {
73+ let key = CString :: new ( key) ?;
74+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
75+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
76+ // to be valid for the lifetime of `key`.
77+ unsafe {
78+ APersistableBundle_putBoolean ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , value) ;
79+ }
80+ Ok ( ( ) )
81+ }
82+
83+ /// Inserts a key-value pair into the bundle.
84+ ///
85+ /// If the key is already present then its value will be overwritten by the given value.
86+ ///
87+ /// Returns an error if the key contains a NUL character.
88+ pub fn insert_int ( & mut self , key : & str , value : i32 ) -> Result < ( ) , NulError > {
89+ let key = CString :: new ( key) ?;
90+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
91+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
92+ // to be valid for the lifetime of `key`.
93+ unsafe {
94+ APersistableBundle_putInt ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , value) ;
95+ }
96+ Ok ( ( ) )
97+ }
98+
99+ /// Inserts a key-value pair into the bundle.
100+ ///
101+ /// If the key is already present then its value will be overwritten by the given value.
102+ ///
103+ /// Returns an error if the key contains a NUL character.
104+ pub fn insert_long ( & mut self , key : & str , value : i64 ) -> Result < ( ) , NulError > {
105+ let key = CString :: new ( key) ?;
106+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
107+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
108+ // to be valid for the lifetime of `key`.
109+ unsafe {
110+ APersistableBundle_putLong ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , value) ;
111+ }
112+ Ok ( ( ) )
113+ }
114+
115+ /// Inserts a key-value pair into the bundle.
116+ ///
117+ /// If the key is already present then its value will be overwritten by the given value.
118+ ///
119+ /// Returns an error if the key contains a NUL character.
120+ pub fn insert_double ( & mut self , key : & str , value : f64 ) -> Result < ( ) , NulError > {
121+ let key = CString :: new ( key) ?;
122+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
123+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
124+ // to be valid for the lifetime of `key`.
125+ unsafe {
126+ APersistableBundle_putDouble ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , value) ;
127+ }
128+ Ok ( ( ) )
129+ }
130+
131+ /// Gets the boolean value associated with the given key.
132+ ///
133+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
134+ /// in the bundle.
135+ pub fn get_bool ( & self , key : & str ) -> Result < Option < bool > , NulError > {
136+ let key = CString :: new ( key) ?;
137+ let mut value = false ;
138+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
139+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
140+ // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
141+ // from a reference.
142+ if unsafe { APersistableBundle_getBoolean ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , & mut value) } {
143+ Ok ( Some ( value) )
144+ } else {
145+ Ok ( None )
146+ }
147+ }
148+
149+ /// Gets the i32 value associated with the given key.
150+ ///
151+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
152+ /// in the bundle.
153+ pub fn get_int ( & self , key : & str ) -> Result < Option < i32 > , NulError > {
154+ let key = CString :: new ( key) ?;
155+ let mut value = 0 ;
156+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
157+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
158+ // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
159+ // from a reference.
160+ if unsafe { APersistableBundle_getInt ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , & mut value) } {
161+ Ok ( Some ( value) )
162+ } else {
163+ Ok ( None )
164+ }
165+ }
166+
167+ /// Gets the i64 value associated with the given key.
168+ ///
169+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
170+ /// in the bundle.
171+ pub fn get_long ( & self , key : & str ) -> Result < Option < i64 > , NulError > {
172+ let key = CString :: new ( key) ?;
173+ let mut value = 0 ;
174+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
175+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
176+ // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
177+ // from a reference.
178+ if unsafe { APersistableBundle_getLong ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , & mut value) } {
179+ Ok ( Some ( value) )
180+ } else {
181+ Ok ( None )
182+ }
183+ }
184+
185+ /// Gets the f64 value associated with the given key.
186+ ///
187+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
188+ /// in the bundle.
189+ pub fn get_double ( & self , key : & str ) -> Result < Option < f64 > , NulError > {
190+ let key = CString :: new ( key) ?;
191+ let mut value = 0.0 ;
192+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
193+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
194+ // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
195+ // from a reference.
196+ if unsafe { APersistableBundle_getDouble ( self . 0 . as_ptr ( ) , key. as_ptr ( ) , & mut value) } {
197+ Ok ( Some ( value) )
198+ } else {
199+ Ok ( None )
200+ }
201+ }
50202}
51203
52204// SAFETY: The underlying *APersistableBundle can be moved between threads.
@@ -131,4 +283,60 @@ mod test {
131283 let duplicate = bundle. clone ( ) ;
132284 assert_eq ! ( bundle, duplicate) ;
133285 }
286+
287+ #[ test]
288+ fn get_empty ( ) {
289+ let bundle = PersistableBundle :: new ( ) ;
290+ assert_eq ! ( bundle. get_bool( "foo" ) , Ok ( None ) ) ;
291+ assert_eq ! ( bundle. get_int( "foo" ) , Ok ( None ) ) ;
292+ assert_eq ! ( bundle. get_long( "foo" ) , Ok ( None ) ) ;
293+ assert_eq ! ( bundle. get_double( "foo" ) , Ok ( None ) ) ;
294+ }
295+
296+ #[ test]
297+ fn remove_empty ( ) {
298+ let mut bundle = PersistableBundle :: new ( ) ;
299+ assert_eq ! ( bundle. remove( "foo" ) , Ok ( false ) ) ;
300+ }
301+
302+ #[ test]
303+ fn insert_get_primitives ( ) {
304+ let mut bundle = PersistableBundle :: new ( ) ;
305+
306+ assert_eq ! ( bundle. insert_bool( "bool" , true ) , Ok ( ( ) ) ) ;
307+ assert_eq ! ( bundle. insert_int( "int" , 42 ) , Ok ( ( ) ) ) ;
308+ assert_eq ! ( bundle. insert_long( "long" , 66 ) , Ok ( ( ) ) ) ;
309+ assert_eq ! ( bundle. insert_double( "double" , 123.4 ) , Ok ( ( ) ) ) ;
310+
311+ assert_eq ! ( bundle. get_bool( "bool" ) , Ok ( Some ( true ) ) ) ;
312+ assert_eq ! ( bundle. get_int( "int" ) , Ok ( Some ( 42 ) ) ) ;
313+ assert_eq ! ( bundle. get_long( "long" ) , Ok ( Some ( 66 ) ) ) ;
314+ assert_eq ! ( bundle. get_double( "double" ) , Ok ( Some ( 123.4 ) ) ) ;
315+ assert_eq ! ( bundle. size( ) , 4 ) ;
316+
317+ // Getting the wrong type should return nothing.
318+ assert_eq ! ( bundle. get_int( "bool" ) , Ok ( None ) ) ;
319+ assert_eq ! ( bundle. get_long( "bool" ) , Ok ( None ) ) ;
320+ assert_eq ! ( bundle. get_double( "bool" ) , Ok ( None ) ) ;
321+ assert_eq ! ( bundle. get_bool( "int" ) , Ok ( None ) ) ;
322+ assert_eq ! ( bundle. get_long( "int" ) , Ok ( None ) ) ;
323+ assert_eq ! ( bundle. get_double( "int" ) , Ok ( None ) ) ;
324+ assert_eq ! ( bundle. get_bool( "long" ) , Ok ( None ) ) ;
325+ assert_eq ! ( bundle. get_int( "long" ) , Ok ( None ) ) ;
326+ assert_eq ! ( bundle. get_double( "long" ) , Ok ( None ) ) ;
327+ assert_eq ! ( bundle. get_bool( "double" ) , Ok ( None ) ) ;
328+ assert_eq ! ( bundle. get_int( "double" ) , Ok ( None ) ) ;
329+ assert_eq ! ( bundle. get_long( "double" ) , Ok ( None ) ) ;
330+
331+ // If they are removed they should no longer be present.
332+ assert_eq ! ( bundle. remove( "bool" ) , Ok ( true ) ) ;
333+ assert_eq ! ( bundle. remove( "int" ) , Ok ( true ) ) ;
334+ assert_eq ! ( bundle. remove( "long" ) , Ok ( true ) ) ;
335+ assert_eq ! ( bundle. remove( "double" ) , Ok ( true ) ) ;
336+ assert_eq ! ( bundle. get_bool( "bool" ) , Ok ( None ) ) ;
337+ assert_eq ! ( bundle. get_int( "int" ) , Ok ( None ) ) ;
338+ assert_eq ! ( bundle. get_long( "long" ) , Ok ( None ) ) ;
339+ assert_eq ! ( bundle. get_double( "double" ) , Ok ( None ) ) ;
340+ assert_eq ! ( bundle. size( ) , 0 ) ;
341+ }
134342}
0 commit comments