diff options
| author | 2021-11-09 15:35:35 +0000 | |
|---|---|---|
| committer | 2021-11-09 16:04:02 +0000 | |
| commit | 8618c4852f5cfbc7479e8bc68a04f15de0431f0e (patch) | |
| tree | 30af3c0a1427b8c02ad7daec052694eb8bb43924 | |
| parent | e50adf3c1ce709d741b84abfd847b944998fb012 (diff) | |
rust: split Parcel enum into two types
Test: m
Bug: 200676345
Change-Id: I351ea0500035dafe0c8444cbb96074725c1c8630
| -rw-r--r-- | libs/binder/rust/src/binder.rs | 54 | ||||
| -rw-r--r-- | libs/binder/rust/src/lib.rs | 6 | ||||
| -rw-r--r-- | libs/binder/rust/src/native.rs | 16 | ||||
| -rw-r--r-- | libs/binder/rust/src/parcel.rs | 457 | ||||
| -rw-r--r-- | libs/binder/rust/src/parcel/file_descriptor.rs | 10 | ||||
| -rw-r--r-- | libs/binder/rust/src/parcel/parcelable.rs | 609 | ||||
| -rw-r--r-- | libs/binder/rust/src/parcel/parcelable_holder.rs | 20 | ||||
| -rw-r--r-- | libs/binder/rust/src/proxy.rs | 21 | ||||
| -rw-r--r-- | libs/binder/rust/tests/integration.rs | 22 | ||||
| -rw-r--r-- | libs/binder/rust/tests/serialization.rs | 6 |
10 files changed, 684 insertions, 537 deletions
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index 4e048d7c5a..bd2e6954cb 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -17,7 +17,7 @@ //! Trait definitions for binder objects use crate::error::{status_t, Result, StatusCode}; -use crate::parcel::{OwnedParcel, Parcel}; +use crate::parcel::{Parcel, BorrowedParcel}; use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder}; use crate::sys; @@ -129,7 +129,7 @@ pub trait Remotable: Send + Sync { /// Handle and reply to a request to invoke a transaction on this object. /// /// `reply` may be [`None`] if the sender does not expect a reply. - fn on_transact(&self, code: TransactionCode, data: &Parcel, reply: &mut Parcel) -> Result<()>; + fn on_transact(&self, code: TransactionCode, data: &BorrowedParcel<'_>, reply: &mut BorrowedParcel<'_>) -> Result<()>; /// Handle a request to invoke the dump transaction on this /// object. @@ -177,25 +177,25 @@ pub trait IBinderInternal: IBinder { fn get_extension(&mut self) -> Result<Option<SpIBinder>>; /// Create a Parcel that can be used with `submit_transact`. - fn prepare_transact(&self) -> Result<OwnedParcel>; + fn prepare_transact(&self) -> Result<Parcel>; /// Perform a generic operation with the object. /// - /// The provided [`OwnedParcel`] must have been created by a call to + /// The provided [`Parcel`] must have been created by a call to /// `prepare_transact` on the same binder. /// /// # Arguments /// /// * `code` - Transaction code for the operation. - /// * `data` - [`OwnedParcel`] with input data. + /// * `data` - [`Parcel`] with input data. /// * `flags` - Transaction flags, e.g. marking the transaction as /// asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY)). fn submit_transact( &self, code: TransactionCode, - data: OwnedParcel, + data: Parcel, flags: TransactionFlags, - ) -> Result<OwnedParcel>; + ) -> Result<Parcel>; /// Perform a generic operation with the object. This is a convenience /// method that internally calls `prepare_transact` followed by @@ -206,15 +206,15 @@ pub trait IBinderInternal: IBinder { /// * `flags` - Transaction flags, e.g. marking the transaction as /// asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY)) /// * `input_callback` A callback for building the `Parcel`. - fn transact<F: FnOnce(&mut Parcel) -> Result<()>>( + fn transact<F: FnOnce(BorrowedParcel<'_>) -> Result<()>>( &self, code: TransactionCode, flags: TransactionFlags, input_callback: F, ) -> Result<Parcel> { let mut parcel = self.prepare_transact()?; - input_callback(&mut parcel.borrowed())?; - self.submit_transact(code, parcel, flags).map(OwnedParcel::into_parcel) + input_callback(parcel.borrowed())?; + self.submit_transact(code, parcel, flags) } } @@ -475,8 +475,8 @@ impl<I: FromIBinder + ?Sized> Eq for Weak<I> {} /// fn on_transact( /// &self, /// code: TransactionCode, -/// data: &Parcel, -/// reply: &mut Parcel, +/// data: &BorrowedParcel, +/// reply: &mut BorrowedParcel, /// ) -> Result<()> { /// // ... /// } @@ -655,13 +655,13 @@ pub struct BinderFeatures { /// have the following type: /// /// ``` -/// # use binder::{Interface, TransactionCode, Parcel}; +/// # use binder::{Interface, TransactionCode, BorrowedParcel}; /// # trait Placeholder { /// fn on_transact( /// service: &dyn Interface, /// code: TransactionCode, -/// data: &Parcel, -/// reply: &mut Parcel, +/// data: &BorrowedParcel, +/// reply: &mut BorrowedParcel, /// ) -> binder::Result<()>; /// # } /// ``` @@ -676,7 +676,7 @@ pub struct BinderFeatures { /// using the provided function, `on_transact`. /// /// ``` -/// use binder::{declare_binder_interface, Binder, Interface, TransactionCode, Parcel}; +/// use binder::{declare_binder_interface, Binder, Interface, TransactionCode, BorrowedParcel}; /// /// pub trait IServiceManager: Interface { /// // remote methods... @@ -692,8 +692,8 @@ pub struct BinderFeatures { /// fn on_transact( /// service: &dyn IServiceManager, /// code: TransactionCode, -/// data: &Parcel, -/// reply: &mut Parcel, +/// data: &BorrowedParcel, +/// reply: &mut BorrowedParcel, /// ) -> binder::Result<()> { /// // ... /// Ok(()) @@ -847,7 +847,7 @@ macro_rules! declare_binder_interface { $descriptor } - fn on_transact(&self, code: $crate::TransactionCode, data: &$crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> { + fn on_transact(&self, code: $crate::TransactionCode, data: &$crate::BorrowedParcel<'_>, reply: &mut $crate::BorrowedParcel<'_>) -> $crate::Result<()> { match $on_transact(&*self.0, code, data, reply) { // The C++ backend converts UNEXPECTED_NULL into an exception Err($crate::StatusCode::UNEXPECTED_NULL) => { @@ -922,14 +922,14 @@ macro_rules! declare_binder_interface { where dyn $interface: $crate::Interface { - fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { + fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> { let binder = $crate::Interface::as_binder(self); parcel.write(&binder) } } impl $crate::parcel::SerializeOption for dyn $interface + '_ { - fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> { parcel.write(&this.map($crate::Interface::as_binder)) } } @@ -988,14 +988,14 @@ macro_rules! declare_binder_interface { } impl<P: $crate::BinderAsyncPool> $crate::parcel::Serialize for dyn $async_interface<P> + '_ { - fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { + fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> { let binder = $crate::Interface::as_binder(self); parcel.write(&binder) } } impl<P: $crate::BinderAsyncPool> $crate::parcel::SerializeOption for dyn $async_interface<P> + '_ { - fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> { parcel.write(&this.map($crate::Interface::as_binder)) } } @@ -1040,26 +1040,26 @@ macro_rules! declare_binder_enum { } impl $crate::parcel::Serialize for $enum { - fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { + fn serialize(&self, parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> { parcel.write(&self.0) } } impl $crate::parcel::SerializeArray for $enum { - fn serialize_array(slice: &[Self], parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { + fn serialize_array(slice: &[Self], parcel: &mut $crate::parcel::BorrowedParcel<'_>) -> $crate::Result<()> { let v: Vec<$backing> = slice.iter().map(|x| x.0).collect(); <$backing as binder::parcel::SerializeArray>::serialize_array(&v[..], parcel) } } impl $crate::parcel::Deserialize for $enum { - fn deserialize(parcel: &$crate::parcel::Parcel) -> $crate::Result<Self> { + fn deserialize(parcel: &$crate::parcel::BorrowedParcel<'_>) -> $crate::Result<Self> { parcel.read().map(Self) } } impl $crate::parcel::DeserializeArray for $enum { - fn deserialize_array(parcel: &$crate::parcel::Parcel) -> $crate::Result<Option<Vec<Self>>> { + fn deserialize_array(parcel: &$crate::parcel::BorrowedParcel<'_>) -> $crate::Result<Option<Vec<Self>>> { let v: Option<Vec<$backing>> = <$backing as binder::parcel::DeserializeArray>::deserialize_array(parcel)?; Ok(v.map(|v| v.into_iter().map(Self).collect())) diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 2ac2d2f0bc..cce55c0188 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -50,8 +50,8 @@ //! fn on_transact( //! service: &dyn ITest, //! code: TransactionCode, -//! _data: &Parcel, -//! reply: &mut Parcel, +//! _data: &BorrowedParcel, +//! reply: &mut BorrowedParcel, //! ) -> binder::Result<()> { //! match code { //! SpIBinder::FIRST_CALL_TRANSACTION => { @@ -115,7 +115,7 @@ pub use crate::binder::{ pub use crate::binder_async::{BoxFuture, BinderAsyncPool}; pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder}; -pub use parcel::{OwnedParcel, Parcel}; +pub use parcel::{BorrowedParcel, Parcel}; pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service}; pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder}; pub use state::{ProcessState, ThreadState}; diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs index a91092e2d4..f5d7187f4a 100644 --- a/libs/binder/rust/src/native.rs +++ b/libs/binder/rust/src/native.rs @@ -18,7 +18,7 @@ use crate::binder::{ AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode, }; use crate::error::{status_result, status_t, Result, StatusCode}; -use crate::parcel::{Parcel, Serialize}; +use crate::parcel::{BorrowedParcel, Serialize}; use crate::proxy::SpIBinder; use crate::sys; @@ -161,8 +161,8 @@ impl<T: Remotable> Binder<T> { /// # fn on_transact( /// # service: &dyn IBar, /// # code: TransactionCode, - /// # data: &Parcel, - /// # reply: &mut Parcel, + /// # data: &BorrowedParcel, + /// # reply: &mut BorrowedParcel, /// # ) -> binder::Result<()> { /// # Ok(()) /// # } @@ -277,8 +277,8 @@ impl<T: Remotable> InterfaceClassMethods for Binder<T> { reply: *mut sys::AParcel, ) -> status_t { let res = { - let mut reply = Parcel::borrowed(reply).unwrap(); - let data = Parcel::borrowed(data as *mut sys::AParcel).unwrap(); + let mut reply = BorrowedParcel::from_raw(reply).unwrap(); + let data = BorrowedParcel::from_raw(data as *mut sys::AParcel).unwrap(); let object = sys::AIBinder_getUserData(binder); let binder: &T = &*(object as *const T); binder.on_transact(code, &data, &mut reply) @@ -384,7 +384,7 @@ impl<T: Remotable> Deref for Binder<T> { } impl<B: Remotable> Serialize for Binder<B> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { parcel.write_binder(Some(&self.as_binder())) } } @@ -503,8 +503,8 @@ impl Remotable for () { fn on_transact( &self, _code: TransactionCode, - _data: &Parcel, - _reply: &mut Parcel, + _data: &BorrowedParcel<'_>, + _reply: &mut BorrowedParcel<'_>, ) -> Result<()> { Ok(()) } diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs index a0e147860d..206b90c807 100644 --- a/libs/binder/rust/src/parcel.rs +++ b/libs/binder/rust/src/parcel.rs @@ -21,11 +21,10 @@ use crate::error::{status_result, Result, StatusCode}; use crate::proxy::SpIBinder; use crate::sys; -use std::cell::RefCell; use std::convert::TryInto; use std::marker::PhantomData; use std::mem::ManuallyDrop; -use std::ptr; +use std::ptr::{self, NonNull}; use std::fmt; mod file_descriptor; @@ -46,53 +45,41 @@ pub use self::parcelable_holder::{ParcelableHolder, ParcelableMetadata}; /// other side of the IPC, and references to live Binder objects that will /// result in the other side receiving a proxy Binder connected with the /// original Binder in the Parcel. -pub enum Parcel { - /// Owned parcel pointer - Owned(*mut sys::AParcel), - /// Borrowed parcel pointer (will not be destroyed on drop) - Borrowed(*mut sys::AParcel), -} - -/// A variant of Parcel that is known to be owned. -pub struct OwnedParcel { - ptr: *mut sys::AParcel, +/// +/// This type represents a parcel that is owned by Rust code. +#[repr(transparent)] +pub struct Parcel { + ptr: NonNull<sys::AParcel>, } /// # Safety /// /// This type guarantees that it owns the AParcel and that all access to -/// the AParcel happens through the OwnedParcel, so it is ok to send across +/// the AParcel happens through the Parcel, so it is ok to send across /// threads. -unsafe impl Send for OwnedParcel {} +unsafe impl Send for Parcel {} -/// A variant of Parcel that is known to be borrowed. +/// Container for a message (data and object references) that can be sent +/// through Binder. +/// +/// This object is a borrowed variant of [`Parcel`]. It is a separate type from +/// `&mut Parcel` because it is not valid to `mem::swap` two parcels. +#[repr(transparent)] pub struct BorrowedParcel<'a> { - inner: Parcel, + ptr: NonNull<sys::AParcel>, _lifetime: PhantomData<&'a mut Parcel>, } -impl OwnedParcel { - /// Create a new empty `OwnedParcel`. - pub fn new() -> OwnedParcel { +impl Parcel { + /// Create a new empty `Parcel`. + pub fn new() -> Parcel { let ptr = unsafe { // Safety: If `AParcel_create` succeeds, it always returns // a valid pointer. If it fails, the process will crash. sys::AParcel_create() }; - assert!(!ptr.is_null()); - Self { ptr } - } - - /// Convert the provided parcel to an owned parcel, or return `None` if it - /// is borrowed. - pub fn try_from(parcel: Parcel) -> Option<OwnedParcel> { - match &parcel { - Parcel::Owned(ptr) => { - let ptr = *ptr; - std::mem::forget(parcel); - Some(OwnedParcel { ptr }) - } - Parcel::Borrowed(_) => None, + Self { + ptr: NonNull::new(ptr).expect("AParcel_create returned null pointer") } } @@ -107,62 +94,93 @@ impl OwnedParcel { /// /// Additionally, the caller must guarantee that it is valid to take /// ownership of the AParcel object. All future access to the AParcel - /// must happen through this `OwnedParcel`. + /// must happen through this `Parcel`. /// - /// Because `OwnedParcel` implements `Send`, the pointer must never point - /// to any thread-local data, e.g., a variable on the stack, either directly - /// or indirectly. - pub unsafe fn from_raw(ptr: *mut sys::AParcel) -> Option<OwnedParcel> { - ptr.as_mut().map(|ptr| Self { ptr }) + /// Because `Parcel` implements `Send`, the pointer must never point to any + /// thread-local data, e.g., a variable on the stack, either directly or + /// indirectly. + pub unsafe fn from_raw(ptr: *mut sys::AParcel) -> Option<Parcel> { + NonNull::new(ptr).map(|ptr| Self { ptr }) } /// Consume the parcel, transferring ownership to the caller. pub(crate) fn into_raw(self) -> *mut sys::AParcel { - let ptr = self.ptr; + let ptr = self.ptr.as_ptr(); let _ = ManuallyDrop::new(self); ptr } - /// Convert this `OwnedParcel` into an owned `Parcel`. - pub fn into_parcel(self) -> Parcel { - Parcel::Owned(self.into_raw()) - } - /// Get a borrowed view into the contents of this `Parcel`. pub fn borrowed(&mut self) -> BorrowedParcel<'_> { + // Safety: The raw pointer is a valid pointer to an AParcel, and the + // lifetime of the returned `BorrowedParcel` is tied to `self`, so the + // borrow checker will ensure that the `AParcel` can only be accessed + // via the `BorrowParcel` until it goes out of scope. BorrowedParcel { - inner: Parcel::Borrowed(self.ptr), + ptr: self.ptr, _lifetime: PhantomData, } } + + /// Get an immutable borrowed view into the contents of this `Parcel`. + pub fn borrowed_ref(&self) -> &BorrowedParcel<'_> { + // Safety: Parcel and BorrowedParcel are both represented in the same + // way as a NonNull<sys::AParcel> due to their use of repr(transparent), + // so casting references as done here is valid. + unsafe { + &*(self as *const Parcel as *const BorrowedParcel<'_>) + } + } } -impl Default for OwnedParcel { +impl Default for Parcel { fn default() -> Self { Self::new() } } -impl Clone for OwnedParcel { +impl Clone for Parcel { fn clone(&self) -> Self { let mut new_parcel = Self::new(); new_parcel .borrowed() - .append_all_from(&Parcel::Borrowed(self.ptr)) + .append_all_from(self.borrowed_ref()) .expect("Failed to append from Parcel"); new_parcel } } -impl<'a> std::ops::Deref for BorrowedParcel<'a> { - type Target = Parcel; - fn deref(&self) -> &Parcel { - &self.inner +impl<'a> BorrowedParcel<'a> { + /// Create a borrowed reference to a parcel object from a raw pointer. + /// + /// # Safety + /// + /// This constructor is safe if the raw pointer parameter is either null + /// (resulting in `None`), or a valid pointer to an `AParcel` object. + /// + /// Since the raw pointer is not restricted by any lifetime, the lifetime on + /// the returned `BorrowedParcel` object can be chosen arbitrarily by the + /// caller. The caller must ensure it is valid to mutably borrow the AParcel + /// for the duration of the lifetime that the caller chooses. Note that + /// since this is a mutable borrow, it must have exclusive access to the + /// AParcel for the duration of the borrow. + pub unsafe fn from_raw(ptr: *mut sys::AParcel) -> Option<BorrowedParcel<'a>> { + Some(Self { + ptr: NonNull::new(ptr)?, + _lifetime: PhantomData, + }) } -} -impl<'a> std::ops::DerefMut for BorrowedParcel<'a> { - fn deref_mut(&mut self) -> &mut Parcel { - &mut self.inner + + /// Get a sub-reference to this reference to the parcel. + pub fn reborrow(&mut self) -> BorrowedParcel<'_> { + // Safety: The raw pointer is a valid pointer to an AParcel, and the + // lifetime of the returned `BorrowedParcel` is tied to `self`, so the + // borrow checker will ensure that the `AParcel` can only be accessed + // via the `BorrowParcel` until it goes out of scope. + BorrowedParcel { + ptr: self.ptr, + _lifetime: PhantomData, + } } } @@ -172,63 +190,30 @@ impl<'a> std::ops::DerefMut for BorrowedParcel<'a> { /// contain a valid pointer to an `AParcel`. unsafe impl AsNative<sys::AParcel> for Parcel { fn as_native(&self) -> *const sys::AParcel { - match *self { - Self::Owned(x) | Self::Borrowed(x) => x, - } + self.ptr.as_ptr() } fn as_native_mut(&mut self) -> *mut sys::AParcel { - match *self { - Self::Owned(x) | Self::Borrowed(x) => x, - } - } -} - -impl Parcel { - /// Create a new empty `Parcel`. - /// - /// Creates a new owned empty parcel that can be written to - /// using the serialization methods and appended to and - /// from using `append_from` and `append_from_all`. - pub fn new() -> Parcel { - let parcel = unsafe { - // Safety: If `AParcel_create` succeeds, it always returns - // a valid pointer. If it fails, the process will crash. - sys::AParcel_create() - }; - assert!(!parcel.is_null()); - Self::Owned(parcel) - } - - /// Create a borrowed reference to a parcel object from a raw pointer. - /// - /// # Safety - /// - /// This constructor is safe if the raw pointer parameter is either null - /// (resulting in `None`), or a valid pointer to an `AParcel` object. - pub(crate) unsafe fn borrowed(ptr: *mut sys::AParcel) -> Option<Parcel> { - ptr.as_mut().map(|ptr| Self::Borrowed(ptr)) + self.ptr.as_ptr() } } -impl Default for Parcel { - fn default() -> Self { - Self::new() +/// # Safety +/// +/// The `BorrowedParcel` constructors guarantee that a `BorrowedParcel` object +/// will always contain a valid pointer to an `AParcel`. +unsafe impl<'a> AsNative<sys::AParcel> for BorrowedParcel<'a> { + fn as_native(&self) -> *const sys::AParcel { + self.ptr.as_ptr() } -} -impl Clone for Parcel { - fn clone(&self) -> Self { - let mut new_parcel = Self::new(); - new_parcel - .append_all_from(self) - .expect("Failed to append from Parcel"); - new_parcel + fn as_native_mut(&mut self) -> *mut sys::AParcel { + self.ptr.as_ptr() } } // Data serialization methods -impl Parcel { +impl<'a> BorrowedParcel<'a> { /// Data written to parcelable is zero'd before being deleted or reallocated. pub fn mark_sensitive(&mut self) { unsafe { @@ -237,12 +222,12 @@ impl Parcel { } } - /// Write a type that implements [`Serialize`] to the `Parcel`. + /// Write a type that implements [`Serialize`] to the parcel. pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> { parcelable.serialize(self) } - /// Writes the length of a slice to the `Parcel`. + /// Writes the length of a slice to the parcel. /// /// This is used in AIDL-generated client side code to indicate the /// allocated space for an output array parameter. @@ -255,7 +240,7 @@ impl Parcel { } } - /// Perform a series of writes to the `Parcel`, prepended with the length + /// Perform a series of writes to the parcel, prepended with the length /// (in bytes) of the written data. /// /// The length `0i32` will be written to the parcel first, followed by the @@ -269,7 +254,7 @@ impl Parcel { /// /// ``` /// # use binder::{Binder, Interface, Parcel}; - /// # let mut parcel = Parcel::Owned(std::ptr::null_mut()); + /// # let mut parcel = Parcel::new(); /// parcel.sized_write(|subparcel| { /// subparcel.write(&1u32)?; /// subparcel.write(&2u32)?; @@ -283,14 +268,14 @@ impl Parcel { /// [16i32, 1u32, 2u32, 3u32] /// ``` pub fn sized_write<F>(&mut self, f: F) -> Result<()> - where for<'a> - F: Fn(&'a WritableSubParcel<'a>) -> Result<()> + where + for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()> { let start = self.get_data_position(); self.write(&0i32)?; { - let subparcel = WritableSubParcel(RefCell::new(self)); - f(&subparcel)?; + let mut subparcel = WritableSubParcel(self.reborrow()); + f(&mut subparcel)?; } let end = self.get_data_position(); unsafe { @@ -307,8 +292,8 @@ impl Parcel { /// Returns the current position in the parcel data. pub fn get_data_position(&self) -> i32 { unsafe { - // Safety: `Parcel` always contains a valid pointer to an `AParcel`, - // and this call is otherwise safe. + // Safety: `BorrowedParcel` always contains a valid pointer to an + // `AParcel`, and this call is otherwise safe. sys::AParcel_getDataPosition(self.as_native()) } } @@ -316,8 +301,8 @@ impl Parcel { /// Returns the total size of the parcel. pub fn get_data_size(&self) -> i32 { unsafe { - // Safety: `Parcel` always contains a valid pointer to an `AParcel`, - // and this call is otherwise safe. + // Safety: `BorrowedParcel` always contains a valid pointer to an + // `AParcel`, and this call is otherwise safe. sys::AParcel_getDataSize(self.as_native()) } } @@ -335,11 +320,11 @@ impl Parcel { status_result(sys::AParcel_setDataPosition(self.as_native(), pos)) } - /// Append a subset of another `Parcel`. + /// Append a subset of another parcel. /// /// This appends `size` bytes of data from `other` starting at offset - /// `start` to the current `Parcel`, or returns an error if not possible. - pub fn append_from(&mut self, other: &Self, start: i32, size: i32) -> Result<()> { + /// `start` to the current parcel, or returns an error if not possible. + pub fn append_from(&mut self, other: &impl AsNative<sys::AParcel>, start: i32, size: i32) -> Result<()> { let status = unsafe { // Safety: `Parcel::appendFrom` from C++ checks that `start` // and `size` are in bounds, and returns an error otherwise. @@ -354,33 +339,125 @@ impl Parcel { status_result(status) } - /// Append the contents of another `Parcel`. - pub fn append_all_from(&mut self, other: &Self) -> Result<()> { - self.append_from(other, 0, other.get_data_size()) + /// Append the contents of another parcel. + pub fn append_all_from(&mut self, other: &impl AsNative<sys::AParcel>) -> Result<()> { + // Safety: `BorrowedParcel` always contains a valid pointer to an + // `AParcel`, and this call is otherwise safe. + let size = unsafe { sys::AParcel_getDataSize(other.as_native()) }; + self.append_from(other, 0, size) } } -/// A segment of a writable parcel, used for [`Parcel::sized_write`]. -pub struct WritableSubParcel<'a>(RefCell<&'a mut Parcel>); +/// A segment of a writable parcel, used for [`BorrowedParcel::sized_write`]. +pub struct WritableSubParcel<'a>(BorrowedParcel<'a>); impl<'a> WritableSubParcel<'a> { /// Write a type that implements [`Serialize`] to the sub-parcel. - pub fn write<S: Serialize + ?Sized>(&self, parcelable: &S) -> Result<()> { - parcelable.serialize(&mut *self.0.borrow_mut()) + pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> { + parcelable.serialize(&mut self.0) } } -// Data deserialization methods impl Parcel { - /// Attempt to read a type that implements [`Deserialize`] from this - /// `Parcel`. + /// Data written to parcelable is zero'd before being deleted or reallocated. + pub fn mark_sensitive(&mut self) { + self.borrowed().mark_sensitive() + } + + /// Write a type that implements [`Serialize`] to the parcel. + pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> { + self.borrowed().write(parcelable) + } + + /// Writes the length of a slice to the parcel. + /// + /// This is used in AIDL-generated client side code to indicate the + /// allocated space for an output array parameter. + pub fn write_slice_size<T>(&mut self, slice: Option<&[T]>) -> Result<()> { + self.borrowed().write_slice_size(slice) + } + + /// Perform a series of writes to the parcel, prepended with the length + /// (in bytes) of the written data. + /// + /// The length `0i32` will be written to the parcel first, followed by the + /// writes performed by the callback. The initial length will then be + /// updated to the length of all data written by the callback, plus the + /// size of the length elemement itself (4 bytes). + /// + /// # Examples + /// + /// After the following call: + /// + /// ``` + /// # use binder::{Binder, Interface, Parcel}; + /// # let mut parcel = Parcel::new(); + /// parcel.sized_write(|subparcel| { + /// subparcel.write(&1u32)?; + /// subparcel.write(&2u32)?; + /// subparcel.write(&3u32) + /// }); + /// ``` + /// + /// `parcel` will contain the following: + /// + /// ```ignore + /// [16i32, 1u32, 2u32, 3u32] + /// ``` + pub fn sized_write<F>(&mut self, f: F) -> Result<()> + where + for<'b> F: FnOnce(&'b mut WritableSubParcel<'b>) -> Result<()> + { + self.borrowed().sized_write(f) + } + + /// Returns the current position in the parcel data. + pub fn get_data_position(&self) -> i32 { + self.borrowed_ref().get_data_position() + } + + /// Returns the total size of the parcel. + pub fn get_data_size(&self) -> i32 { + self.borrowed_ref().get_data_size() + } + + /// Move the current read/write position in the parcel. + /// + /// # Safety + /// + /// This method is safe if `pos` is less than the current size of the parcel + /// data buffer. Otherwise, we are relying on correct bounds checking in the + /// Parcel C++ code on every subsequent read or write to this parcel. If all + /// accesses are bounds checked, this call is still safe, but we can't rely + /// on that. + pub unsafe fn set_data_position(&self, pos: i32) -> Result<()> { + self.borrowed_ref().set_data_position(pos) + } + + /// Append a subset of another parcel. + /// + /// This appends `size` bytes of data from `other` starting at offset + /// `start` to the current parcel, or returns an error if not possible. + pub fn append_from(&mut self, other: &impl AsNative<sys::AParcel>, start: i32, size: i32) -> Result<()> { + self.borrowed().append_from(other, start, size) + } + + /// Append the contents of another parcel. + pub fn append_all_from(&mut self, other: &impl AsNative<sys::AParcel>) -> Result<()> { + self.borrowed().append_all_from(other) + } +} + +// Data deserialization methods +impl<'a> BorrowedParcel<'a> { + /// Attempt to read a type that implements [`Deserialize`] from this parcel. pub fn read<D: Deserialize>(&self) -> Result<D> { D::deserialize(self) } - /// Attempt to read a type that implements [`Deserialize`] from this - /// `Parcel` onto an existing value. This operation will overwrite the old - /// value partially or completely, depending on how much data is available. + /// Attempt to read a type that implements [`Deserialize`] from this parcel + /// onto an existing value. This operation will overwrite the old value + /// partially or completely, depending on how much data is available. pub fn read_onto<D: Deserialize>(&self, x: &mut D) -> Result<()> { x.deserialize_from(self) } @@ -413,9 +490,9 @@ impl Parcel { /// }); /// ``` /// - pub fn sized_read<F>(&self, mut f: F) -> Result<()> + pub fn sized_read<F>(&self, f: F) -> Result<()> where - for<'a> F: FnMut(ReadableSubParcel<'a>) -> Result<()> + for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()> { let start = self.get_data_position(); let parcelable_size: i32 = self.read()?; @@ -430,7 +507,10 @@ impl Parcel { } let subparcel = ReadableSubParcel { - parcel: self, + parcel: BorrowedParcel { + ptr: self.ptr, + _lifetime: PhantomData, + }, end_position: end, }; f(subparcel)?; @@ -444,8 +524,8 @@ impl Parcel { Ok(()) } - /// Read a vector size from the `Parcel` and resize the given output vector - /// to be correctly sized for that amount of data. + /// Read a vector size from the parcel and resize the given output vector to + /// be correctly sized for that amount of data. /// /// This method is used in AIDL-generated server side code for methods that /// take a mutable slice reference parameter. @@ -463,7 +543,7 @@ impl Parcel { Ok(()) } - /// Read a vector size from the `Parcel` and either create a correctly sized + /// Read a vector size from the parcel and either create a correctly sized /// vector for that amount of data or set the output parameter to None if /// the vector should be null. /// @@ -491,7 +571,7 @@ impl Parcel { /// A segment of a readable parcel, used for [`Parcel::sized_read`]. pub struct ReadableSubParcel<'a> { - parcel: &'a Parcel, + parcel: BorrowedParcel<'a>, end_position: i32, } @@ -501,7 +581,7 @@ impl<'a> ReadableSubParcel<'a> { // The caller should have checked this, // but it can't hurt to double-check assert!(self.has_more_data()); - D::deserialize(self.parcel) + D::deserialize(&self.parcel) } /// Check if the sub-parcel has more data to read @@ -510,11 +590,82 @@ impl<'a> ReadableSubParcel<'a> { } } -// Internal APIs impl Parcel { + /// Attempt to read a type that implements [`Deserialize`] from this parcel. + pub fn read<D: Deserialize>(&self) -> Result<D> { + self.borrowed_ref().read() + } + + /// Attempt to read a type that implements [`Deserialize`] from this parcel + /// onto an existing value. This operation will overwrite the old value + /// partially or completely, depending on how much data is available. + pub fn read_onto<D: Deserialize>(&self, x: &mut D) -> Result<()> { + self.borrowed_ref().read_onto(x) + } + + /// Safely read a sized parcelable. + /// + /// Read the size of a parcelable, compute the end position + /// of that parcelable, then build a sized readable sub-parcel + /// and call a closure with the sub-parcel as its parameter. + /// The closure can keep reading data from the sub-parcel + /// until it runs out of input data. The closure is responsible + /// for calling [`ReadableSubParcel::has_more_data`] to check for + /// more data before every read, at least until Rust generators + /// are stabilized. + /// After the closure returns, skip to the end of the current + /// parcelable regardless of how much the closure has read. + /// + /// # Examples + /// + /// ```no_run + /// let mut parcelable = Default::default(); + /// parcel.sized_read(|subparcel| { + /// if subparcel.has_more_data() { + /// parcelable.a = subparcel.read()?; + /// } + /// if subparcel.has_more_data() { + /// parcelable.b = subparcel.read()?; + /// } + /// Ok(()) + /// }); + /// ``` + /// + pub fn sized_read<F>(&self, f: F) -> Result<()> + where + for<'b> F: FnOnce(ReadableSubParcel<'b>) -> Result<()> + { + self.borrowed_ref().sized_read(f) + } + + /// Read a vector size from the parcel and resize the given output vector to + /// be correctly sized for that amount of data. + /// + /// This method is used in AIDL-generated server side code for methods that + /// take a mutable slice reference parameter. + pub fn resize_out_vec<D: Default + Deserialize>(&self, out_vec: &mut Vec<D>) -> Result<()> { + self.borrowed_ref().resize_out_vec(out_vec) + } + + /// Read a vector size from the parcel and either create a correctly sized + /// vector for that amount of data or set the output parameter to None if + /// the vector should be null. + /// + /// This method is used in AIDL-generated server side code for methods that + /// take a mutable slice reference parameter. + pub fn resize_nullable_out_vec<D: Default + Deserialize>( + &self, + out_vec: &mut Option<Vec<D>>, + ) -> Result<()> { + self.borrowed_ref().resize_nullable_out_vec(out_vec) + } +} + +// Internal APIs +impl<'a> BorrowedParcel<'a> { pub(crate) fn write_binder(&mut self, binder: Option<&SpIBinder>) -> Result<()> { unsafe { - // Safety: `Parcel` always contains a valid pointer to an + // Safety: `BorrowedParcel` always contains a valid pointer to an // `AParcel`. `AsNative` for `Option<SpIBinder`> will either return // null or a valid pointer to an `AIBinder`, both of which are // valid, safe inputs to `AParcel_writeStrongBinder`. @@ -534,7 +685,7 @@ impl Parcel { pub(crate) fn read_binder(&self) -> Result<Option<SpIBinder>> { let mut binder = ptr::null_mut(); let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an + // Safety: `BorrowedParcel` always contains a valid pointer to an // `AParcel`. We pass a valid, mutable out pointer to the `binder` // parameter. After this call, `binder` will be either null or a // valid pointer to an `AIBinder` owned by the caller. @@ -554,25 +705,11 @@ impl Parcel { impl Drop for Parcel { fn drop(&mut self) { // Run the C++ Parcel complete object destructor - if let Self::Owned(ptr) = *self { - unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. If we own the parcel, we can safely delete it - // here. - sys::AParcel_delete(ptr) - } - } - } -} - -impl Drop for OwnedParcel { - fn drop(&mut self) { - // Run the C++ Parcel complete object destructor unsafe { - // Safety: `OwnedParcel` always contains a valid pointer to an + // Safety: `Parcel` always contains a valid pointer to an // `AParcel`. Since we own the parcel, we can safely delete it // here. - sys::AParcel_delete(self.ptr) + sys::AParcel_delete(self.ptr.as_ptr()) } } } @@ -584,9 +721,9 @@ impl fmt::Debug for Parcel { } } -impl fmt::Debug for OwnedParcel { +impl<'a> fmt::Debug for BorrowedParcel<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OwnedParcel") + f.debug_struct("BorrowedParcel") .finish() } } @@ -608,7 +745,7 @@ fn test_read_write() { assert_eq!(parcel.read::<Option<String>>(), Ok(None)); assert_eq!(parcel.read::<String>(), Err(StatusCode::UNEXPECTED_NULL)); - assert_eq!(parcel.read_binder().err(), Some(StatusCode::BAD_TYPE)); + assert_eq!(parcel.borrowed_ref().read_binder().err(), Some(StatusCode::BAD_TYPE)); parcel.write(&1i32).unwrap(); diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs index 8bcc5d0092..b0dea945e0 100644 --- a/libs/binder/rust/src/parcel/file_descriptor.rs +++ b/libs/binder/rust/src/parcel/file_descriptor.rs @@ -15,7 +15,7 @@ */ use super::{ - Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray, + Deserialize, DeserializeArray, DeserializeOption, BorrowedParcel, Serialize, SerializeArray, SerializeOption, }; use crate::binder::AsNative; @@ -61,7 +61,7 @@ impl IntoRawFd for ParcelFileDescriptor { } impl Serialize for ParcelFileDescriptor { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { let fd = self.0.as_raw_fd(); let status = unsafe { // Safety: `Parcel` always contains a valid pointer to an @@ -78,7 +78,7 @@ impl Serialize for ParcelFileDescriptor { impl SerializeArray for ParcelFileDescriptor {} impl SerializeOption for ParcelFileDescriptor { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> { if let Some(f) = this { f.serialize(parcel) } else { @@ -95,7 +95,7 @@ impl SerializeOption for ParcelFileDescriptor { } impl DeserializeOption for ParcelFileDescriptor { - fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { + fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> { let mut fd = -1i32; unsafe { // Safety: `Parcel` always contains a valid pointer to an @@ -125,7 +125,7 @@ impl DeserializeOption for ParcelFileDescriptor { } impl Deserialize for ParcelFileDescriptor { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { Deserialize::deserialize(parcel) .transpose() .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs index db9d8b0011..9007cbafc2 100644 --- a/libs/binder/rust/src/parcel/parcelable.rs +++ b/libs/binder/rust/src/parcel/parcelable.rs @@ -16,14 +16,14 @@ use crate::binder::{AsNative, FromIBinder, Stability, Strong}; use crate::error::{status_result, status_t, Result, Status, StatusCode}; -use crate::parcel::Parcel; +use crate::parcel::BorrowedParcel; use crate::proxy::SpIBinder; use crate::sys; use std::convert::{TryFrom, TryInto}; use std::ffi::c_void; use std::os::raw::{c_char, c_ulong}; -use std::mem::{self, MaybeUninit}; +use std::mem::{self, MaybeUninit, ManuallyDrop}; use std::ptr; use std::slice; @@ -39,7 +39,7 @@ pub trait Parcelable { /// `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 Parcel) -> Result<()>; + fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>; /// Internal deserialization function for parcelables. /// @@ -47,26 +47,26 @@ pub trait Parcelable { /// `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: &Parcel) -> Result<()>; + fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()>; } /// 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<()>; + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> 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>; + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self>; /// Deserialize an instance from the given [`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: &Parcel) -> Result<()> { + fn deserialize_from(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> { *self = Self::deserialize(parcel)?; Ok(()) } @@ -80,8 +80,8 @@ pub trait Deserialize: Sized { // 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<()> { + /// Serialize an array of this type into the given parcel. + fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> { let res = unsafe { // Safety: Safe FFI, slice will always be a safe pointer to pass. sys::AParcel_writeParcelableArray( @@ -111,7 +111,7 @@ unsafe extern "C" fn serialize_element<T: Serialize>( let slice: &[T] = slice::from_raw_parts(array.cast(), index+1); - let mut parcel = match Parcel::borrowed(parcel) { + let mut parcel = match BorrowedParcel::from_raw(parcel) { None => return StatusCode::UNEXPECTED_NULL as status_t, Some(p) => p, }; @@ -126,8 +126,8 @@ unsafe extern "C" fn serialize_element<T: Serialize>( /// 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>>> { + /// Deserialize an array of type from the given parcel. + fn deserialize_array(parcel: &BorrowedParcel<'_>) -> 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 @@ -173,7 +173,7 @@ unsafe extern "C" fn deserialize_element<T: Deserialize>( None => return StatusCode::BAD_INDEX as status_t, }; - let parcel = match Parcel::borrowed(parcel as *mut _) { + let parcel = match BorrowedParcel::from_raw(parcel as *mut _) { None => return StatusCode::UNEXPECTED_NULL as status_t, Some(p) => p, }; @@ -205,8 +205,8 @@ pub const NULL_PARCELABLE_FLAG: i32 = 0; // 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<()> { + /// 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) @@ -218,8 +218,8 @@ pub trait SerializeOption: Serialize { /// 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>> { + /// 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) @@ -228,10 +228,10 @@ pub trait DeserializeOption: Deserialize { } } - /// Deserialize an Option of this type from the given [`Parcel`] onto the + /// 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: &Parcel) -> Result<()> { + fn deserialize_option_from(this: &mut Option<Self>, parcel: &BorrowedParcel<'_>) -> Result<()> { *this = Self::deserialize_option(parcel)?; Ok(()) } @@ -297,10 +297,23 @@ macro_rules! parcelable_primitives { }; } +/// Safety: All elements in the vector must be properly initialized. +unsafe fn vec_assume_init<T>(vec: Vec<MaybeUninit<T>>) -> Vec<T> { + // We can convert 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. + let mut vec = ManuallyDrop::new(vec); + 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 Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { unsafe { // Safety: `Parcel` always contains a valid pointer to an // `AParcel`, and any `$ty` literal value is safe to pass to @@ -313,7 +326,7 @@ macro_rules! impl_parcelable { {Deserialize, $ty:ty, $read_fn:path} => { impl Deserialize for $ty { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { let mut val = Self::default(); unsafe { // Safety: `Parcel` always contains a valid pointer to an @@ -329,7 +342,7 @@ macro_rules! impl_parcelable { {SerializeArray, $ty:ty, $write_array_fn:path} => { impl SerializeArray for $ty { - fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> { + fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> Result<()> { let status = unsafe { // Safety: `Parcel` always contains a valid pointer to an // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` @@ -353,7 +366,7 @@ macro_rules! impl_parcelable { {DeserializeArray, $ty:ty, $read_array_fn:path} => { impl DeserializeArray for $ty { - fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> { + fn deserialize_array(parcel: &BorrowedParcel<'_>) -> Result<Option<Vec<Self>>> { let mut vec: Option<Vec<MaybeUninit<Self>>> = None; let status = unsafe { // Safety: `Parcel` always contains a valid pointer to an @@ -371,11 +384,8 @@ macro_rules! impl_parcelable { // 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) + // initialized. + vec.map(|vec| vec_assume_init(vec)) }; Ok(vec) } @@ -443,19 +453,19 @@ impl SerializeArray for bool {} impl DeserializeArray for bool {} impl Serialize for u8 { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { (*self as i8).serialize(parcel) } } impl Deserialize for u8 { - fn deserialize(parcel: &Parcel) -> Result<Self> { + 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 Parcel) -> Result<()> { + fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> 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 @@ -474,19 +484,19 @@ impl SerializeArray for u8 { } impl Serialize for i16 { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { (*self as u16).serialize(parcel) } } impl Deserialize for i16 { - fn deserialize(parcel: &Parcel) -> Result<Self> { + 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 Parcel) -> Result<()> { + fn serialize_array(slice: &[Self], parcel: &mut BorrowedParcel<'_>) -> 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 @@ -505,7 +515,7 @@ impl SerializeArray for i16 { } impl SerializeOption for str { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> { match this { None => unsafe { // Safety: `Parcel` always contains a valid pointer to an @@ -541,7 +551,7 @@ impl SerializeOption for str { } impl Serialize for str { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { Some(self).serialize(parcel) } } @@ -549,7 +559,7 @@ impl Serialize for str { impl SerializeArray for &str {} impl Serialize for String { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { Some(self.as_str()).serialize(parcel) } } @@ -557,13 +567,13 @@ impl Serialize for String { impl SerializeArray for String {} impl SerializeOption for String { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> { SerializeOption::serialize_option(this.map(String::as_str), parcel) } } impl Deserialize for Option<String> { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { let mut vec: Option<Vec<u8>> = None; let status = unsafe { // Safety: `Parcel` always contains a valid pointer to an `AParcel`. @@ -591,7 +601,7 @@ impl Deserialize for Option<String> { impl DeserializeArray for Option<String> {} impl Deserialize for String { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { Deserialize::deserialize(parcel) .transpose() .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) @@ -601,19 +611,19 @@ impl Deserialize for String { impl DeserializeArray for String {} impl<T: SerializeArray> Serialize for [T] { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { SerializeArray::serialize_array(self, parcel) } } impl<T: SerializeArray> Serialize for Vec<T> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + 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 Parcel) -> Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> { if let Some(v) = this { SerializeArray::serialize_array(v, parcel) } else { @@ -623,13 +633,13 @@ impl<T: SerializeArray> SerializeOption for [T] { } impl<T: SerializeArray> SerializeOption for Vec<T> { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { + 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> { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { DeserializeArray::deserialize_array(parcel) .transpose() .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) @@ -637,25 +647,25 @@ impl<T: DeserializeArray> Deserialize for Vec<T> { } impl<T: DeserializeArray> DeserializeOption for Vec<T> { - fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { + fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> { DeserializeArray::deserialize_array(parcel) } } impl Serialize for Stability { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { i32::from(*self).serialize(parcel) } } impl Deserialize for Stability { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { i32::deserialize(parcel).and_then(Stability::try_from) } } impl Serialize for Status { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { unsafe { // Safety: `Parcel` always contains a valid pointer to an `AParcel` // and `Status` always contains a valid pointer to an `AStatus`, so @@ -670,7 +680,7 @@ impl Serialize for Status { } impl Deserialize for Status { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { let mut status_ptr = ptr::null_mut(); let ret_status = unsafe { // Safety: `Parcel` always contains a valid pointer to an @@ -691,13 +701,13 @@ impl Deserialize for Status { } impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + 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 Parcel) -> Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> { SerializeOption::serialize_option(this.map(|b| &**b), parcel) } } @@ -705,14 +715,14 @@ impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {} impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> 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>> { + fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> { let ibinder: Option<SpIBinder> = parcel.read()?; ibinder.map(FromIBinder::try_from).transpose() } @@ -722,29 +732,29 @@ 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 Parcel) -> Result<()> { + 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 Parcel) -> Result<()> { + 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 Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { SerializeOption::serialize_option(self.as_ref(), parcel) } } impl<T: DeserializeOption> Deserialize for Option<T> { - fn deserialize(parcel: &Parcel) -> Result<Self> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> { DeserializeOption::deserialize_option(parcel) } - fn deserialize_from(&mut self, parcel: &Parcel) -> Result<()> { + fn deserialize_from(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> { DeserializeOption::deserialize_option_from(self, parcel) } } @@ -762,7 +772,7 @@ macro_rules! impl_serialize_for_parcelable { impl $crate::parcel::Serialize for $parcelable { fn serialize( &self, - parcel: &mut $crate::parcel::Parcel, + parcel: &mut $crate::parcel::BorrowedParcel<'_>, ) -> $crate::Result<()> { <Self as $crate::parcel::SerializeOption>::serialize_option( Some(self), @@ -776,7 +786,7 @@ macro_rules! impl_serialize_for_parcelable { impl $crate::parcel::SerializeOption for $parcelable { fn serialize_option( this: Option<&Self>, - parcel: &mut $crate::parcel::Parcel, + parcel: &mut $crate::parcel::BorrowedParcel<'_>, ) -> $crate::Result<()> { if let Some(this) = this { use $crate::parcel::Parcelable; @@ -796,13 +806,12 @@ macro_rules! impl_serialize_for_parcelable { /// `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) => { impl $crate::parcel::Deserialize for $parcelable { fn deserialize( - parcel: &$crate::parcel::Parcel, + parcel: &$crate::parcel::BorrowedParcel<'_>, ) -> $crate::Result<Self> { $crate::parcel::DeserializeOption::deserialize_option(parcel) .transpose() @@ -810,7 +819,7 @@ macro_rules! impl_deserialize_for_parcelable { } fn deserialize_from( &mut self, - parcel: &$crate::parcel::Parcel, + parcel: &$crate::parcel::BorrowedParcel<'_>, ) -> $crate::Result<()> { let status: i32 = parcel.read()?; if status == $crate::parcel::NULL_PARCELABLE_FLAG { @@ -826,7 +835,7 @@ macro_rules! impl_deserialize_for_parcelable { impl $crate::parcel::DeserializeOption for $parcelable { fn deserialize_option( - parcel: &$crate::parcel::Parcel, + parcel: &$crate::parcel::BorrowedParcel<'_>, ) -> $crate::Result<Option<Self>> { let mut result = None; Self::deserialize_option_from(&mut result, parcel)?; @@ -834,7 +843,7 @@ macro_rules! impl_deserialize_for_parcelable { } fn deserialize_option_from( this: &mut Option<Self>, - parcel: &$crate::parcel::Parcel, + parcel: &$crate::parcel::BorrowedParcel<'_>, ) -> $crate::Result<()> { let status: i32 = parcel.read()?; if status == $crate::parcel::NULL_PARCELABLE_FLAG { @@ -851,326 +860,332 @@ macro_rules! impl_deserialize_for_parcelable { } impl<T: Serialize> Serialize for Box<T> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { Serialize::serialize(&**self, parcel) } } impl<T: Deserialize> Deserialize for Box<T> { - fn deserialize(parcel: &Parcel) -> Result<Self> { + 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 Parcel) -> Result<()> { + 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: &Parcel) -> Result<Option<Self>> { + fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> { DeserializeOption::deserialize_option(parcel).map(|t| t.map(Box::new)) } } -#[test] -fn test_custom_parcelable() { - 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) +#[cfg(test)] +mod tests { + use crate::Parcel; + use super::*; + + #[test] + fn test_custom_parcelable() { + 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 { - fn deserialize(parcel: &Parcel) -> Result<Self> { - Ok(Custom( - parcel.read()?, - parcel.read()?, - parcel.read()?, - parcel.read::<Option<Vec<String>>>()?.unwrap(), - )) + impl Deserialize for Custom { + 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 string8 = "Custom Parcelable".to_string(); - let s1 = "str1".to_string(); - let s2 = "str2".to_string(); - let s3 = "str3".to_string(); + let s1 = "str1".to_string(); + let s2 = "str2".to_string(); + let s3 = "str3".to_string(); - let strs = vec![s1, s2, s3]; + let strs = vec![s1, s2, s3]; - let custom = Custom(123_456_789, true, string8, strs); + let custom = Custom(123_456_789, true, string8, strs); - let mut parcel = Parcel::new(); - let start = parcel.get_data_position(); + let mut parcel = Parcel::new(); + let start = parcel.get_data_position(); - assert!(custom.serialize(&mut parcel).is_ok()); + assert!(custom.serialize(&mut parcel.borrowed()).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } - let custom2 = Custom::deserialize(&parcel).unwrap(); + 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); -} + 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]; + #[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(); + let mut parcel = Parcel::new(); + let start = parcel.get_data_position(); - assert!(bools.serialize(&mut parcel).is_ok()); + assert!(bools.serialize(&mut parcel.borrowed()).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).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()); - } + 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(); + let vec = Vec::<bool>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, [true, false, false, true]); + assert_eq!(vec, [true, false, false, true]); - let u8s = [101u8, 255, 42, 117]; + let u8s = [101u8, 255, 42, 117]; - let mut parcel = Parcel::new(); - let start = parcel.get_data_position(); + let mut parcel = Parcel::new(); + let start = parcel.get_data_position(); - assert!(parcel.write(&u8s[..]).is_ok()); + assert!(parcel.write(&u8s[..]).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).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()); - } + 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 vec = Vec::<u8>::deserialize(parcel.borrowed_ref()).unwrap(); + assert_eq!(vec, [101, 255, 42, 117]); - let i8s = [-128i8, 127, 42, -117]; + let i8s = [-128i8, 127, 42, -117]; - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } - assert!(parcel.write(&i8s[..]).is_ok()); + assert!(parcel.write(&i8s[..]).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).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()); - } + 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 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]; + 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(u16s.serialize(&mut parcel.borrowed()).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()); - } + 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(); + let vec = Vec::<u16>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, [u16::max_value(), 12_345, 42, 117]); + assert_eq!(vec, [u16::max_value(), 12_345, 42, 117]); - let i16s = [i16::max_value(), i16::min_value(), 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(i16s.serialize(&mut parcel.borrowed()).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()); - } + 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(); + let vec = Vec::<i16>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, [i16::max_value(), i16::min_value(), 42, -117]); + assert_eq!(vec, [i16::max_value(), i16::min_value(), 42, -117]); - let u32s = [u32::max_value(), 12_345, 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(u32s.serialize(&mut parcel.borrowed()).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()); - } + 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(); + let vec = Vec::<u32>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, [u32::max_value(), 12_345, 42, 117]); + assert_eq!(vec, [u32::max_value(), 12_345, 42, 117]); - let i32s = [i32::max_value(), i32::min_value(), 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(i32s.serialize(&mut parcel.borrowed()).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()); - } + 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(); + let vec = Vec::<i32>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, [i32::max_value(), i32::min_value(), 42, -117]); + assert_eq!(vec, [i32::max_value(), i32::min_value(), 42, -117]); - let u64s = [u64::max_value(), 12_345, 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(u64s.serialize(&mut parcel.borrowed()).is_ok()); + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } - let vec = Vec::<u64>::deserialize(&parcel).unwrap(); + let vec = Vec::<u64>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, [u64::max_value(), 12_345, 42, 117]); + assert_eq!(vec, [u64::max_value(), 12_345, 42, 117]); - let i64s = [i64::max_value(), i64::min_value(), 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(i64s.serialize(&mut parcel.borrowed()).is_ok()); + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } - let vec = Vec::<i64>::deserialize(&parcel).unwrap(); + let vec = Vec::<i64>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, [i64::max_value(), i64::min_value(), 42, -117]); + assert_eq!(vec, [i64::max_value(), i64::min_value(), 42, -117]); - let f32s = [ - std::f32::NAN, - std::f32::INFINITY, - 1.23456789, - std::f32::EPSILON, - ]; + 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(f32s.serialize(&mut parcel.borrowed()).is_ok()); + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } - let vec = Vec::<f32>::deserialize(&parcel).unwrap(); + 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..]); + // 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, - ]; + 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(f64s.serialize(&mut parcel.borrowed()).is_ok()); + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } - let vec = Vec::<f64>::deserialize(&parcel).unwrap(); + 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..]); + // 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 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]; + 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()); - } + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } + assert!(strs.serialize(&mut parcel.borrowed()).is_ok()); + unsafe { + assert!(parcel.set_data_position(start).is_ok()); + } - let vec = Vec::<String>::deserialize(&parcel).unwrap(); + let vec = Vec::<String>::deserialize(parcel.borrowed_ref()).unwrap(); - assert_eq!(vec, strs); + assert_eq!(vec, strs); + } } diff --git a/libs/binder/rust/src/parcel/parcelable_holder.rs b/libs/binder/rust/src/parcel/parcelable_holder.rs index bccfd2d25e..b4282b2ec8 100644 --- a/libs/binder/rust/src/parcel/parcelable_holder.rs +++ b/libs/binder/rust/src/parcel/parcelable_holder.rs @@ -16,7 +16,7 @@ use crate::binder::Stability; use crate::error::{Result, StatusCode}; -use crate::parcel::{OwnedParcel, Parcel, Parcelable}; +use crate::parcel::{Parcel, BorrowedParcel, Parcelable}; use crate::{impl_deserialize_for_parcelable, impl_serialize_for_parcelable}; use downcast_rs::{impl_downcast, DowncastSync}; @@ -50,7 +50,7 @@ enum ParcelableHolderData { parcelable: Arc<dyn AnyParcelable>, name: String, }, - Parcel(OwnedParcel), + Parcel(Parcel), } impl Default for ParcelableHolderData { @@ -148,7 +148,6 @@ impl ParcelableHolder { } } ParcelableHolderData::Parcel(ref mut parcel) => { - let parcel = parcel.borrowed(); unsafe { // Safety: 0 should always be a valid position. parcel.set_data_position(0)?; @@ -160,7 +159,7 @@ impl ParcelableHolder { } let mut parcelable = T::default(); - parcelable.read_from_parcel(&parcel)?; + parcelable.read_from_parcel(parcel.borrowed_ref())?; let parcelable = Arc::new(parcelable); let result = Arc::clone(&parcelable); @@ -181,7 +180,7 @@ impl_serialize_for_parcelable!(ParcelableHolder); impl_deserialize_for_parcelable!(ParcelableHolder); impl Parcelable for ParcelableHolder { - fn write_to_parcel(&self, parcel: &mut Parcel) -> Result<()> { + fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { parcel.write(&self.stability)?; let mut data = self.data.lock().unwrap(); @@ -214,14 +213,13 @@ impl Parcelable for ParcelableHolder { Ok(()) } ParcelableHolderData::Parcel(ref mut p) => { - let p = p.borrowed(); parcel.write(&p.get_data_size())?; - parcel.append_all_from(&p) + parcel.append_all_from(&*p) } } } - fn read_from_parcel(&mut self, parcel: &Parcel) -> Result<()> { + fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> { self.stability = parcel.read()?; let data_size: i32 = parcel.read()?; @@ -242,10 +240,8 @@ impl Parcelable for ParcelableHolder { .checked_add(data_size) .ok_or(StatusCode::BAD_VALUE)?; - let mut new_parcel = OwnedParcel::new(); - new_parcel - .borrowed() - .append_from(parcel, data_start, data_size)?; + let mut new_parcel = Parcel::new(); + new_parcel.append_from(parcel, data_start, data_size)?; *self.data.get_mut().unwrap() = ParcelableHolderData::Parcel(new_parcel); unsafe { diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs index a8d0c33034..83553d793b 100644 --- a/libs/binder/rust/src/proxy.rs +++ b/libs/binder/rust/src/proxy.rs @@ -22,8 +22,7 @@ use crate::binder::{ }; use crate::error::{status_result, Result, StatusCode}; use crate::parcel::{ - Deserialize, DeserializeArray, DeserializeOption, OwnedParcel, Parcel, Serialize, SerializeArray, - SerializeOption, + Parcel, BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray, SerializeOption, }; use crate::sys; @@ -235,7 +234,7 @@ impl Drop for SpIBinder { } impl<T: AsNative<sys::AIBinder>> IBinderInternal for T { - fn prepare_transact(&self) -> Result<OwnedParcel> { + fn prepare_transact(&self) -> Result<Parcel> { let mut input = ptr::null_mut(); let status = unsafe { // Safety: `SpIBinder` guarantees that `self` always contains a @@ -255,16 +254,16 @@ impl<T: AsNative<sys::AIBinder>> IBinderInternal for T { // Safety: At this point, `input` is either a valid, owned `AParcel` // pointer, or null. `OwnedParcel::from_raw` safely handles both cases, // taking ownership of the parcel. - OwnedParcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL) + Parcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL) } } fn submit_transact( &self, code: TransactionCode, - data: OwnedParcel, + data: Parcel, flags: TransactionFlags, - ) -> Result<OwnedParcel> { + ) -> Result<Parcel> { let mut reply = ptr::null_mut(); let status = unsafe { // Safety: `SpIBinder` guarantees that `self` always contains a @@ -299,7 +298,7 @@ impl<T: AsNative<sys::AIBinder>> IBinderInternal for T { // construct a `Parcel` out of it. `AIBinder_transact` passes // ownership of the `reply` parcel to Rust, so we need to // construct an owned variant. - OwnedParcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL) + Parcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL) } } @@ -415,13 +414,13 @@ impl<T: AsNative<sys::AIBinder>> IBinder for T { } impl Serialize for SpIBinder { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { + fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> { parcel.write_binder(Some(self)) } } impl SerializeOption for SpIBinder { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { + fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> { parcel.write_binder(this) } } @@ -429,7 +428,7 @@ impl SerializeOption for SpIBinder { impl SerializeArray for SpIBinder {} impl Deserialize for SpIBinder { - fn deserialize(parcel: &Parcel) -> Result<SpIBinder> { + fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<SpIBinder> { parcel .read_binder() .transpose() @@ -438,7 +437,7 @@ impl Deserialize for SpIBinder { } impl DeserializeOption for SpIBinder { - fn deserialize_option(parcel: &Parcel) -> Result<Option<SpIBinder>> { + fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<SpIBinder>> { parcel.read_binder() } } diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index ebfe879f49..1fd2eadc4e 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -17,7 +17,7 @@ //! Rust Binder crate integration tests use binder::declare_binder_interface; -use binder::parcel::{Parcel, OwnedParcel}; +use binder::parcel::BorrowedParcel; use binder::{ Binder, BinderFeatures, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode, FIRST_CALL_TRANSACTION, @@ -179,8 +179,8 @@ declare_binder_interface! { fn on_transact( service: &dyn ITest, code: TransactionCode, - _data: &Parcel, - reply: &mut Parcel, + _data: &BorrowedParcel<'_>, + reply: &mut BorrowedParcel<'_>, ) -> binder::Result<()> { match code.try_into()? { TestTransactionCode::Test => reply.write(&service.test()?), @@ -218,24 +218,24 @@ impl<P: binder::BinderAsyncPool> IATest<P> for BpTest { fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> { let binder = self.binder.clone(); P::spawn( - move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()), - |reply| async move { reply?.into_parcel().read() } + move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())), + |reply| async move { reply?.read() } ) } fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> { let binder = self.binder.clone(); P::spawn( - move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()), - |reply| async move { reply?.into_parcel().read() } + move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())), + |reply| async move { reply?.read() } ) } fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> { let binder = self.binder.clone(); P::spawn( - move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()), - |reply| async move { reply?.into_parcel().read() } + move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())), + |reply| async move { reply?.read() } ) } } @@ -284,8 +284,8 @@ declare_binder_interface! { fn on_transact_same_descriptor( _service: &dyn ITestSameDescriptor, _code: TransactionCode, - _data: &Parcel, - _reply: &mut Parcel, + _data: &BorrowedParcel<'_>, + _reply: &mut BorrowedParcel<'_>, ) -> binder::Result<()> { Ok(()) } diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs index 66ba846c2d..1fc761e2c8 100644 --- a/libs/binder/rust/tests/serialization.rs +++ b/libs/binder/rust/tests/serialization.rs @@ -20,7 +20,7 @@ use binder::declare_binder_interface; use binder::parcel::ParcelFileDescriptor; use binder::{ - Binder, BinderFeatures, ExceptionCode, Interface, Parcel, Result, SpIBinder, Status, + Binder, BinderFeatures, BorrowedParcel, ExceptionCode, Interface, Result, SpIBinder, Status, StatusCode, TransactionCode, }; @@ -111,8 +111,8 @@ impl ReadParcelTest for () {} fn on_transact( _service: &dyn ReadParcelTest, code: TransactionCode, - parcel: &Parcel, - reply: &mut Parcel, + parcel: &BorrowedParcel<'_>, + reply: &mut BorrowedParcel<'_>, ) -> Result<()> { match code { bindings::Transaction_TEST_BOOL => { |