binder/persistable_bundle.rs
1/*
2 * Copyright (C) 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::{
18 binder::AsNative,
19 error::{status_result, StatusCode},
20 impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
21 parcel::{BorrowedParcel, UnstructuredParcelable},
22};
23use binder_ndk_sys::{
24 APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
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,
36 APersistableBundle_putBoolean, APersistableBundle_putBooleanVector,
37 APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt,
38 APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector,
39 APersistableBundle_putPersistableBundle, APersistableBundle_putString,
40 APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size,
41 APersistableBundle_writeToParcel, APERSISTABLEBUNDLE_ALLOCATOR_FAILED,
42 APERSISTABLEBUNDLE_KEY_NOT_FOUND,
43};
44use std::ffi::{c_char, c_void, CStr, CString, NulError};
45use std::ptr::{null_mut, slice_from_raw_parts_mut, NonNull};
46use zerocopy::FromZeros;
47
48/// A mapping from string keys to values of various types.
49#[derive(Debug)]
50pub struct PersistableBundle(NonNull<APersistableBundle>);
51
52impl PersistableBundle {
53 /// Creates a new `PersistableBundle`.
54 pub fn new() -> Self {
55 // SAFETY: APersistableBundle_new doesn't actually have any safety requirements.
56 let bundle = unsafe { APersistableBundle_new() };
57 Self(NonNull::new(bundle).expect("Allocated APersistableBundle was null"))
58 }
59
60 /// Returns the number of mappings in the bundle.
61 pub fn size(&self) -> usize {
62 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
63 // lifetime of the `PersistableBundle`.
64 unsafe { APersistableBundle_size(self.0.as_ptr()) }
65 .try_into()
66 .expect("APersistableBundle_size returned a negative size")
67 }
68
69 /// Removes any entry with the given key.
70 ///
71 /// Returns an error if the given key contains a NUL character, otherwise returns whether there
72 /// was any entry to remove.
73 pub fn remove(&mut self, key: &str) -> Result<bool, NulError> {
74 let key = CString::new(key)?;
75 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
76 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
77 // to be valid for the duration of this call.
78 Ok(unsafe { APersistableBundle_erase(self.0.as_ptr(), key.as_ptr()) != 0 })
79 }
80
81 /// Inserts a key-value pair into the bundle.
82 ///
83 /// If the key is already present then its value will be overwritten by the given value.
84 ///
85 /// Returns an error if the key contains a NUL character.
86 pub fn insert_bool(&mut self, key: &str, value: bool) -> Result<(), NulError> {
87 let key = CString::new(key)?;
88 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
89 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
90 // to be valid for the duration of this call.
91 unsafe {
92 APersistableBundle_putBoolean(self.0.as_ptr(), key.as_ptr(), value);
93 }
94 Ok(())
95 }
96
97 /// Inserts a key-value pair into the bundle.
98 ///
99 /// If the key is already present then its value will be overwritten by the given value.
100 ///
101 /// Returns an error if the key contains a NUL character.
102 pub fn insert_int(&mut self, key: &str, value: i32) -> Result<(), NulError> {
103 let key = CString::new(key)?;
104 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
105 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
106 // to be valid for the duration of this call.
107 unsafe {
108 APersistableBundle_putInt(self.0.as_ptr(), key.as_ptr(), value);
109 }
110 Ok(())
111 }
112
113 /// Inserts a key-value pair into the bundle.
114 ///
115 /// If the key is already present then its value will be overwritten by the given value.
116 ///
117 /// Returns an error if the key contains a NUL character.
118 pub fn insert_long(&mut self, key: &str, value: i64) -> Result<(), NulError> {
119 let key = CString::new(key)?;
120 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
121 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
122 // to be valid for the duration of this call.
123 unsafe {
124 APersistableBundle_putLong(self.0.as_ptr(), key.as_ptr(), value);
125 }
126 Ok(())
127 }
128
129 /// Inserts a key-value pair into the bundle.
130 ///
131 /// If the key is already present then its value will be overwritten by the given value.
132 ///
133 /// Returns an error if the key contains a NUL character.
134 pub fn insert_double(&mut self, key: &str, value: f64) -> Result<(), NulError> {
135 let key = CString::new(key)?;
136 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
137 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
138 // to be valid for the duration of this call.
139 unsafe {
140 APersistableBundle_putDouble(self.0.as_ptr(), key.as_ptr(), value);
141 }
142 Ok(())
143 }
144
145 /// Inserts a key-value pair into the bundle.
146 ///
147 /// If the key is already present then its value will be overwritten by the given value.
148 ///
149 /// Returns an error if the key or value contains a NUL character.
150 pub fn insert_string(&mut self, key: &str, value: &str) -> Result<(), NulError> {
151 let key = CString::new(key)?;
152 let value = CString::new(value)?;
153 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
154 // lifetime of the `PersistableBundle`. The pointer returned by `CStr::as_ptr` is guaranteed
155 // to be valid for the duration of this call.
156 unsafe {
157 APersistableBundle_putString(self.0.as_ptr(), key.as_ptr(), value.as_ptr());
158 }
159 Ok(())
160 }
161
162 /// Inserts a key-value pair into the bundle.
163 ///
164 /// If the key is already present then its value will be overwritten by the given value.
165 ///
166 /// Returns an error if the key contains a NUL character.
167 pub fn insert_bool_vec(&mut self, key: &str, value: &[bool]) -> Result<(), NulError> {
168 let key = CString::new(key)?;
169 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
170 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
171 // to be valid for the duration of this call, and likewise the pointer returned by
172 // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
173 // duration of the call.
174 unsafe {
175 APersistableBundle_putBooleanVector(
176 self.0.as_ptr(),
177 key.as_ptr(),
178 value.as_ptr(),
179 value.len().try_into().unwrap(),
180 );
181 }
182 Ok(())
183 }
184
185 /// Inserts a key-value pair into the bundle.
186 ///
187 /// If the key is already present then its value will be overwritten by the given value.
188 ///
189 /// Returns an error if the key contains a NUL character.
190 pub fn insert_int_vec(&mut self, key: &str, value: &[i32]) -> Result<(), NulError> {
191 let key = CString::new(key)?;
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 duration of this call, and likewise the pointer returned by
195 // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
196 // duration of the call.
197 unsafe {
198 APersistableBundle_putIntVector(
199 self.0.as_ptr(),
200 key.as_ptr(),
201 value.as_ptr(),
202 value.len().try_into().unwrap(),
203 );
204 }
205 Ok(())
206 }
207
208 /// Inserts a key-value pair into the bundle.
209 ///
210 /// If the key is already present then its value will be overwritten by the given value.
211 ///
212 /// Returns an error if the key contains a NUL character.
213 pub fn insert_long_vec(&mut self, key: &str, value: &[i64]) -> Result<(), NulError> {
214 let key = CString::new(key)?;
215 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
216 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
217 // to be valid for the duration of this call, and likewise the pointer returned by
218 // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
219 // duration of the call.
220 unsafe {
221 APersistableBundle_putLongVector(
222 self.0.as_ptr(),
223 key.as_ptr(),
224 value.as_ptr(),
225 value.len().try_into().unwrap(),
226 );
227 }
228 Ok(())
229 }
230
231 /// Inserts a key-value pair into the bundle.
232 ///
233 /// If the key is already present then its value will be overwritten by the given value.
234 ///
235 /// Returns an error if the key contains a NUL character.
236 pub fn insert_double_vec(&mut self, key: &str, value: &[f64]) -> Result<(), NulError> {
237 let key = CString::new(key)?;
238 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
239 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
240 // to be valid for the duration of this call, and likewise the pointer returned by
241 // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
242 // duration of the call.
243 unsafe {
244 APersistableBundle_putDoubleVector(
245 self.0.as_ptr(),
246 key.as_ptr(),
247 value.as_ptr(),
248 value.len().try_into().unwrap(),
249 );
250 }
251 Ok(())
252 }
253
254 /// Inserts a key-value pair into the bundle.
255 ///
256 /// If the key is already present then its value will be overwritten by the given value.
257 ///
258 /// Returns an error if the key contains a NUL character.
259 pub fn insert_string_vec<'a, T: ToString + 'a>(
260 &mut self,
261 key: &str,
262 value: impl IntoIterator<Item = &'a T>,
263 ) -> Result<(), NulError> {
264 let key = CString::new(key)?;
265 // We need to collect the new `CString`s into something first so that they live long enough
266 // for their pointers to be valid for the `APersistableBundle_putStringVector` call below.
267 let c_strings = value
268 .into_iter()
269 .map(|s| CString::new(s.to_string()))
270 .collect::<Result<Vec<_>, NulError>>()?;
271 let char_pointers = c_strings.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
272 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
273 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
274 // to be valid for the duration of this call, and likewise the pointer returned by
275 // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
276 // duration of the call.
277 unsafe {
278 APersistableBundle_putStringVector(
279 self.0.as_ptr(),
280 key.as_ptr(),
281 char_pointers.as_ptr(),
282 char_pointers.len().try_into().unwrap(),
283 );
284 }
285 Ok(())
286 }
287
288 /// Inserts a key-value pair into the bundle.
289 ///
290 /// If the key is already present then its value will be overwritten by the given value.
291 ///
292 /// Returns an error if the key contains a NUL character.
293 pub fn insert_persistable_bundle(
294 &mut self,
295 key: &str,
296 value: &PersistableBundle,
297 ) -> Result<(), NulError> {
298 let key = CString::new(key)?;
299 // SAFETY: The wrapped `APersistableBundle` pointers are guaranteed to be valid for the
300 // lifetime of the `PersistableBundle`s. The pointer returned by `CStr::as_ptr` is
301 // guaranteed to be valid for the duration of this call, and
302 // `APersistableBundle_putPersistableBundle` does a deep copy so that is all that is
303 // required.
304 unsafe {
305 APersistableBundle_putPersistableBundle(
306 self.0.as_ptr(),
307 key.as_ptr(),
308 value.0.as_ptr(),
309 );
310 }
311 Ok(())
312 }
313
314 /// Gets the boolean value associated with the given key.
315 ///
316 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
317 /// in the bundle.
318 pub fn get_bool(&self, key: &str) -> Result<Option<bool>, NulError> {
319 let key = CString::new(key)?;
320 let mut value = false;
321 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
322 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
323 // to be valid for the duration of this call. The value pointer must be valid because it
324 // comes from a reference.
325 if unsafe { APersistableBundle_getBoolean(self.0.as_ptr(), key.as_ptr(), &mut value) } {
326 Ok(Some(value))
327 } else {
328 Ok(None)
329 }
330 }
331
332 /// Gets the i32 value associated with the given key.
333 ///
334 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
335 /// in the bundle.
336 pub fn get_int(&self, key: &str) -> Result<Option<i32>, NulError> {
337 let key = CString::new(key)?;
338 let mut value = 0;
339 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
340 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
341 // to be valid for the duration of this call. The value pointer must be valid because it
342 // comes from a reference.
343 if unsafe { APersistableBundle_getInt(self.0.as_ptr(), key.as_ptr(), &mut value) } {
344 Ok(Some(value))
345 } else {
346 Ok(None)
347 }
348 }
349
350 /// Gets the i64 value associated with the given key.
351 ///
352 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
353 /// in the bundle.
354 pub fn get_long(&self, key: &str) -> Result<Option<i64>, NulError> {
355 let key = CString::new(key)?;
356 let mut value = 0;
357 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
358 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
359 // to be valid for the duration of this call. The value pointer must be valid because it
360 // comes from a reference.
361 if unsafe { APersistableBundle_getLong(self.0.as_ptr(), key.as_ptr(), &mut value) } {
362 Ok(Some(value))
363 } else {
364 Ok(None)
365 }
366 }
367
368 /// Gets the f64 value associated with the given key.
369 ///
370 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
371 /// in the bundle.
372 pub fn get_double(&self, key: &str) -> Result<Option<f64>, NulError> {
373 let key = CString::new(key)?;
374 let mut value = 0.0;
375 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
376 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
377 // to be valid for the duration of this call. The value pointer must be valid because it
378 // comes from a reference.
379 if unsafe { APersistableBundle_getDouble(self.0.as_ptr(), key.as_ptr(), &mut value) } {
380 Ok(Some(value))
381 } else {
382 Ok(None)
383 }
384 }
385
386 /// Gets the string value associated with the given key.
387 ///
388 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
389 /// in the bundle.
390 pub fn get_string(&self, key: &str) -> Result<Option<String>, NulError> {
391 let key = CString::new(key)?;
392 let mut value = null_mut();
393 let mut allocated_size: usize = 0;
394 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
395 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
396 // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
397 // from a reference.
398 let value_size_bytes = unsafe {
399 APersistableBundle_getString(
400 self.0.as_ptr(),
401 key.as_ptr(),
402 &mut value,
403 Some(string_allocator),
404 (&raw mut allocated_size).cast(),
405 )
406 };
407 match value_size_bytes {
408 APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None),
409 APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
410 panic!("APersistableBundle_getString failed to allocate string");
411 }
412 _ => {
413 let raw_slice = slice_from_raw_parts_mut(value.cast(), allocated_size);
414 // SAFETY: The pointer was returned from string_allocator, which used
415 // `Box::into_raw`, and we've got the appropriate size back from allocated_size.
416 let boxed_slice: Box<[u8]> = unsafe { Box::from_raw(raw_slice) };
417 assert_eq!(
418 allocated_size,
419 usize::try_from(value_size_bytes)
420 .expect("APersistableBundle_getString returned negative value size")
421 + 1
422 );
423 let c_string = CString::from_vec_with_nul(boxed_slice.into())
424 .expect("APersistableBundle_getString returned string missing NUL byte");
425 let string = c_string
426 .into_string()
427 .expect("APersistableBundle_getString returned invalid UTF-8");
428 Ok(Some(string))
429 }
430 }
431 }
432
433 /// Gets the vector of `T` associated with the given key.
434 ///
435 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
436 /// in the bundle.
437 ///
438 /// `get_func` should be one of the `APersistableBundle_get*Vector` functions from
439 /// `binder_ndk_sys`.
440 ///
441 /// # Safety
442 ///
443 /// `get_func` must only require that the pointers it takes are valid for the duration of the
444 /// call. It must allow a null pointer for the buffer, and must return the size in bytes of
445 /// buffer it requires. If it is given a non-null buffer pointer it must write that number of
446 /// bytes to the buffer, which must be a whole number of valid `T` values.
447 unsafe fn get_vec<T: Clone>(
448 &self,
449 key: &str,
450 default: T,
451 get_func: unsafe extern "C" fn(
452 *const APersistableBundle,
453 *const c_char,
454 *mut T,
455 i32,
456 ) -> i32,
457 ) -> Result<Option<Vec<T>>, NulError> {
458 let key = CString::new(key)?;
459 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
460 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
461 // to be valid for the lifetime of `key`. A null pointer is allowed for the buffer.
462 match unsafe { get_func(self.0.as_ptr(), key.as_ptr(), null_mut(), 0) } {
463 APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None),
464 APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
465 panic!("APersistableBundle_getStringVector failed to allocate string");
466 }
467 required_buffer_size => {
468 let mut value = vec![
469 default;
470 usize::try_from(required_buffer_size).expect(
471 "APersistableBundle_get*Vector returned invalid size"
472 ) / size_of::<T>()
473 ];
474 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
475 // the lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()`
476 // is guaranteed to be valid for the lifetime of `key`. The value buffer pointer is
477 // valid as it comes from the Vec we just allocated.
478 match unsafe {
479 get_func(
480 self.0.as_ptr(),
481 key.as_ptr(),
482 value.as_mut_ptr(),
483 (value.len() * size_of::<T>()).try_into().unwrap(),
484 )
485 } {
486 APERSISTABLEBUNDLE_KEY_NOT_FOUND => {
487 panic!("APersistableBundle_get*Vector failed to find key after first finding it");
488 }
489 APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
490 panic!("APersistableBundle_getStringVector failed to allocate string");
491 }
492 _ => Ok(Some(value)),
493 }
494 }
495 }
496 }
497
498 /// Gets the boolean vector value associated with the given key.
499 ///
500 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
501 /// in the bundle.
502 pub fn get_bool_vec(&self, key: &str) -> Result<Option<Vec<bool>>, NulError> {
503 // SAFETY: APersistableBundle_getBooleanVector fulfils all the safety requirements of
504 // `get_vec`.
505 unsafe { self.get_vec(key, Default::default(), APersistableBundle_getBooleanVector) }
506 }
507
508 /// Gets the i32 vector value associated with the given key.
509 ///
510 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
511 /// in the bundle.
512 pub fn get_int_vec(&self, key: &str) -> Result<Option<Vec<i32>>, NulError> {
513 // SAFETY: APersistableBundle_getIntVector fulfils all the safety requirements of
514 // `get_vec`.
515 unsafe { self.get_vec(key, Default::default(), APersistableBundle_getIntVector) }
516 }
517
518 /// Gets the i64 vector value associated with the given key.
519 ///
520 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
521 /// in the bundle.
522 pub fn get_long_vec(&self, key: &str) -> Result<Option<Vec<i64>>, NulError> {
523 // SAFETY: APersistableBundle_getLongVector fulfils all the safety requirements of
524 // `get_vec`.
525 unsafe { self.get_vec(key, Default::default(), APersistableBundle_getLongVector) }
526 }
527
528 /// Gets the f64 vector value associated with the given key.
529 ///
530 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
531 /// in the bundle.
532 pub fn get_double_vec(&self, key: &str) -> Result<Option<Vec<f64>>, NulError> {
533 // SAFETY: APersistableBundle_getDoubleVector fulfils all the safety requirements of
534 // `get_vec`.
535 unsafe { self.get_vec(key, Default::default(), APersistableBundle_getDoubleVector) }
536 }
537
538 /// Gets the string vector value associated with the given key.
539 ///
540 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
541 /// in the bundle.
542 pub fn get_string_vec(&self, key: &str) -> Result<Option<Vec<String>>, NulError> {
543 if let Some(value) =
544 // SAFETY: `get_string_vector_with_allocator` fulfils all the safety requirements of
545 // `get_vec`.
546 unsafe { self.get_vec(key, null_mut(), get_string_vector_with_allocator) }?
547 {
548 Ok(Some(
549 value
550 .into_iter()
551 .map(|s| {
552 // SAFETY: The pointer was returned from `string_allocator`, which used
553 // `Box::into_raw`, and `APersistableBundle_getStringVector` should have
554 // written valid bytes to it including a NUL terminator in the last
555 // position.
556 let string_length = unsafe { CStr::from_ptr(s) }.count_bytes();
557 let raw_slice = slice_from_raw_parts_mut(s.cast(), string_length + 1);
558 // SAFETY: The pointer was returned from `string_allocator`, which used
559 // `Box::into_raw`, and we've got the appropriate size back by checking the
560 // length of the string.
561 let boxed_slice: Box<[u8]> = unsafe { Box::from_raw(raw_slice) };
562 let c_string = CString::from_vec_with_nul(boxed_slice.into()).expect(
563 "APersistableBundle_getStringVector returned string missing NUL byte",
564 );
565 c_string
566 .into_string()
567 .expect("APersistableBundle_getStringVector returned invalid UTF-8")
568 })
569 .collect(),
570 ))
571 } else {
572 Ok(None)
573 }
574 }
575
576 /// Gets the `PersistableBundle` value associated with the given key.
577 ///
578 /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
579 /// in the bundle.
580 pub fn get_persistable_bundle(&self, key: &str) -> Result<Option<Self>, NulError> {
581 let key = CString::new(key)?;
582 let mut value = null_mut();
583 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
584 // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
585 // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
586 // from a reference.
587 if unsafe {
588 APersistableBundle_getPersistableBundle(self.0.as_ptr(), key.as_ptr(), &mut value)
589 } {
590 Ok(Some(Self(NonNull::new(value).expect(
591 "APersistableBundle_getPersistableBundle returned true but didn't set outBundle",
592 ))))
593 } else {
594 Ok(None)
595 }
596 }
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 }
762}
763
764/// Wrapper around `APersistableBundle_getStringVector` to pass `string_allocator` and a null
765/// context pointer.
766///
767/// # Safety
768///
769/// * `bundle` must point to a valid `APersistableBundle` which is not modified for the duration of
770/// the call.
771/// * `key` must point to a valid NUL-terminated C string.
772/// * `buffer` must either be null or point to a buffer of at least `buffer_size_bytes` bytes,
773/// properly aligned for `T`, and not otherwise accessed for the duration of the call.
774unsafe extern "C" fn get_string_vector_with_allocator(
775 bundle: *const APersistableBundle,
776 key: *const c_char,
777 buffer: *mut *mut c_char,
778 buffer_size_bytes: i32,
779) -> i32 {
780 // SAFETY: The safety requirements are all guaranteed by our caller according to the safety
781 // documentation above.
782 unsafe {
783 APersistableBundle_getStringVector(
784 bundle,
785 key,
786 buffer,
787 buffer_size_bytes,
788 Some(string_allocator),
789 null_mut(),
790 )
791 }
792}
793
794// SAFETY: The underlying *APersistableBundle can be moved between threads.
795unsafe impl Send for PersistableBundle {}
796
797// SAFETY: The underlying *APersistableBundle can be read from multiple threads, and we require
798// `&mut PersistableBundle` for any operations which mutate it.
799unsafe impl Sync for PersistableBundle {}
800
801impl Default for PersistableBundle {
802 fn default() -> Self {
803 Self::new()
804 }
805}
806
807impl Drop for PersistableBundle {
808 fn drop(&mut self) {
809 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
810 // lifetime of this `PersistableBundle`.
811 unsafe { APersistableBundle_delete(self.0.as_ptr()) };
812 }
813}
814
815impl Clone for PersistableBundle {
816 fn clone(&self) -> Self {
817 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
818 // lifetime of the `PersistableBundle`.
819 let duplicate = unsafe { APersistableBundle_dup(self.0.as_ptr()) };
820 Self(NonNull::new(duplicate).expect("Duplicated APersistableBundle was null"))
821 }
822}
823
824impl PartialEq for PersistableBundle {
825 fn eq(&self, other: &Self) -> bool {
826 // SAFETY: The wrapped `APersistableBundle` pointers are guaranteed to be valid for the
827 // lifetime of the `PersistableBundle`s.
828 unsafe { APersistableBundle_isEqual(self.0.as_ptr(), other.0.as_ptr()) }
829 }
830}
831
832impl UnstructuredParcelable for PersistableBundle {
833 fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
834 let status =
835 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
836 // lifetime of the `PersistableBundle`. `parcel.as_native_mut()` always returns a valid
837 // parcel pointer.
838 unsafe { APersistableBundle_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) };
839 status_result(status)
840 }
841
842 fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
843 let mut bundle = null_mut();
844
845 // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
846 // lifetime of the `PersistableBundle`. `parcel.as_native()` always returns a valid parcel
847 // pointer.
848 let status = unsafe { APersistableBundle_readFromParcel(parcel.as_native(), &mut bundle) };
849 status_result(status)?;
850
851 Ok(Self(NonNull::new(bundle).expect(
852 "APersistableBundle_readFromParcel returned success but didn't allocate bundle",
853 )))
854 }
855}
856
857/// Allocates a boxed slice of the given size in bytes, returns a pointer to it and writes its size
858/// to `*context`.
859///
860/// # Safety
861///
862/// `context` must either be null or point to a `usize` to which we can write.
863unsafe extern "C" fn string_allocator(size: i32, context: *mut c_void) -> *mut c_char {
864 let Ok(size) = size.try_into() else {
865 return null_mut();
866 };
867 let Ok(boxed_slice) = <[c_char]>::new_box_zeroed_with_elems(size) else {
868 return null_mut();
869 };
870 if !context.is_null() {
871 // SAFETY: The caller promised that `context` is either null or points to a `usize` to which
872 // we can write, and we just checked that it's not null.
873 unsafe {
874 *context.cast::<usize>() = size;
875 }
876 }
877 Box::into_raw(boxed_slice).cast()
878}
879
880impl_deserialize_for_unstructured_parcelable!(PersistableBundle);
881impl_serialize_for_unstructured_parcelable!(PersistableBundle);
882
883/// The types which may be stored as values in a [`PersistableBundle`].
884#[derive(Clone, Copy, Debug, Eq, PartialEq)]
885pub 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
910#[cfg(test)]
911mod test {
912 use super::*;
913
914 #[test]
915 fn create_delete() {
916 let bundle = PersistableBundle::new();
917 drop(bundle);
918 }
919
920 #[test]
921 fn duplicate_equal() {
922 let bundle = PersistableBundle::new();
923 let duplicate = bundle.clone();
924 assert_eq!(bundle, duplicate);
925 }
926
927 #[test]
928 fn get_empty() {
929 let bundle = PersistableBundle::new();
930 assert_eq!(bundle.get_bool("foo"), Ok(None));
931 assert_eq!(bundle.get_int("foo"), Ok(None));
932 assert_eq!(bundle.get_long("foo"), Ok(None));
933 assert_eq!(bundle.get_double("foo"), Ok(None));
934 assert_eq!(bundle.get_bool_vec("foo"), Ok(None));
935 assert_eq!(bundle.get_int_vec("foo"), Ok(None));
936 assert_eq!(bundle.get_long_vec("foo"), Ok(None));
937 assert_eq!(bundle.get_double_vec("foo"), Ok(None));
938 assert_eq!(bundle.get_string("foo"), Ok(None));
939 }
940
941 #[test]
942 fn remove_empty() {
943 let mut bundle = PersistableBundle::new();
944 assert_eq!(bundle.remove("foo"), Ok(false));
945 }
946
947 #[test]
948 fn insert_get_primitives() {
949 let mut bundle = PersistableBundle::new();
950
951 assert_eq!(bundle.insert_bool("bool", true), Ok(()));
952 assert_eq!(bundle.insert_int("int", 42), Ok(()));
953 assert_eq!(bundle.insert_long("long", 66), Ok(()));
954 assert_eq!(bundle.insert_double("double", 123.4), Ok(()));
955
956 assert_eq!(bundle.get_bool("bool"), Ok(Some(true)));
957 assert_eq!(bundle.get_int("int"), Ok(Some(42)));
958 assert_eq!(bundle.get_long("long"), Ok(Some(66)));
959 assert_eq!(bundle.get_double("double"), Ok(Some(123.4)));
960 assert_eq!(bundle.size(), 4);
961
962 // Getting the wrong type should return nothing.
963 assert_eq!(bundle.get_int("bool"), Ok(None));
964 assert_eq!(bundle.get_long("bool"), Ok(None));
965 assert_eq!(bundle.get_double("bool"), Ok(None));
966 assert_eq!(bundle.get_bool("int"), Ok(None));
967 assert_eq!(bundle.get_long("int"), Ok(None));
968 assert_eq!(bundle.get_double("int"), Ok(None));
969 assert_eq!(bundle.get_bool("long"), Ok(None));
970 assert_eq!(bundle.get_int("long"), Ok(None));
971 assert_eq!(bundle.get_double("long"), Ok(None));
972 assert_eq!(bundle.get_bool("double"), Ok(None));
973 assert_eq!(bundle.get_int("double"), Ok(None));
974 assert_eq!(bundle.get_long("double"), Ok(None));
975
976 // If they are removed they should no longer be present.
977 assert_eq!(bundle.remove("bool"), Ok(true));
978 assert_eq!(bundle.remove("int"), Ok(true));
979 assert_eq!(bundle.remove("long"), Ok(true));
980 assert_eq!(bundle.remove("double"), Ok(true));
981 assert_eq!(bundle.get_bool("bool"), Ok(None));
982 assert_eq!(bundle.get_int("int"), Ok(None));
983 assert_eq!(bundle.get_long("long"), Ok(None));
984 assert_eq!(bundle.get_double("double"), Ok(None));
985 assert_eq!(bundle.size(), 0);
986 }
987
988 #[test]
989 fn insert_get_string() {
990 let mut bundle = PersistableBundle::new();
991
992 assert_eq!(bundle.insert_string("string", "foo"), Ok(()));
993 assert_eq!(bundle.insert_string("empty", ""), Ok(()));
994 assert_eq!(bundle.size(), 2);
995
996 assert_eq!(bundle.get_string("string"), Ok(Some("foo".to_string())));
997 assert_eq!(bundle.get_string("empty"), Ok(Some("".to_string())));
998 }
999
1000 #[test]
1001 fn insert_get_vec() {
1002 let mut bundle = PersistableBundle::new();
1003
1004 assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(()));
1005 assert_eq!(bundle.insert_int_vec("int", &[42]), Ok(()));
1006 assert_eq!(bundle.insert_long_vec("long", &[66, 67, 68]), Ok(()));
1007 assert_eq!(bundle.insert_double_vec("double", &[123.4]), Ok(()));
1008 assert_eq!(bundle.insert_string_vec("string", &["foo", "bar", "baz"]), Ok(()));
1009 assert_eq!(
1010 bundle.insert_string_vec(
1011 "string",
1012 &[&"foo".to_string(), &"bar".to_string(), &"baz".to_string()]
1013 ),
1014 Ok(())
1015 );
1016 assert_eq!(
1017 bundle.insert_string_vec(
1018 "string",
1019 &["foo".to_string(), "bar".to_string(), "baz".to_string()]
1020 ),
1021 Ok(())
1022 );
1023
1024 assert_eq!(bundle.size(), 5);
1025
1026 assert_eq!(bundle.get_bool_vec("bool"), Ok(Some(vec![])));
1027 assert_eq!(bundle.get_int_vec("int"), Ok(Some(vec![42])));
1028 assert_eq!(bundle.get_long_vec("long"), Ok(Some(vec![66, 67, 68])));
1029 assert_eq!(bundle.get_double_vec("double"), Ok(Some(vec![123.4])));
1030 assert_eq!(
1031 bundle.get_string_vec("string"),
1032 Ok(Some(vec!["foo".to_string(), "bar".to_string(), "baz".to_string()]))
1033 );
1034 }
1035
1036 #[test]
1037 fn insert_get_bundle() {
1038 let mut bundle = PersistableBundle::new();
1039
1040 let mut sub_bundle = PersistableBundle::new();
1041 assert_eq!(sub_bundle.insert_int("int", 42), Ok(()));
1042 assert_eq!(sub_bundle.size(), 1);
1043 assert_eq!(bundle.insert_persistable_bundle("bundle", &sub_bundle), Ok(()));
1044
1045 assert_eq!(bundle.get_persistable_bundle("bundle"), Ok(Some(sub_bundle)));
1046 }
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 }
1076}