blob: 33dfe19fe9e94122f9e999c6fd17dc22d6da8f39 [file] [log] [blame]
/*
* 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, Interface, Stability, Strong};
use crate::error::{status_result, status_t, Result, Status, StatusCode};
use crate::parcel::BorrowedParcel;
use crate::proxy::SpIBinder;
use crate::sys;
use std::convert::{TryFrom, TryInto};
use std::ffi::c_void;
use std::mem::{self, ManuallyDrop};
use std::os::raw::c_char;
use std::ptr;
use std::slice;
/// Super-trait for structured Binder parcelables, i.e. those generated from AIDL.
///
/// This trait is equivalent `android::Parcelable` in C++,
/// and defines a common interface that all parcelables need
/// to implement.
pub trait Parcelable {
/// Internal serialization function for parcelables.
///
/// This method is mainly for internal use.
/// `Serialize::serialize` and its variants are generally
/// preferred over this function, since the former also
/// prepend a header.
fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>;
/// Internal deserialization function for parcelables.
///
/// This method is mainly for internal use.
/// `Deserialize::deserialize` and its variants are generally
/// preferred over this function, since the former also
/// parse the additional header.
fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()>;
}
/// Super-trait for unstructured Binder parcelables, i.e. those implemented manually.
///
/// These differ from structured parcelables in that they may not have a reasonable default value
/// and so aren't required to implement `Default`.
pub trait UnstructuredParcelable: Sized {
/// Internal serialization function for parcelables.
///
/// This method is mainly for internal use. `Serialize::serialize` and its variants are
/// generally preferred over calling this function, since the former also prepend a header.
fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>;
/// Internal deserialization function for parcelables.
///
/// This method is mainly for internal use. `Deserialize::deserialize` and its variants are
/// generally preferred over calling this function, since the former also parse the additional
/// header.
fn from_parcel(parcel: &BorrowedParcel<'_>) -> Result<Self>;
/// Internal deserialization function for parcelables.
///
/// This method is mainly for internal use. `Deserialize::deserialize_from` and its variants are
/// generally preferred over calling this function, since the former also parse the additional
/// header.
fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
*self = Self::from_parcel(parcel)?;
Ok(())
}
}
/// A struct whose instances can be written to a [`crate::parcel::Parcel`].
// Might be able to hook this up as a serde backend in the future?
pub trait Serialize {
/// Serialize this instance into the given [`crate::parcel::Parcel`].
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>;
}
/// A struct whose instances can be restored from a [`crate::parcel::Parcel`].
// Might be able to hook this up as a serde backend in the future?
pub trait Deserialize: Sized {
/// Type for the uninitialized value of this type. Will be either `Self`
/// if the type implements `Default`, `Option<Self>` otherwise.
type UninitType;
/// Assert at compile-time that `Self` and `Self::UninitType` have the same
/// size and alignment. This will either fail to compile or evaluate to `true`.
/// The only two macros that work here are `panic!` and `assert!`, so we cannot
/// use `assert_eq!`.
const ASSERT_UNINIT_SIZE_AND_ALIGNMENT: bool = {
assert!(std::mem::size_of::<Self>() == std::mem::size_of::<Self::UninitType>());
assert!(std::mem::align_of::<Self>() == std::mem::align_of::<Self::UninitType>());
true
};
/// Return an uninitialized or default-initialized value for this type.
fn uninit() -> Self::UninitType;
/// Convert an initialized value of type `Self` into `Self::UninitType`.
fn from_init(value: Self) -> Self::UninitType;
/// Deserialize an instance from the given [`crate::parcel::Parcel`].
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self>;
/// Deserialize an instance from the given [`crate::parcel::Parcel`] onto the
/// current object. This operation will overwrite the old value
/// partially or completely, depending on how much data is available.
fn deserialize_from(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
*self = Self::deserialize(parcel)?;
Ok(())
}
}
/// 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 BorrowedParcel<'_>) -> Result<()> {
// Safety: Safe FFI, slice will always be a safe pointer to pass.
let res = unsafe {
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: usize,
) -> status_t {
// Safety: The caller guarantees that `array` is a valid pointer of the
// appropriate type.
let slice: &[T] = unsafe { slice::from_raw_parts(array.cast(), index + 1) };
// Safety: The caller must give us a parcel pointer which is either null or
// valid at least for the duration of this function call. We don't keep the
// resulting value beyond the function.
let mut parcel = match unsafe { BorrowedParcel::from_raw(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: &BorrowedParcel<'_>) -> Result<Option<Vec<Self>>> {
let mut vec: Option<Vec<Self::UninitType>> = None;
// Safety: Safe FFI, vec is the correct opaque type expected by
// allocate_vec and deserialize_element.
let res = unsafe {
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)?;
// Safety: We are assuming that the NDK correctly initialized every
// element of the vector by now, so we know that all the
// UninitTypes are now properly initialized. We can transmute from
// Vec<T::UninitType> to Vec<T> because T::UninitType has the same
// alignment and size as T, so the pointer to the vector allocation
// will be compatible.
let vec: Option<Vec<Self>> = unsafe { mem::transmute(vec) };
Ok(vec)
}
}
/// Callback to deserialize a parcelable element.
///
/// # Safety
///
/// The opaque array data pointer must be a mutable pointer to an
/// `Option<Vec<T::UninitType>>` 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: usize,
) -> status_t {
// Safety: The caller guarantees that `array` is a valid pointer of the
// appropriate type.
let vec = unsafe { &mut *(array as *mut Option<Vec<T::UninitType>>) };
let vec = match vec {
Some(v) => v,
None => return StatusCode::BAD_INDEX as status_t,
};
// Safety: The caller must give us a parcel pointer which is either null or
// valid at least for the duration of this function call. We don't keep the
// resulting value beyond the function.
let parcel = match unsafe { BorrowedParcel::from_raw(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,
};
vec[index] = T::from_init(element);
StatusCode::OK as status_t
}
/// Flag that specifies that the following parcelable is present.
///
/// This is the Rust equivalent of `Parcel::kNonNullParcelableFlag`
/// from `include/binder/Parcel.h` in C++.
pub const NON_NULL_PARCELABLE_FLAG: i32 = 1;
/// Flag that specifies that the following parcelable is absent.
///
/// This is the Rust equivalent of `Parcel::kNullParcelableFlag`
/// from `include/binder/Parcel.h` in C++.
pub const NULL_PARCELABLE_FLAG: i32 = 0;
/// 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 BorrowedParcel<'_>) -> Result<()> {
if let Some(inner) = this {
parcel.write(&NON_NULL_PARCELABLE_FLAG)?;
parcel.write(inner)
} else {
parcel.write(&NULL_PARCELABLE_FLAG)
}
}
}
/// 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: &BorrowedParcel<'_>) -> Result<Option<Self>> {
let null: i32 = parcel.read()?;
if null == NULL_PARCELABLE_FLAG {
Ok(None)
} else {
parcel.read().map(Some)
}
}
/// Deserialize an Option of this type from the given parcel onto the
/// current object. This operation will overwrite the current value
/// partially or completely, depending on how much data is available.
fn deserialize_option_from(this: &mut Option<Self>, parcel: &BorrowedParcel<'_>) -> Result<()> {
*this = Self::deserialize_option(parcel)?;
Ok(())
}
}
/// 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<T::UninitType>>`. `buffer` will be assigned a mutable pointer
/// to the allocated vector data if this function returns true. `buffer` must be a valid pointer.
unsafe extern "C" fn allocate_vec_with_buffer<T: Deserialize>(
data: *mut c_void,
len: i32,
buffer: *mut *mut T,
) -> bool {
// Safety: We have the same safety requirements as `allocate_vec` for `data`.
let res = unsafe { allocate_vec::<T>(data, len) };
// Safety: The caller guarantees that `data` is a valid mutable pointer to the appropriate type.
let vec = unsafe { &mut *(data as *mut Option<Vec<T::UninitType>>) };
if let Some(new_vec) = vec {
// Safety: The caller guarantees that `buffer` is a valid pointer.
unsafe {
*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<T::UninitType>>`.
unsafe extern "C" fn allocate_vec<T: Deserialize>(data: *mut c_void, len: i32) -> bool {
// Safety: The caller guarantees that `data` is a valid mutable pointer to the appropriate type.
let vec = unsafe { &mut *(data as *mut Option<Vec<T::UninitType>>) };
if len < 0 {
*vec = None;
return true;
}
// Assert at compile time that `T` and `T::UninitType` have the same size and alignment.
let _ = T::ASSERT_UNINIT_SIZE_AND_ALIGNMENT;
let mut new_vec: Vec<T::UninitType> = Vec::with_capacity(len as usize);
new_vec.resize_with(len as usize, T::uninit);
// Safety: The caller guarantees that vec is a valid mutable pointer to the appropriate type.
unsafe {
ptr::write(vec, Some(new_vec));
}
true
}
macro_rules! parcelable_primitives {
{
$(
impl $trait:ident for $ty:ty = $fn:path;
)*
} => {
$(impl_parcelable!{$trait, $ty, $fn})*
};
}
/// Safety: All elements in the vector must be properly initialized.
unsafe fn vec_assume_init<T: Deserialize>(vec: Vec<T::UninitType>) -> Vec<T> {
// Assert at compile time that `T` and `T::UninitType` have the same size and alignment.
let _ = T::ASSERT_UNINIT_SIZE_AND_ALIGNMENT;
let mut vec = ManuallyDrop::new(vec);
// Safety: We can convert from Vec<T::UninitType> to Vec<T> because
// T::UninitType has the same alignment and size as T, so the pointer to the
// vector allocation will be compatible.
unsafe { Vec::from_raw_parts(vec.as_mut_ptr().cast(), vec.len(), vec.capacity()) }
}
macro_rules! impl_parcelable {
{Serialize, $ty:ty, $write_fn:path} => {
impl Serialize for $ty {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
// Safety: `Parcel` always contains a valid pointer to an
// `AParcel`, and any `$ty` literal value is safe to pass to
// `$write_fn`.
unsafe {
status_result($write_fn(parcel.as_native_mut(), *self))
}
}
}
};
{Deserialize, $ty:ty, $read_fn:path} => {
impl Deserialize for $ty {
type UninitType = Self;
fn uninit() -> Self::UninitType { Self::UninitType::default() }
fn from_init(value: Self) -> Self::UninitType { value }
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let mut val = Self::default();
// 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
unsafe {
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 BorrowedParcel<'_>) -> Result<()> {
// 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.
let status = unsafe {
$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: &BorrowedParcel<'_>) -> Result<Option<Vec<Self>>> {
let mut vec: Option<Vec<Self::UninitType>> = None;
// Safety: `Parcel` always contains a valid pointer to an
// `AParcel`. `allocate_vec<T>` expects the opaque pointer to
// be of type `*mut Option<Vec<T::UninitType>>`, so `&mut vec` is
// correct for it.
let status = unsafe {
$read_array_fn(
parcel.as_native(),
&mut vec as *mut _ as *mut c_void,
Some(allocate_vec_with_buffer),
)
};
status_result(status)?;
// Safety: We are assuming that the NDK correctly
// initialized every element of the vector by now, so we
// know that all the UninitTypes are now properly
// initialized.
let vec: Option<Vec<Self>> = unsafe {
vec.map(|vec| vec_assume_init(vec))
};
Ok(vec)
}
}
};
}
impl<T: DeserializeOption> DeserializeArray for Option<T> {}
impl<T: SerializeOption> SerializeArray for Option<T> {}
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 BorrowedParcel<'_>) -> Result<()> {
(*self as i8).serialize(parcel)
}
}
impl Deserialize for u8 {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
i8::deserialize(parcel).map(|v| v as u8)
}
}
impl SerializeArray for u8 {
fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> {
// 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.
let status = unsafe {
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 BorrowedParcel<'_>) -> Result<()> {
(*self as u16).serialize(parcel)
}
}
impl Deserialize for i16 {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
u16::deserialize(parcel).map(|v| v as i16)
}
}
impl SerializeArray for i16 {
fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> {
// 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.
let status = unsafe {
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 BorrowedParcel<'_>) -> Result<()> {
match this {
// 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.
None => unsafe {
status_result(sys::AParcel_writeString(parcel.as_native_mut(), ptr::null(), -1))
},
// 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.
Some(s) => unsafe {
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 Serialize for str {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
Some(self).serialize(parcel)
}
}
impl SerializeArray for &str {}
impl Serialize for String {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
Some(self.as_str()).serialize(parcel)
}
}
impl SerializeArray for String {}
impl SerializeOption for String {
fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
SerializeOption::serialize_option(this.map(String::as_str), parcel)
}
}
impl Deserialize for Option<String> {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let mut vec: Option<Vec<u8>> = None;
// 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.
let status = unsafe {
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 {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> 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 BorrowedParcel<'_>) -> Result<()> {
SerializeArray::serialize_array(self, parcel)
}
}
impl<T: SerializeArray> Serialize for Vec<T> {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
SerializeArray::serialize_array(&self[..], parcel)
}
}
impl<T: SerializeArray> SerializeOption for [T] {
fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> 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 BorrowedParcel<'_>) -> Result<()> {
SerializeOption::serialize_option(this.map(Vec::as_slice), parcel)
}
}
impl<T: DeserializeArray> Deserialize for Vec<T> {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
DeserializeArray::deserialize_array(parcel)
.transpose()
.unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
}
impl<T: DeserializeArray> DeserializeOption for Vec<T> {
fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
DeserializeArray::deserialize_array(parcel)
}
}
impl<T: SerializeArray, const N: usize> Serialize for [T; N] {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
// forwards to T::serialize_array.
SerializeArray::serialize_array(self, parcel)
}
}
impl<T: SerializeArray, const N: usize> SerializeOption for [T; N] {
fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
SerializeOption::serialize_option(this.map(|arr| &arr[..]), parcel)
}
}
impl<T: SerializeArray, const N: usize> SerializeArray for [T; N] {}
impl<T: DeserializeArray, const N: usize> Deserialize for [T; N] {
type UninitType = [T::UninitType; N];
fn uninit() -> Self::UninitType {
[(); N].map(|_| T::uninit())
}
fn from_init(value: Self) -> Self::UninitType {
value.map(T::from_init)
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let vec = DeserializeArray::deserialize_array(parcel)
.transpose()
.unwrap_or(Err(StatusCode::UNEXPECTED_NULL))?;
vec.try_into().or(Err(StatusCode::BAD_VALUE))
}
}
impl<T: DeserializeArray, const N: usize> DeserializeOption for [T; N] {
fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
let vec = DeserializeArray::deserialize_array(parcel)?;
vec.map(|v| v.try_into().or(Err(StatusCode::BAD_VALUE))).transpose()
}
}
impl<T: DeserializeArray, const N: usize> DeserializeArray for [T; N] {}
impl Serialize for Stability {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
i32::from(*self).serialize(parcel)
}
}
impl Deserialize for Stability {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
i32::deserialize(parcel).and_then(Stability::try_from)
}
}
impl Serialize for Status {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
// 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.
unsafe {
status_result(sys::AParcel_writeStatusHeader(parcel.as_native_mut(), self.as_native()))
}
}
}
impl Deserialize for Status {
type UninitType = Option<Self>;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
Some(value)
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let mut status_ptr = ptr::null_mut();
let ret_status =
// 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.
unsafe { sys::AParcel_readStatusHeader(parcel.as_native(), &mut status_ptr) };
status_result(ret_status)?;
// 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.
Ok(unsafe { Status::from_ptr(status_ptr) })
}
}
impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
Serialize::serialize(&**self, parcel)
}
}
impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> {
fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
SerializeOption::serialize_option(this.map(|b| &**b), parcel)
}
}
impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {}
impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
type UninitType = Option<Strong<T>>;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
Some(value)
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let ibinder: SpIBinder = parcel.read()?;
FromIBinder::try_from(ibinder)
}
}
struct AssertIBinder;
impl Interface for AssertIBinder {}
impl FromIBinder for AssertIBinder {
// This is only needed so we can assert on the size of Strong<AssertIBinder>
fn try_from(_: SpIBinder) -> Result<Strong<Self>> {
unimplemented!()
}
}
impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> {
fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
let ibinder: Option<SpIBinder> = parcel.read()?;
ibinder.map(FromIBinder::try_from).transpose()
}
}
impl<T: FromIBinder + ?Sized> DeserializeArray for Strong<T> {}
// We need these to support Option<&T> for all T
impl<T: Serialize + ?Sized> Serialize for &T {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
Serialize::serialize(*self, parcel)
}
}
impl<T: SerializeOption + ?Sized> SerializeOption for &T {
fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
SerializeOption::serialize_option(this.copied(), parcel)
}
}
impl<T: SerializeOption> Serialize for Option<T> {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
SerializeOption::serialize_option(self.as_ref(), parcel)
}
}
impl<T: DeserializeOption> Deserialize for Option<T> {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
DeserializeOption::deserialize_option(parcel)
}
fn deserialize_from(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
DeserializeOption::deserialize_option_from(self, parcel)
}
}
/// Implement `Serialize` trait and friends for a parcelable
///
/// This is an internal macro used by the AIDL compiler to implement
/// `Serialize`, `SerializeArray` and `SerializeOption` for
/// structured parcelables. The target type must implement the
/// `Parcelable` trait.
#[macro_export]
macro_rules! impl_serialize_for_parcelable {
($parcelable:ident) => {
$crate::impl_serialize_for_parcelable!($parcelable < >);
};
($parcelable:ident < $( $param:ident ),* , >) => {
$crate::impl_serialize_for_parcelable!($parcelable < $($param),* >);
};
($parcelable:ident < $( $param:ident ),* > ) => {
impl < $($param),* > $crate::binder_impl::Serialize for $parcelable < $($param),* > {
fn serialize(
&self,
parcel: &mut $crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
<Self as $crate::binder_impl::SerializeOption>::serialize_option(Some(self), parcel)
}
}
impl < $($param),* > $crate::binder_impl::SerializeArray for $parcelable < $($param),* > {}
impl < $($param),* > $crate::binder_impl::SerializeOption for $parcelable < $($param),* > {
fn serialize_option(
this: Option<&Self>,
parcel: &mut $crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
if let Some(this) = this {
use $crate::Parcelable;
parcel.write(&$crate::binder_impl::NON_NULL_PARCELABLE_FLAG)?;
this.write_to_parcel(parcel)
} else {
parcel.write(&$crate::binder_impl::NULL_PARCELABLE_FLAG)
}
}
}
};
}
/// Implement `Deserialize` trait and friends for a parcelable
///
/// This is an internal macro used by the AIDL compiler to implement
/// `Deserialize`, `DeserializeArray` and `DeserializeOption` for
/// structured parcelables. The target type must implement the
/// `Parcelable` trait.
#[macro_export]
macro_rules! impl_deserialize_for_parcelable {
($parcelable:ident) => {
$crate::impl_deserialize_for_parcelable!($parcelable < >);
};
($parcelable:ident < $( $param:ident ),* , >) => {
$crate::impl_deserialize_for_parcelable!($parcelable < $($param),* >);
};
($parcelable:ident < $( $param:ident ),* > ) => {
impl < $($param: Default),* > $crate::binder_impl::Deserialize for $parcelable < $($param),* > {
type UninitType = Self;
fn uninit() -> Self::UninitType { Self::UninitType::default() }
fn from_init(value: Self) -> Self::UninitType { value }
fn deserialize(
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<Self, $crate::StatusCode> {
$crate::binder_impl::DeserializeOption::deserialize_option(parcel)
.transpose()
.unwrap_or(Err($crate::StatusCode::UNEXPECTED_NULL))
}
fn deserialize_from(
&mut self,
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
let status: i32 = parcel.read()?;
if status == $crate::binder_impl::NULL_PARCELABLE_FLAG {
Err($crate::StatusCode::UNEXPECTED_NULL)
} else {
use $crate::Parcelable;
self.read_from_parcel(parcel)
}
}
}
impl < $($param: Default),* > $crate::binder_impl::DeserializeArray for $parcelable < $($param),* > {}
impl < $($param: Default),* > $crate::binder_impl::DeserializeOption for $parcelable < $($param),* > {
fn deserialize_option(
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<Option<Self>, $crate::StatusCode> {
let mut result = None;
Self::deserialize_option_from(&mut result, parcel)?;
Ok(result)
}
fn deserialize_option_from(
this: &mut Option<Self>,
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
let status: i32 = parcel.read()?;
if status == $crate::binder_impl::NULL_PARCELABLE_FLAG {
*this = None;
Ok(())
} else {
use $crate::Parcelable;
this.get_or_insert_with(Self::default).read_from_parcel(parcel)
}
}
}
};
}
/// Implements `Serialize` trait and friends for an unstructured parcelable.
///
/// The target type must implement the `UnstructuredParcelable` trait.
#[macro_export]
macro_rules! impl_serialize_for_unstructured_parcelable {
($parcelable:ident) => {
$crate::impl_serialize_for_unstructured_parcelable!($parcelable < >);
};
($parcelable:ident < $( $param:ident ),* , >) => {
$crate::impl_serialize_for_unstructured_parcelable!($parcelable < $($param),* >);
};
($parcelable:ident < $( $param:ident ),* > ) => {
impl < $($param),* > $crate::binder_impl::Serialize for $parcelable < $($param),* > {
fn serialize(
&self,
parcel: &mut $crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
<Self as $crate::binder_impl::SerializeOption>::serialize_option(Some(self), parcel)
}
}
impl < $($param),* > $crate::binder_impl::SerializeArray for $parcelable < $($param),* > {}
impl < $($param),* > $crate::binder_impl::SerializeOption for $parcelable < $($param),* > {
fn serialize_option(
this: Option<&Self>,
parcel: &mut $crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
if let Some(this) = this {
use $crate::binder_impl::UnstructuredParcelable;
parcel.write(&$crate::binder_impl::NON_NULL_PARCELABLE_FLAG)?;
this.write_to_parcel(parcel)
} else {
parcel.write(&$crate::binder_impl::NULL_PARCELABLE_FLAG)
}
}
}
};
}
/// Implement `Deserialize` trait and friends for an unstructured parcelable
///
/// The target type must implement the `UnstructuredParcelable` trait.
#[macro_export]
macro_rules! impl_deserialize_for_unstructured_parcelable {
($parcelable:ident) => {
$crate::impl_deserialize_for_unstructured_parcelable!($parcelable < >);
};
($parcelable:ident < $( $param:ident ),* , >) => {
$crate::impl_deserialize_for_unstructured_parcelable!($parcelable < $($param),* >);
};
($parcelable:ident < $( $param:ident ),* > ) => {
impl < $($param: Default),* > $crate::binder_impl::Deserialize for $parcelable < $($param),* > {
type UninitType = Option<Self>;
fn uninit() -> Self::UninitType { None }
fn from_init(value: Self) -> Self::UninitType { Some(value) }
fn deserialize(
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<Self, $crate::StatusCode> {
$crate::binder_impl::DeserializeOption::deserialize_option(parcel)
.transpose()
.unwrap_or(Err($crate::StatusCode::UNEXPECTED_NULL))
}
fn deserialize_from(
&mut self,
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
let status: i32 = parcel.read()?;
if status == $crate::binder_impl::NULL_PARCELABLE_FLAG {
Err($crate::StatusCode::UNEXPECTED_NULL)
} else {
use $crate::binder_impl::UnstructuredParcelable;
self.read_from_parcel(parcel)
}
}
}
impl < $($param: Default),* > $crate::binder_impl::DeserializeArray for $parcelable < $($param),* > {}
impl < $($param: Default),* > $crate::binder_impl::DeserializeOption for $parcelable < $($param),* > {
fn deserialize_option(
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<Option<Self>, $crate::StatusCode> {
let present: i32 = parcel.read()?;
match present {
$crate::binder_impl::NULL_PARCELABLE_FLAG => Ok(None),
$crate::binder_impl::NON_NULL_PARCELABLE_FLAG => {
use $crate::binder_impl::UnstructuredParcelable;
Ok(Some(Self::from_parcel(parcel)?))
}
_ => Err(StatusCode::BAD_VALUE),
}
}
fn deserialize_option_from(
this: &mut Option<Self>,
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<(), $crate::StatusCode> {
let present: i32 = parcel.read()?;
match present {
$crate::binder_impl::NULL_PARCELABLE_FLAG => {
*this = None;
Ok(())
}
$crate::binder_impl::NON_NULL_PARCELABLE_FLAG => {
use $crate::binder_impl::UnstructuredParcelable;
if let Some(this) = this {
this.read_from_parcel(parcel)?;
} else {
*this = Some(Self::from_parcel(parcel)?);
}
Ok(())
}
_ => Err(StatusCode::BAD_VALUE),
}
}
}
};
}
impl<T: Serialize> Serialize for Box<T> {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
Serialize::serialize(&**self, parcel)
}
}
impl<T: Deserialize> Deserialize for Box<T> {
type UninitType = Option<Self>;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
Some(value)
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Deserialize::deserialize(parcel).map(Box::new)
}
}
impl<T: SerializeOption> SerializeOption for Box<T> {
fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
SerializeOption::serialize_option(this.map(|inner| &**inner), parcel)
}
}
impl<T: DeserializeOption> DeserializeOption for Box<T> {
fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
DeserializeOption::deserialize_option(parcel).map(|t| t.map(Box::new))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parcel::Parcel;
#[test]
fn test_custom_parcelable() {
#[derive(Default)]
struct Custom(u32, bool, String, Vec<String>);
impl Serialize for Custom {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
self.0.serialize(parcel)?;
self.1.serialize(parcel)?;
self.2.serialize(parcel)?;
self.3.serialize(parcel)
}
}
impl Deserialize for Custom {
type UninitType = Self;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
value
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> 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();
let start = parcel.get_data_position();
assert!(custom.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let custom2 = Custom::deserialize(parcel.borrowed_ref()).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() {
let bools = [true, false, false, true];
let mut parcel = Parcel::new();
let start = parcel.get_data_position();
assert!(bools.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
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);
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<bool>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [true, false, false, true]);
let u8s = [101u8, 255, 42, 117];
let mut parcel = Parcel::new();
let start = parcel.get_data_position();
assert!(parcel.write(&u8s[..]).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
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
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<u8>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [101, 255, 42, 117]);
let i8s = [-128i8, 127, 42, -117];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(parcel.write(&i8s[..]).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
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
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<u8>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [-128i8 as u8, 127, 42, -117i8 as u8]);
let u16s = [u16::max_value(), 12_345, 42, 117];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(u16s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
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
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<u16>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [u16::max_value(), 12_345, 42, 117]);
let i16s = [i16::max_value(), i16::min_value(), 42, -117];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(i16s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
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
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<i16>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [i16::max_value(), i16::min_value(), 42, -117]);
let u32s = [u32::max_value(), 12_345, 42, 117];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(u32s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
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
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<u32>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [u32::max_value(), 12_345, 42, 117]);
let i32s = [i32::max_value(), i32::min_value(), 42, -117];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(i32s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
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
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<i32>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [i32::max_value(), i32::min_value(), 42, -117]);
let u64s = [u64::max_value(), 12_345, 42, 117];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(u64s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<u64>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, [u64::max_value(), 12_345, 42, 117]);
let i64s = [i64::max_value(), i64::min_value(), 42, -117];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(i64s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<i64>::deserialize(parcel.borrowed_ref()).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];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(f32s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<f32>::deserialize(parcel.borrowed_ref()).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];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(f64s.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<f64>::deserialize(parcel.borrowed_ref()).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];
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
assert!(strs.serialize(&mut parcel.borrowed()).is_ok());
// SAFETY: start is less than the current size of the parcel data buffer, because we haven't
// made it any shorter since we got the position.
unsafe {
assert!(parcel.set_data_position(start).is_ok());
}
let vec = Vec::<String>::deserialize(parcel.borrowed_ref()).unwrap();
assert_eq!(vec, strs);
}
}