Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c133845 authored by Andrei Homescu's avatar Andrei Homescu
Browse files

binder_rs: Add Parcelable trait

Adds Parcelable trait that all auto-generated Rust parcelables
implement. This trait provides the get_descriptor() and
get_stability(), as well as internal serialization and
deserialization methods specific to parcelables.

Bug: 169035750
Test: m
Change-Id: Ib97ac4d79cd9829ab3968076492ac1f28f27e8ff
parent ee132fac
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ mod parcelable;
pub use self::file_descriptor::ParcelFileDescriptor;
pub use self::parcelable::{
    Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray, SerializeOption,
    Parcelable,
};

/// Container for a message (data and object references) that can be sent
+70 −11
Original line number Diff line number Diff line
@@ -27,6 +27,29 @@ use std::mem::{self, MaybeUninit};
use std::ptr;
use std::slice;

/// Super-trait for Binder parcelables.
///
/// This trait is equivalent `android::Parcelable` in C++,
/// and defines a common interface that all parcelables need
/// to implement.
pub trait Parcelable {
    /// Internal serialization function for parcelables.
    ///
    /// This method is mainly for internal use.
    /// `Serialize::serialize` and its variants are generally
    /// preferred over this function, since the former also
    /// prepend a header.
    fn write_to_parcel(&self, parcel: &mut Parcel) -> Result<()>;

    /// Internal deserialization function for parcelables.
    ///
    /// This method is mainly for internal use.
    /// `Deserialize::deserialize` and its variants are generally
    /// preferred over this function, since the former also
    /// parse the additional header.
    fn read_from_parcel(&mut self, parcel: &Parcel) -> 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 {
@@ -711,19 +734,53 @@ impl<T: DeserializeOption> Deserialize for Option<T> {
    }
}

/// Implement `Serialize` trait and friends for a parcelable
///
/// This is an internal macro used by the AIDL compiler to implement
/// `Serialize`, `SerializeArray` and `SerializeOption` for
/// structured parcelables. The target type must implement the
/// `Parcelable` trait.
/// ```
#[macro_export]
macro_rules! impl_serialize_for_parcelable {
    ($parcelable:ident) => {
        impl $crate::parcel::Serialize for $parcelable {
            fn serialize(
                &self,
                parcel: &mut $crate::parcel::Parcel,
            ) -> $crate::Result<()> {
                <Self as $crate::parcel::SerializeOption>::serialize_option(
                    Some(self),
                    parcel,
                )
            }
        }

        impl $crate::parcel::SerializeArray for $parcelable {}

        impl $crate::parcel::SerializeOption for $parcelable {
            fn serialize_option(
                this: Option<&Self>,
                parcel: &mut $crate::parcel::Parcel,
            ) -> $crate::Result<()> {
                if let Some(this) = this {
                    use $crate::parcel::Parcelable;
                    parcel.write(&1i32)?;
                    this.write_to_parcel(parcel)
                } else {
                    parcel.write(&0i32)
                }
            }
        }
    }
}

/// Implement `Deserialize` trait and friends for a parcelable
///
/// This is an internal macro used by the AIDL compiler to implement
/// `Deserialize`, `DeserializeArray` and `DeserializeOption` for
/// structured parcelables. The target type must implement a
/// `deserialize_parcelable` method with the following signature:
/// ```no_run
/// fn deserialize_parcelable(
///     &mut self,
///     parcel: &binder::parcel::Parcelable,
/// ) -> binder::Result<()> {
///     // ...
/// }
/// structured parcelables. The target type must implement the
/// `Parcelable` trait.
/// ```
#[macro_export]
macro_rules! impl_deserialize_for_parcelable {
@@ -744,7 +801,8 @@ macro_rules! impl_deserialize_for_parcelable {
                if status == 0 {
                    Err($crate::StatusCode::UNEXPECTED_NULL)
                } else {
                    self.deserialize_parcelable(parcel)
                    use $crate::parcel::Parcelable;
                    self.read_from_parcel(parcel)
                }
            }
        }
@@ -768,8 +826,9 @@ macro_rules! impl_deserialize_for_parcelable {
                    *this = None;
                    Ok(())
                } else {
                    use $crate::parcel::Parcelable;
                    this.get_or_insert_with(Self::default)
                        .deserialize_parcelable(parcel)
                        .read_from_parcel(parcel)
                }
            }
        }