diff options
Diffstat (limited to 'libs/binder/rust/src/parcel/parcelable.rs')
-rw-r--r-- | libs/binder/rust/src/parcel/parcelable.rs | 989 |
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); +} |