/* * 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; } /// 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::), ) }; 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( 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>> { let mut vec: Option>> = 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::), Some(deserialize_element::), ) }; status_result(res)?; let vec: Option> = 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> to Vec because MaybeUninit 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>>` with at least enough elements for `index` to be valid /// (zero-based). unsafe extern "C" fn deserialize_element( 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>>); 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` // 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> { 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>>`. `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( data: *mut c_void, len: i32, buffer: *mut *mut T, ) -> bool { let res = allocate_vec::(data, len); let vec = &mut *(data as *mut Option>>); 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>>`. unsafe extern "C" fn allocate_vec( data: *mut c_void, len: i32, ) -> bool { let vec = &mut *(data as *mut Option>>); if len < 0 { *vec = None; return true; } let mut new_vec: Vec> = 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 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 { 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>> { let mut vec: Option>> = None; let status = unsafe { // Safety: `Parcel` always contains a valid pointer to an // `AParcel`. `allocate_vec` expects the opaque pointer to // be of type `*mut Option>>`, 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> = 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> to // Vec because MaybeUninit 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>` is interchangeable with // `Option>` (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>` is interchangeable with // `Option>` (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 { 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 { 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 {} impl Deserialize for Option { fn deserialize(parcel: &Parcel) -> Result { let mut vec: Option> = None; let status = unsafe { // Safety: `Parcel` always contains a valid pointer to an `AParcel`. // `Option>` is equivalent to the expected `Option>` // 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 {} impl Deserialize for String { fn deserialize(parcel: &Parcel) -> Result { Deserialize::deserialize(parcel) .transpose() .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) } } impl DeserializeArray for String {} impl Serialize for [T] { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { SerializeArray::serialize_array(self, parcel) } } impl Serialize for Vec { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { SerializeArray::serialize_array(&self[..], parcel) } } impl 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 SerializeOption for Vec { fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { SerializeOption::serialize_option(this.map(Vec::as_slice), parcel) } } impl Deserialize for Vec { fn deserialize(parcel: &Parcel) -> Result { DeserializeArray::deserialize_array(parcel) .transpose() .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) } } impl DeserializeOption for Vec { fn deserialize_option(parcel: &Parcel) -> Result> { 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 { 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 Serialize for Strong { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Serialize::serialize(&**self, parcel) } } impl SerializeOption for Strong { fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { SerializeOption::serialize_option(this.map(|b| &**b), parcel) } } impl Deserialize for Strong { fn deserialize(parcel: &Parcel) -> Result { let ibinder: SpIBinder = parcel.read()?; FromIBinder::try_from(ibinder) } } impl DeserializeOption for Strong { fn deserialize_option(parcel: &Parcel) -> Result> { let ibinder: Option = parcel.read()?; ibinder.map(FromIBinder::try_from).transpose() } } // We need these to support Option<&T> for all T impl Serialize for &T { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Serialize::serialize(*self, parcel) } } impl SerializeOption for &T { fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { SerializeOption::serialize_option(this.copied(), parcel) } } impl Serialize for Option { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { SerializeOption::serialize_option(self.as_ref(), parcel) } } impl Deserialize for Option { fn deserialize(parcel: &Parcel) -> Result { 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); 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 { Ok(Custom( parcel.read()?, parcel.read()?, parcel.read()?, parcel.read::>>()?.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::().unwrap(), 4); assert_eq!(parcel.read::().unwrap(), 1); assert_eq!(parcel.read::().unwrap(), 0); assert_eq!(parcel.read::().unwrap(), 0); assert_eq!(parcel.read::().unwrap(), 1); unsafe { assert!(parcel.set_data_position(start).is_ok()); } let vec = Vec::::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::().unwrap(), 4); // 4 items assert_eq!(parcel.read::().unwrap(), 0x752aff65); // bytes unsafe { assert!(parcel.set_data_position(start).is_ok()); } let vec = Vec::::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::().unwrap(), 4); // 4 items assert_eq!(parcel.read::().unwrap(), 0x8b2a7f80); // bytes unsafe { assert!(parcel.set_data_position(start).is_ok()); } let vec = Vec::::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::().unwrap(), 4); // 4 items assert_eq!(parcel.read::().unwrap(), 0xffff); // u16::max_value() assert_eq!(parcel.read::().unwrap(), 12345); // 12,345 assert_eq!(parcel.read::().unwrap(), 42); // 42 assert_eq!(parcel.read::().unwrap(), 117); // 117 unsafe { assert!(parcel.set_data_position(start).is_ok()); } let vec = Vec::::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::().unwrap(), 4); // 4 items assert_eq!(parcel.read::().unwrap(), 0x7fff); // i16::max_value() assert_eq!(parcel.read::().unwrap(), 0x8000); // i16::min_value() assert_eq!(parcel.read::().unwrap(), 42); // 42 assert_eq!(parcel.read::().unwrap(), 0xff8b); // -117 unsafe { assert!(parcel.set_data_position(start).is_ok()); } let vec = Vec::::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::().unwrap(), 4); // 4 items assert_eq!(parcel.read::().unwrap(), 0xffffffff); // u32::max_value() assert_eq!(parcel.read::().unwrap(), 12345); // 12,345 assert_eq!(parcel.read::().unwrap(), 42); // 42 assert_eq!(parcel.read::().unwrap(), 117); // 117 unsafe { assert!(parcel.set_data_position(start).is_ok()); } let vec = Vec::::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::().unwrap(), 4); // 4 items assert_eq!(parcel.read::().unwrap(), 0x7fffffff); // i32::max_value() assert_eq!(parcel.read::().unwrap(), 0x80000000); // i32::min_value() assert_eq!(parcel.read::().unwrap(), 42); // 42 assert_eq!(parcel.read::().unwrap(), 0xffffff8b); // -117 unsafe { assert!(parcel.set_data_position(start).is_ok()); } let vec = Vec::::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::::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::::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::::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::::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::::deserialize(&parcel).unwrap(); assert_eq!(vec, strs); }