Skip to content

Commit 713a276

Browse files
Treehugger RobotGerrit Code Review
authored andcommitted
Merge "Add methods to get and insert primitives." into main
2 parents 5714afd + 4ebfd92 commit 713a276

1 file changed

Lines changed: 209 additions & 1 deletion

File tree

libs/binder/rust/src/persistable_bundle.rs

Lines changed: 209 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ use crate::{
2222
};
2323
use 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};
2832
use 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

Comments
 (0)