summaryrefslogtreecommitdiff
path: root/libs/binder/rust/src/parcel/parcelable.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libs/binder/rust/src/parcel/parcelable.rs')
-rw-r--r--libs/binder/rust/src/parcel/parcelable.rs989
1 files changed, 989 insertions, 0 deletions
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
new file mode 100644
index 0000000000..f57788b87e
--- /dev/null
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -0,0 +1,989 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::binder::{AsNative, FromIBinder, Strong};
+use crate::error::{status_result, status_t, Result, Status, StatusCode};
+use crate::parcel::Parcel;
+use crate::proxy::SpIBinder;
+use crate::sys;
+
+use std::convert::TryInto;
+use std::ffi::c_void;
+use std::os::raw::{c_char, c_ulong};
+use std::mem::{self, MaybeUninit};
+use std::ptr;
+use std::slice;
+
+/// A struct whose instances can be written to a [`Parcel`].
+// Might be able to hook this up as a serde backend in the future?
+pub trait Serialize {
+ /// Serialize this instance into the given [`Parcel`].
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()>;
+}
+
+/// A struct whose instances can be restored from a [`Parcel`].
+// Might be able to hook this up as a serde backend in the future?
+pub trait Deserialize: Sized {
+ /// Deserialize an instance from the given [`Parcel`].
+ fn deserialize(parcel: &Parcel) -> Result<Self>;
+}
+
+/// Helper trait for types that can be serialized as arrays.
+/// Defaults to calling Serialize::serialize() manually for every element,
+/// but can be overridden for custom implementations like `writeByteArray`.
+// Until specialization is stabilized in Rust, we need this to be a separate
+// trait because it's the only way to have a default implementation for a method.
+// We want the default implementation for most types, but an override for
+// a few special ones like `readByteArray` for `u8`.
+pub trait SerializeArray: Serialize + Sized {
+ /// Serialize an array of this type into the given [`Parcel`].
+ fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+ let res = unsafe {
+ // Safety: Safe FFI, slice will always be a safe pointer to pass.
+ sys::AParcel_writeParcelableArray(
+ parcel.as_native_mut(),
+ slice.as_ptr() as *const c_void,
+ slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?,
+ Some(serialize_element::<Self>),
+ )
+ };
+ status_result(res)
+ }
+}
+
+/// Callback to serialize an element of a generic parcelable array.
+///
+/// Safety: We are relying on binder_ndk to not overrun our slice. As long as it
+/// doesn't provide an index larger than the length of the original slice in
+/// serialize_array, this operation is safe. The index provided is zero-based.
+unsafe extern "C" fn serialize_element<T: Serialize>(
+ parcel: *mut sys::AParcel,
+ array: *const c_void,
+ index: c_ulong,
+) -> status_t {
+ // c_ulong and usize are the same, but we need the explicitly sized version
+ // so the function signature matches what bindgen generates.
+ let index = index as usize;
+
+ let slice: &[T] = slice::from_raw_parts(array.cast(), index+1);
+
+ let mut parcel = match Parcel::borrowed(parcel) {
+ None => return StatusCode::UNEXPECTED_NULL as status_t,
+ Some(p) => p,
+ };
+
+ slice[index].serialize(&mut parcel)
+ .err()
+ .unwrap_or(StatusCode::OK)
+ as status_t
+}
+
+/// Helper trait for types that can be deserialized as arrays.
+/// Defaults to calling Deserialize::deserialize() manually for every element,
+/// but can be overridden for custom implementations like `readByteArray`.
+pub trait DeserializeArray: Deserialize {
+ /// Deserialize an array of type from the given [`Parcel`].
+ fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> {
+ let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
+ let res = unsafe {
+ // Safety: Safe FFI, vec is the correct opaque type expected by
+ // allocate_vec and deserialize_element.
+ sys::AParcel_readParcelableArray(
+ parcel.as_native(),
+ &mut vec as *mut _ as *mut c_void,
+ Some(allocate_vec::<Self>),
+ Some(deserialize_element::<Self>),
+ )
+ };
+ status_result(res)?;
+ let vec: Option<Vec<Self>> = unsafe {
+ // Safety: We are assuming that the NDK correctly initialized every
+ // element of the vector by now, so we know that all the
+ // MaybeUninits are now properly initialized. We can transmute from
+ // Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T> has the same
+ // alignment and size as T, so the pointer to the vector allocation
+ // will be compatible.
+ mem::transmute(vec)
+ };
+ Ok(vec)
+ }
+}
+
+/// Callback to deserialize a parcelable element.
+///
+/// The opaque array data pointer must be a mutable pointer to an
+/// `Option<Vec<MaybeUninit<T>>>` with at least enough elements for `index` to be valid
+/// (zero-based).
+unsafe extern "C" fn deserialize_element<T: Deserialize>(
+ parcel: *const sys::AParcel,
+ array: *mut c_void,
+ index: c_ulong,
+) -> status_t {
+ // c_ulong and usize are the same, but we need the explicitly sized version
+ // so the function signature matches what bindgen generates.
+ let index = index as usize;
+
+ let vec = &mut *(array as *mut Option<Vec<MaybeUninit<T>>>);
+ let vec = match vec {
+ Some(v) => v,
+ None => return StatusCode::BAD_INDEX as status_t,
+ };
+
+ let parcel = match Parcel::borrowed(parcel as *mut _) {
+ None => return StatusCode::UNEXPECTED_NULL as status_t,
+ Some(p) => p,
+ };
+ let element = match parcel.read() {
+ Ok(e) => e,
+ Err(code) => return code as status_t,
+ };
+ ptr::write(vec[index].as_mut_ptr(), element);
+ StatusCode::OK as status_t
+}
+
+/// Helper trait for types that can be nullable when serialized.
+// We really need this trait instead of implementing `Serialize for Option<T>`
+// because of the Rust orphan rule which prevents us from doing
+// `impl Serialize for Option<&dyn IFoo>` for AIDL interfaces.
+// Instead we emit `impl SerializeOption for dyn IFoo` which is allowed.
+// We also use it to provide a default implementation for AIDL-generated
+// parcelables.
+pub trait SerializeOption: Serialize {
+ /// Serialize an Option of this type into the given [`Parcel`].
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ if let Some(inner) = this {
+ parcel.write(&1i32)?;
+ parcel.write(inner)
+ } else {
+ parcel.write(&0i32)
+ }
+ }
+}
+
+/// Helper trait for types that can be nullable when deserialized.
+pub trait DeserializeOption: Deserialize {
+ /// Deserialize an Option of this type from the given [`Parcel`].
+ fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+ let null: i32 = parcel.read()?;
+ if null == 0 {
+ Ok(None)
+ } else {
+ parcel.read().map(Some)
+ }
+ }
+}
+
+/// Callback to allocate a vector for parcel array read functions.
+///
+/// This variant is for APIs which use an out buffer pointer.
+///
+/// # Safety
+///
+/// The opaque data pointer passed to the array read function must be a mutable
+/// pointer to an `Option<Vec<MaybeUninit<T>>>`. `buffer` will be assigned a mutable pointer
+/// to the allocated vector data if this function returns true.
+unsafe extern "C" fn allocate_vec_with_buffer<T>(
+ data: *mut c_void,
+ len: i32,
+ buffer: *mut *mut T,
+) -> bool {
+ let res = allocate_vec::<T>(data, len);
+ let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>);
+ if let Some(new_vec) = vec {
+ *buffer = new_vec.as_mut_ptr() as *mut T;
+ }
+ res
+}
+
+/// Callback to allocate a vector for parcel array read functions.
+///
+/// # Safety
+///
+/// The opaque data pointer passed to the array read function must be a mutable
+/// pointer to an `Option<Vec<MaybeUninit<T>>>`.
+unsafe extern "C" fn allocate_vec<T>(
+ data: *mut c_void,
+ len: i32,
+) -> bool {
+ let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>);
+ if len < 0 {
+ *vec = None;
+ return true;
+ }
+ let mut new_vec: Vec<MaybeUninit<T>> = Vec::with_capacity(len as usize);
+
+ // Safety: We are filling the vector with uninitialized data here, but this
+ // is safe because the vector contains MaybeUninit elements which can be
+ // uninitialized. We're putting off the actual unsafe bit, transmuting the
+ // vector to a Vec<T> until the contents are initialized.
+ new_vec.set_len(len as usize);
+
+ ptr::write(vec, Some(new_vec));
+ true
+}
+
+
+macro_rules! parcelable_primitives {
+ {
+ $(
+ impl $trait:ident for $ty:ty = $fn:path;
+ )*
+ } => {
+ $(impl_parcelable!{$trait, $ty, $fn})*
+ };
+}
+
+macro_rules! impl_parcelable {
+ {Serialize, $ty:ty, $write_fn:path} => {
+ impl Serialize for $ty {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`, and any `$ty` literal value is safe to pass to
+ // `$write_fn`.
+ status_result($write_fn(parcel.as_native_mut(), *self))
+ }
+ }
+ }
+ };
+
+ {Deserialize, $ty:ty, $read_fn:path} => {
+ impl Deserialize for $ty {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ let mut val = Self::default();
+ unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. We pass a valid, mutable pointer to `val`, a
+ // literal of type `$ty`, and `$read_fn` will write the
+ // value read into `val` if successful
+ status_result($read_fn(parcel.as_native(), &mut val))?
+ };
+ Ok(val)
+ }
+ }
+ };
+
+ {SerializeArray, $ty:ty, $write_array_fn:path} => {
+ impl SerializeArray for $ty {
+ fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+ let status = unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. If the slice is > 0 length, `slice.as_ptr()`
+ // will be a valid pointer to an array of elements of type
+ // `$ty`. If the slice length is 0, `slice.as_ptr()` may be
+ // dangling, but this is safe since the pointer is not
+ // dereferenced if the length parameter is 0.
+ $write_array_fn(
+ parcel.as_native_mut(),
+ slice.as_ptr(),
+ slice
+ .len()
+ .try_into()
+ .or(Err(StatusCode::BAD_VALUE))?,
+ )
+ };
+ status_result(status)
+ }
+ }
+ };
+
+ {DeserializeArray, $ty:ty, $read_array_fn:path} => {
+ impl DeserializeArray for $ty {
+ fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> {
+ let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
+ let status = unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. `allocate_vec<T>` expects the opaque pointer to
+ // be of type `*mut Option<Vec<MaybeUninit<T>>>`, so `&mut vec` is
+ // correct for it.
+ $read_array_fn(
+ parcel.as_native(),
+ &mut vec as *mut _ as *mut c_void,
+ Some(allocate_vec_with_buffer),
+ )
+ };
+ status_result(status)?;
+ let vec: Option<Vec<Self>> = unsafe {
+ // Safety: We are assuming that the NDK correctly
+ // initialized every element of the vector by now, so we
+ // know that all the MaybeUninits are now properly
+ // initialized. We can transmute from Vec<MaybeUninit<T>> to
+ // Vec<T> because MaybeUninit<T> has the same alignment and
+ // size as T, so the pointer to the vector allocation will
+ // be compatible.
+ mem::transmute(vec)
+ };
+ Ok(vec)
+ }
+ }
+ };
+}
+
+parcelable_primitives! {
+ impl Serialize for bool = sys::AParcel_writeBool;
+ impl Deserialize for bool = sys::AParcel_readBool;
+
+ // This is only safe because `Option<Vec<u8>>` is interchangeable with
+ // `Option<Vec<i8>>` (what the allocator function actually allocates.
+ impl DeserializeArray for u8 = sys::AParcel_readByteArray;
+
+ impl Serialize for i8 = sys::AParcel_writeByte;
+ impl Deserialize for i8 = sys::AParcel_readByte;
+ impl SerializeArray for i8 = sys::AParcel_writeByteArray;
+ impl DeserializeArray for i8 = sys::AParcel_readByteArray;
+
+ impl Serialize for u16 = sys::AParcel_writeChar;
+ impl Deserialize for u16 = sys::AParcel_readChar;
+ impl SerializeArray for u16 = sys::AParcel_writeCharArray;
+ impl DeserializeArray for u16 = sys::AParcel_readCharArray;
+
+ // This is only safe because `Option<Vec<i16>>` is interchangeable with
+ // `Option<Vec<u16>>` (what the allocator function actually allocates.
+ impl DeserializeArray for i16 = sys::AParcel_readCharArray;
+
+ impl Serialize for u32 = sys::AParcel_writeUint32;
+ impl Deserialize for u32 = sys::AParcel_readUint32;
+ impl SerializeArray for u32 = sys::AParcel_writeUint32Array;
+ impl DeserializeArray for u32 = sys::AParcel_readUint32Array;
+
+ impl Serialize for i32 = sys::AParcel_writeInt32;
+ impl Deserialize for i32 = sys::AParcel_readInt32;
+ impl SerializeArray for i32 = sys::AParcel_writeInt32Array;
+ impl DeserializeArray for i32 = sys::AParcel_readInt32Array;
+
+ impl Serialize for u64 = sys::AParcel_writeUint64;
+ impl Deserialize for u64 = sys::AParcel_readUint64;
+ impl SerializeArray for u64 = sys::AParcel_writeUint64Array;
+ impl DeserializeArray for u64 = sys::AParcel_readUint64Array;
+
+ impl Serialize for i64 = sys::AParcel_writeInt64;
+ impl Deserialize for i64 = sys::AParcel_readInt64;
+ impl SerializeArray for i64 = sys::AParcel_writeInt64Array;
+ impl DeserializeArray for i64 = sys::AParcel_readInt64Array;
+
+ impl Serialize for f32 = sys::AParcel_writeFloat;
+ impl Deserialize for f32 = sys::AParcel_readFloat;
+ impl SerializeArray for f32 = sys::AParcel_writeFloatArray;
+ impl DeserializeArray for f32 = sys::AParcel_readFloatArray;
+
+ impl Serialize for f64 = sys::AParcel_writeDouble;
+ impl Deserialize for f64 = sys::AParcel_readDouble;
+ impl SerializeArray for f64 = sys::AParcel_writeDoubleArray;
+ impl DeserializeArray for f64 = sys::AParcel_readDoubleArray;
+}
+
+impl SerializeArray for bool {}
+impl DeserializeArray for bool {}
+
+impl Serialize for u8 {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ (*self as i8).serialize(parcel)
+ }
+}
+
+impl Deserialize for u8 {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ i8::deserialize(parcel).map(|v| v as u8)
+ }
+}
+
+impl SerializeArray for u8 {
+ fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+ let status = unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` will be a
+ // valid pointer to an array of elements of type `$ty`. If the slice
+ // length is 0, `slice.as_ptr()` may be dangling, but this is safe
+ // since the pointer is not dereferenced if the length parameter is
+ // 0.
+ sys::AParcel_writeByteArray(
+ parcel.as_native_mut(),
+ slice.as_ptr() as *const i8,
+ slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?,
+ )
+ };
+ status_result(status)
+ }
+}
+
+impl Serialize for i16 {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ (*self as u16).serialize(parcel)
+ }
+}
+
+impl Deserialize for i16 {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ u16::deserialize(parcel).map(|v| v as i16)
+ }
+}
+
+impl SerializeArray for i16 {
+ fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
+ let status = unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` will be a
+ // valid pointer to an array of elements of type `$ty`. If the slice
+ // length is 0, `slice.as_ptr()` may be dangling, but this is safe
+ // since the pointer is not dereferenced if the length parameter is
+ // 0.
+ sys::AParcel_writeCharArray(
+ parcel.as_native_mut(),
+ slice.as_ptr() as *const u16,
+ slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?,
+ )
+ };
+ status_result(status)
+ }
+}
+
+impl SerializeOption for str {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ match this {
+ None => unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. If the string pointer is null,
+ // `AParcel_writeString` requires that the length is -1 to
+ // indicate that we want to serialize a null string.
+ status_result(sys::AParcel_writeString(
+ parcel.as_native_mut(),
+ ptr::null(),
+ -1,
+ ))
+ },
+ Some(s) => unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. `AParcel_writeString` assumes that we pass a utf-8
+ // string pointer of `length` bytes, which is what str in Rust
+ // is. The docstring for `AParcel_writeString` says that the
+ // string input should be null-terminated, but it doesn't
+ // actually rely on that fact in the code. If this ever becomes
+ // necessary, we will need to null-terminate the str buffer
+ // before sending it.
+ status_result(sys::AParcel_writeString(
+ parcel.as_native_mut(),
+ s.as_ptr() as *const c_char,
+ s.as_bytes()
+ .len()
+ .try_into()
+ .or(Err(StatusCode::BAD_VALUE))?,
+ ))
+ },
+ }
+ }
+}
+
+impl SerializeArray for Option<&str> {}
+
+impl Serialize for str {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Some(self).serialize(parcel)
+ }
+}
+
+impl SerializeArray for &str {}
+
+impl Serialize for String {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Some(self.as_str()).serialize(parcel)
+ }
+}
+
+impl SerializeArray for String {}
+
+impl SerializeOption for String {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ SerializeOption::serialize_option(this.map(String::as_str), parcel)
+ }
+}
+
+impl SerializeArray for Option<String> {}
+
+impl Deserialize for Option<String> {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ let mut vec: Option<Vec<u8>> = None;
+ let status = unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an `AParcel`.
+ // `Option<Vec<u8>>` is equivalent to the expected `Option<Vec<i8>>`
+ // for `allocate_vec`, so `vec` is safe to pass as the opaque data
+ // pointer on platforms where char is signed.
+ sys::AParcel_readString(
+ parcel.as_native(),
+ &mut vec as *mut _ as *mut c_void,
+ Some(allocate_vec_with_buffer),
+ )
+ };
+
+ status_result(status)?;
+ vec.map(|mut s| {
+ // The vector includes a null-terminator and we don't want the
+ // string to be null-terminated for Rust.
+ s.pop();
+ String::from_utf8(s).or(Err(StatusCode::BAD_VALUE))
+ })
+ .transpose()
+ }
+}
+
+impl DeserializeArray for Option<String> {}
+
+impl Deserialize for String {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ Deserialize::deserialize(parcel)
+ .transpose()
+ .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
+ }
+}
+
+impl DeserializeArray for String {}
+
+impl<T: SerializeArray> Serialize for [T] {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ SerializeArray::serialize_array(self, parcel)
+ }
+}
+
+impl<T: SerializeArray> Serialize for Vec<T> {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ SerializeArray::serialize_array(&self[..], parcel)
+ }
+}
+
+impl<T: SerializeArray> SerializeOption for [T] {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ if let Some(v) = this {
+ SerializeArray::serialize_array(v, parcel)
+ } else {
+ parcel.write(&-1i32)
+ }
+ }
+}
+
+impl<T: SerializeArray> SerializeOption for Vec<T> {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ SerializeOption::serialize_option(this.map(Vec::as_slice), parcel)
+ }
+}
+
+impl<T: DeserializeArray> Deserialize for Vec<T> {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ DeserializeArray::deserialize_array(parcel)
+ .transpose()
+ .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
+ }
+}
+
+impl<T: DeserializeArray> DeserializeOption for Vec<T> {
+ fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+ DeserializeArray::deserialize_array(parcel)
+ }
+}
+
+impl Serialize for Status {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an `AParcel`
+ // and `Status` always contains a valid pointer to an `AStatus`, so
+ // both parameters are valid and safe. This call does not take
+ // ownership of either of its parameters.
+ status_result(sys::AParcel_writeStatusHeader(
+ parcel.as_native_mut(),
+ self.as_native(),
+ ))
+ }
+ }
+}
+
+impl Deserialize for Status {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ let mut status_ptr = ptr::null_mut();
+ let ret_status = unsafe {
+ // Safety: `Parcel` always contains a valid pointer to an
+ // `AParcel`. We pass a mutable out pointer which will be
+ // assigned a valid `AStatus` pointer if the function returns
+ // status OK. This function passes ownership of the status
+ // pointer to the caller, if it was assigned.
+ sys::AParcel_readStatusHeader(parcel.as_native(), &mut status_ptr)
+ };
+ status_result(ret_status)?;
+ Ok(unsafe {
+ // Safety: At this point, the return status of the read call was ok,
+ // so we know that `status_ptr` is a valid, owned pointer to an
+ // `AStatus`, from which we can safely construct a `Status` object.
+ Status::from_ptr(status_ptr)
+ })
+ }
+}
+
+impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Serialize::serialize(&**self, parcel)
+ }
+}
+
+impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ SerializeOption::serialize_option(this.map(|b| &**b), parcel)
+ }
+}
+
+impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ let ibinder: SpIBinder = parcel.read()?;
+ FromIBinder::try_from(ibinder)
+ }
+}
+
+impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> {
+ fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+ let ibinder: Option<SpIBinder> = parcel.read()?;
+ ibinder.map(FromIBinder::try_from).transpose()
+ }
+}
+
+// We need these to support Option<&T> for all T
+impl<T: Serialize + ?Sized> Serialize for &T {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Serialize::serialize(*self, parcel)
+ }
+}
+
+impl<T: SerializeOption + ?Sized> SerializeOption for &T {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ SerializeOption::serialize_option(this.copied(), parcel)
+ }
+}
+
+impl<T: SerializeOption> Serialize for Option<T> {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ SerializeOption::serialize_option(self.as_ref(), parcel)
+ }
+}
+
+impl<T: DeserializeOption> Deserialize for Option<T> {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ DeserializeOption::deserialize_option(parcel)
+ }
+}
+
+#[test]
+fn test_custom_parcelable() {
+ use crate::binder::Interface;
+ use crate::native::Binder;
+ let mut service = Binder::new(()).as_binder();
+
+ struct Custom(u32, bool, String, Vec<String>);
+
+ impl Serialize for Custom {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ self.0.serialize(parcel)?;
+ self.1.serialize(parcel)?;
+ self.2.serialize(parcel)?;
+ self.3.serialize(parcel)
+ }
+ }
+
+ impl Deserialize for Custom {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ Ok(Custom(
+ parcel.read()?,
+ parcel.read()?,
+ parcel.read()?,
+ parcel.read::<Option<Vec<String>>>()?.unwrap(),
+ ))
+ }
+ }
+
+ let string8 = "Custom Parcelable".to_string();
+
+ let s1 = "str1".to_string();
+ let s2 = "str2".to_string();
+ let s3 = "str3".to_string();
+
+ let strs = vec![s1, s2, s3];
+
+ let custom = Custom(123_456_789, true, string8, strs);
+
+ let mut parcel = Parcel::new_for_test(&mut service).unwrap();
+ let start = parcel.get_data_position();
+
+ assert!(custom.serialize(&mut parcel).is_ok());
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let custom2 = Custom::deserialize(&parcel).unwrap();
+
+ assert_eq!(custom2.0, 123_456_789);
+ assert!(custom2.1);
+ assert_eq!(custom2.2, custom.2);
+ assert_eq!(custom2.3, custom.3);
+}
+
+#[test]
+#[allow(clippy::excessive_precision)]
+fn test_slice_parcelables() {
+ use crate::binder::Interface;
+ use crate::native::Binder;
+ let mut service = Binder::new(()).as_binder();
+
+ let bools = [true, false, false, true];
+
+ let mut parcel = Parcel::new_for_test(&mut service).unwrap();
+ let start = parcel.get_data_position();
+
+ assert!(bools.serialize(&mut parcel).is_ok());
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert_eq!(parcel.read::<u32>().unwrap(), 4);
+ assert_eq!(parcel.read::<u32>().unwrap(), 1);
+ assert_eq!(parcel.read::<u32>().unwrap(), 0);
+ assert_eq!(parcel.read::<u32>().unwrap(), 0);
+ assert_eq!(parcel.read::<u32>().unwrap(), 1);
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<bool>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, [true, false, false, true]);
+
+ let u8s = [101u8, 255, 42, 117];
+
+ let mut parcel = Parcel::new_for_test(&mut service).unwrap();
+ let start = parcel.get_data_position();
+
+ assert!(parcel.write(&u8s[..]).is_ok());
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+ assert_eq!(parcel.read::<u32>().unwrap(), 0x752aff65); // bytes
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<u8>::deserialize(&parcel).unwrap();
+ assert_eq!(vec, [101, 255, 42, 117]);
+
+ let i8s = [-128i8, 127, 42, -117];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert!(parcel.write(&i8s[..]).is_ok());
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+ assert_eq!(parcel.read::<u32>().unwrap(), 0x8b2a7f80); // bytes
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<u8>::deserialize(&parcel).unwrap();
+ assert_eq!(vec, [-128i8 as u8, 127, 42, -117i8 as u8]);
+
+ let u16s = [u16::max_value(), 12_345, 42, 117];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(u16s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+ assert_eq!(parcel.read::<u32>().unwrap(), 0xffff); // u16::max_value()
+ assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345
+ assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+ assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<u16>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, [u16::max_value(), 12_345, 42, 117]);
+
+ let i16s = [i16::max_value(), i16::min_value(), 42, -117];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(i16s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+ assert_eq!(parcel.read::<u32>().unwrap(), 0x7fff); // i16::max_value()
+ assert_eq!(parcel.read::<u32>().unwrap(), 0x8000); // i16::min_value()
+ assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+ assert_eq!(parcel.read::<u32>().unwrap(), 0xff8b); // -117
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<i16>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, [i16::max_value(), i16::min_value(), 42, -117]);
+
+ let u32s = [u32::max_value(), 12_345, 42, 117];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(u32s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+ assert_eq!(parcel.read::<u32>().unwrap(), 0xffffffff); // u32::max_value()
+ assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345
+ assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+ assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<u32>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, [u32::max_value(), 12_345, 42, 117]);
+
+ let i32s = [i32::max_value(), i32::min_value(), 42, -117];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(i32s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items
+ assert_eq!(parcel.read::<u32>().unwrap(), 0x7fffffff); // i32::max_value()
+ assert_eq!(parcel.read::<u32>().unwrap(), 0x80000000); // i32::min_value()
+ assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42
+ assert_eq!(parcel.read::<u32>().unwrap(), 0xffffff8b); // -117
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<i32>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, [i32::max_value(), i32::min_value(), 42, -117]);
+
+ let u64s = [u64::max_value(), 12_345, 42, 117];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(u64s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<u64>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, [u64::max_value(), 12_345, 42, 117]);
+
+ let i64s = [i64::max_value(), i64::min_value(), 42, -117];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(i64s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<i64>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, [i64::max_value(), i64::min_value(), 42, -117]);
+
+ let f32s = [
+ std::f32::NAN,
+ std::f32::INFINITY,
+ 1.23456789,
+ std::f32::EPSILON,
+ ];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(f32s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<f32>::deserialize(&parcel).unwrap();
+
+ // NAN != NAN so we can't use it in the assert_eq:
+ assert!(vec[0].is_nan());
+ assert_eq!(vec[1..], f32s[1..]);
+
+ let f64s = [
+ std::f64::NAN,
+ std::f64::INFINITY,
+ 1.234567890123456789,
+ std::f64::EPSILON,
+ ];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(f64s.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<f64>::deserialize(&parcel).unwrap();
+
+ // NAN != NAN so we can't use it in the assert_eq:
+ assert!(vec[0].is_nan());
+ assert_eq!(vec[1..], f64s[1..]);
+
+ let s1 = "Hello, Binder!";
+ let s2 = "This is a utf8 string.";
+ let s3 = "Some more text here.";
+ let s4 = "Embedded nulls \0 \0";
+
+ let strs = [s1, s2, s3, s4];
+
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+ assert!(strs.serialize(&mut parcel).is_ok());
+ unsafe {
+ assert!(parcel.set_data_position(start).is_ok());
+ }
+
+ let vec = Vec::<String>::deserialize(&parcel).unwrap();
+
+ assert_eq!(vec, strs);
+}