Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d67998a8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add methods to get vectors." into main am: 430db867 am: 3d6cfc8c

parents 4c445497 3d6cfc8c
Loading
Loading
Loading
Loading
+117 −9
Original line number Original line Diff line number Diff line
@@ -22,17 +22,18 @@ use crate::{
};
};
use binder_ndk_sys::{
use binder_ndk_sys::{
    APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
    APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
    APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getDouble,
    APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanVector,
    APersistableBundle_getInt, APersistableBundle_getLong, APersistableBundle_getPersistableBundle,
    APersistableBundle_getDouble, APersistableBundle_getDoubleVector, APersistableBundle_getInt,
    APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_putBoolean,
    APersistableBundle_getIntVector, APersistableBundle_getLong, APersistableBundle_getLongVector,
    APersistableBundle_putBooleanVector, APersistableBundle_putDouble,
    APersistableBundle_getPersistableBundle, APersistableBundle_isEqual, APersistableBundle_new,
    APersistableBundle_putDoubleVector, APersistableBundle_putInt, APersistableBundle_putIntVector,
    APersistableBundle_putBoolean, APersistableBundle_putBooleanVector,
    APersistableBundle_putLong, APersistableBundle_putLongVector,
    APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt,
    APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector,
    APersistableBundle_putPersistableBundle, APersistableBundle_putString,
    APersistableBundle_putPersistableBundle, APersistableBundle_putString,
    APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size,
    APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size,
    APersistableBundle_writeToParcel,
    APersistableBundle_writeToParcel, APERSISTABLEBUNDLE_KEY_NOT_FOUND,
};
};
use std::ffi::{CString, NulError};
use std::ffi::{c_char, CString, NulError};
use std::ptr::{null_mut, NonNull};
use std::ptr::{null_mut, NonNull};


/// A mapping from string keys to values of various types.
/// A mapping from string keys to values of various types.
@@ -373,6 +374,104 @@ impl PersistableBundle {
        }
        }
    }
    }


    /// Gets the vector of `T` associated with the given key.
    ///
    /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
    /// in the bundle.
    ///
    /// `get_func` should be one of the `APersistableBundle_get*Vector` functions from
    /// `binder_ndk_sys`.
    ///
    /// # Safety
    ///
    /// `get_func` must only require that the pointers it takes are valid for the duration of the
    /// call. It must allow a null pointer for the buffer, and must return the size in bytes of
    /// buffer it requires. If it is given a non-null buffer pointer it must write that number of
    /// bytes to the buffer, which must be a whole number of valid `T` values.
    unsafe fn get_vec<T: Clone + Default>(
        &self,
        key: &str,
        get_func: unsafe extern "C" fn(
            *const APersistableBundle,
            *const c_char,
            *mut T,
            i32,
        ) -> i32,
    ) -> Result<Option<Vec<T>>, NulError> {
        let key = CString::new(key)?;
        // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
        // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
        // to be valid for the lifetime of `key`. A null pointer is allowed for the buffer.
        match unsafe { get_func(self.0.as_ptr(), key.as_ptr(), null_mut(), 0) } {
            APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None),
            required_buffer_size => {
                let mut value = vec![
                    T::default();
                    usize::try_from(required_buffer_size).expect(
                        "APersistableBundle_get*Vector returned invalid size"
                    ) / size_of::<T>()
                ];
                // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
                // the lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()`
                // is guaranteed to be valid for the lifetime of `key`. The value buffer pointer is
                // valid as it comes from the Vec we just allocated.
                match unsafe {
                    get_func(
                        self.0.as_ptr(),
                        key.as_ptr(),
                        value.as_mut_ptr(),
                        (value.len() * size_of::<T>()).try_into().unwrap(),
                    )
                } {
                    APERSISTABLEBUNDLE_KEY_NOT_FOUND => {
                        panic!("APersistableBundle_get*Vector failed to find key after first finding it");
                    }
                    _ => Ok(Some(value)),
                }
            }
        }
    }

    /// Gets the boolean vector value associated with the given key.
    ///
    /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
    /// in the bundle.
    pub fn get_bool_vec(&self, key: &str) -> Result<Option<Vec<bool>>, NulError> {
        // SAFETY: APersistableBundle_getBooleanVector fulfils all the safety requirements of
        // `get_vec`.
        unsafe { self.get_vec(key, APersistableBundle_getBooleanVector) }
    }

    /// Gets the i32 vector value associated with the given key.
    ///
    /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
    /// in the bundle.
    pub fn get_int_vec(&self, key: &str) -> Result<Option<Vec<i32>>, NulError> {
        // SAFETY: APersistableBundle_getIntVector fulfils all the safety requirements of
        // `get_vec`.
        unsafe { self.get_vec(key, APersistableBundle_getIntVector) }
    }

    /// Gets the i64 vector value associated with the given key.
    ///
    /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
    /// in the bundle.
    pub fn get_long_vec(&self, key: &str) -> Result<Option<Vec<i64>>, NulError> {
        // SAFETY: APersistableBundle_getLongVector fulfils all the safety requirements of
        // `get_vec`.
        unsafe { self.get_vec(key, APersistableBundle_getLongVector) }
    }

    /// Gets the f64 vector value associated with the given key.
    ///
    /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
    /// in the bundle.
    pub fn get_double_vec(&self, key: &str) -> Result<Option<Vec<f64>>, NulError> {
        // SAFETY: APersistableBundle_getDoubleVector fulfils all the safety requirements of
        // `get_vec`.
        unsafe { self.get_vec(key, APersistableBundle_getDoubleVector) }
    }

    /// Gets the `PersistableBundle` value associated with the given key.
    /// Gets the `PersistableBundle` value associated with the given key.
    ///
    ///
    /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
    /// 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 {
        assert_eq!(bundle.get_int("foo"), Ok(None));
        assert_eq!(bundle.get_int("foo"), Ok(None));
        assert_eq!(bundle.get_long("foo"), Ok(None));
        assert_eq!(bundle.get_long("foo"), Ok(None));
        assert_eq!(bundle.get_double("foo"), Ok(None));
        assert_eq!(bundle.get_double("foo"), Ok(None));
        assert_eq!(bundle.get_bool_vec("foo"), Ok(None));
        assert_eq!(bundle.get_int_vec("foo"), Ok(None));
        assert_eq!(bundle.get_long_vec("foo"), Ok(None));
        assert_eq!(bundle.get_double_vec("foo"), Ok(None));
    }
    }


    #[test]
    #[test]
@@ -543,7 +646,7 @@ mod test {
    }
    }


    #[test]
    #[test]
    fn insert_vec() {
    fn insert_get_vec() {
        let mut bundle = PersistableBundle::new();
        let mut bundle = PersistableBundle::new();


        assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(()));
        assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(()));
@@ -567,6 +670,11 @@ mod test {
        );
        );


        assert_eq!(bundle.size(), 5);
        assert_eq!(bundle.size(), 5);

        assert_eq!(bundle.get_bool_vec("bool"), Ok(Some(vec![])));
        assert_eq!(bundle.get_int_vec("int"), Ok(Some(vec![42])));
        assert_eq!(bundle.get_long_vec("long"), Ok(Some(vec![66, 67, 68])));
        assert_eq!(bundle.get_double_vec("double"), Ok(Some(vec![123.4])));
    }
    }


    #[test]
    #[test]
+5 −0
Original line number Original line Diff line number Diff line
@@ -92,6 +92,11 @@ enum {
#endif
#endif
};
};


enum {
    APERSISTABLEBUNDLE_KEY_NOT_FOUND = APERSISTABLEBUNDLE_KEY_NOT_FOUND,
    APERSISTABLEBUNDLE_ALLOCATOR_FAILED = APERSISTABLEBUNDLE_ALLOCATOR_FAILED,
};

} // namespace consts
} // namespace consts


} // namespace c_interface
} // namespace c_interface