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

Commit ee12a1ee authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes from topic "unstructured_parcelable_macros" into main am: ca340b1f

parents c65973d5 ca340b1f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -136,8 +136,8 @@ pub mod binder_impl {
    pub use crate::native::Binder;
    pub use crate::parcel::{
        BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Parcel,
        ParcelableMetadata, Serialize, SerializeArray, SerializeOption, NON_NULL_PARCELABLE_FLAG,
        NULL_PARCELABLE_FLAG,
        ParcelableMetadata, Serialize, SerializeArray, SerializeOption, UnstructuredParcelable,
        NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG,
    };
    pub use crate::proxy::{AssociateClass, Proxy};
}
+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ mod parcelable_holder;
pub use self::file_descriptor::ParcelFileDescriptor;
pub use self::parcelable::{
    Deserialize, DeserializeArray, DeserializeOption, Parcelable, Serialize, SerializeArray,
    SerializeOption, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG,
    SerializeOption, UnstructuredParcelable, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG,
};
pub use self::parcelable_holder::{ParcelableHolder, ParcelableMetadata};

+149 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ use std::os::raw::c_char;
use std::ptr;
use std::slice;

/// Super-trait for Binder parcelables.
/// Super-trait for structured Binder parcelables, i.e. those generated from AIDL.
///
/// This trait is equivalent `android::Parcelable` in C++,
/// and defines a common interface that all parcelables need
@@ -50,6 +50,35 @@ pub trait Parcelable {
    fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()>;
}

/// Super-trait for unstructured Binder parcelables, i.e. those implemented manually.
///
/// These differ from structured parcelables in that they may not have a reasonable default value
/// and so aren't required to implement `Default`.
pub trait UnstructuredParcelable: Sized {
    /// Internal serialization function for parcelables.
    ///
    /// This method is mainly for internal use. `Serialize::serialize` and its variants are
    /// generally preferred over calling this function, since the former also prepend a header.
    fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>;

    /// Internal deserialization function for parcelables.
    ///
    /// This method is mainly for internal use. `Deserialize::deserialize` and its variants are
    /// generally preferred over calling this function, since the former also parse the additional
    /// header.
    fn from_parcel(parcel: &BorrowedParcel<'_>) -> Result<Self>;

    /// Internal deserialization function for parcelables.
    ///
    /// This method is mainly for internal use. `Deserialize::deserialize_from` and its variants are
    /// generally preferred over calling this function, since the former also parse the additional
    /// header.
    fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<()> {
        *self = Self::from_parcel(parcel)?;
        Ok(())
    }
}

/// A struct whose instances can be written to a [`crate::parcel::Parcel`].
// Might be able to hook this up as a serde backend in the future?
pub trait Serialize {
@@ -1002,6 +1031,125 @@ macro_rules! impl_deserialize_for_parcelable {
    };
}

/// Implements `Serialize` trait and friends for an unstructured parcelable.
///
/// The target type must implement the `UnstructuredParcelable` trait.
#[macro_export]
macro_rules! impl_serialize_for_unstructured_parcelable {
    ($parcelable:ident) => {
        $crate::impl_serialize_for_unstructured_parcelable!($parcelable < >);
    };
    ($parcelable:ident < $( $param:ident ),* , >) => {
        $crate::impl_serialize_for_unstructured_parcelable!($parcelable < $($param),* >);
    };
    ($parcelable:ident < $( $param:ident ),* > ) => {
        impl < $($param),* > $crate::binder_impl::Serialize for $parcelable < $($param),* > {
            fn serialize(
                &self,
                parcel: &mut $crate::binder_impl::BorrowedParcel<'_>,
            ) -> std::result::Result<(), $crate::StatusCode> {
                <Self as $crate::binder_impl::SerializeOption>::serialize_option(Some(self), parcel)
            }
        }

        impl < $($param),* > $crate::binder_impl::SerializeArray for $parcelable < $($param),* > {}

        impl < $($param),* > $crate::binder_impl::SerializeOption for $parcelable < $($param),* > {
            fn serialize_option(
                this: Option<&Self>,
                parcel: &mut $crate::binder_impl::BorrowedParcel<'_>,
            ) -> std::result::Result<(), $crate::StatusCode> {
                if let Some(this) = this {
                    use $crate::binder_impl::UnstructuredParcelable;
                    parcel.write(&$crate::binder_impl::NON_NULL_PARCELABLE_FLAG)?;
                    this.write_to_parcel(parcel)
                } else {
                    parcel.write(&$crate::binder_impl::NULL_PARCELABLE_FLAG)
                }
            }
        }
    };
}

/// Implement `Deserialize` trait and friends for an unstructured parcelable
///
/// The target type must implement the `UnstructuredParcelable` trait.
#[macro_export]
macro_rules! impl_deserialize_for_unstructured_parcelable {
    ($parcelable:ident) => {
        $crate::impl_deserialize_for_unstructured_parcelable!($parcelable < >);
    };
    ($parcelable:ident < $( $param:ident ),* , >) => {
        $crate::impl_deserialize_for_unstructured_parcelable!($parcelable < $($param),* >);
    };
    ($parcelable:ident < $( $param:ident ),* > ) => {
        impl < $($param: Default),* > $crate::binder_impl::Deserialize for $parcelable < $($param),* > {
            type UninitType = Option<Self>;
            fn uninit() -> Self::UninitType { None }
            fn from_init(value: Self) -> Self::UninitType { Some(value) }
            fn deserialize(
                parcel: &$crate::binder_impl::BorrowedParcel<'_>,
            ) -> std::result::Result<Self, $crate::StatusCode> {
                $crate::binder_impl::DeserializeOption::deserialize_option(parcel)
                    .transpose()
                    .unwrap_or(Err($crate::StatusCode::UNEXPECTED_NULL))
            }
            fn deserialize_from(
                &mut self,
                parcel: &$crate::binder_impl::BorrowedParcel<'_>,
            ) -> std::result::Result<(), $crate::StatusCode> {
                let status: i32 = parcel.read()?;
                if status == $crate::binder_impl::NULL_PARCELABLE_FLAG {
                    Err($crate::StatusCode::UNEXPECTED_NULL)
                } else {
                    use $crate::binder_impl::UnstructuredParcelable;
                    self.read_from_parcel(parcel)
                }
            }
        }

        impl < $($param: Default),* > $crate::binder_impl::DeserializeArray for $parcelable < $($param),* > {}

        impl < $($param: Default),* > $crate::binder_impl::DeserializeOption for $parcelable < $($param),* > {
            fn deserialize_option(
                parcel: &$crate::binder_impl::BorrowedParcel<'_>,
            ) -> std::result::Result<Option<Self>, $crate::StatusCode> {
                let present: i32 = parcel.read()?;
                match present {
                    $crate::binder_impl::NULL_PARCELABLE_FLAG => Ok(None),
                    $crate::binder_impl::NON_NULL_PARCELABLE_FLAG => {
                        use $crate::binder_impl::UnstructuredParcelable;
                        Ok(Some(Self::from_parcel(parcel)?))
                    }
                    _ => Err(StatusCode::BAD_VALUE),
                }
            }
            fn deserialize_option_from(
                this: &mut Option<Self>,
                parcel: &$crate::binder_impl::BorrowedParcel<'_>,
            ) -> std::result::Result<(), $crate::StatusCode> {
                let present: i32 = parcel.read()?;
                match present {
                    $crate::binder_impl::NULL_PARCELABLE_FLAG => {
                        *this = None;
                        Ok(())
                    }
                    $crate::binder_impl::NON_NULL_PARCELABLE_FLAG => {
                        use $crate::binder_impl::UnstructuredParcelable;
                        if let Some(this) = this {
                            this.read_from_parcel(parcel)?;
                        } else {
                            *this = Some(Self::from_parcel(parcel)?);
                        }
                        Ok(())
                    }
                    _ => Err(StatusCode::BAD_VALUE),
                }
            }
        }
    };
}

impl<T: Serialize> Serialize for Box<T> {
    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
        Serialize::serialize(&**self, parcel)
+28 −71
Original line number Diff line number Diff line
@@ -19,10 +19,8 @@ extern crate nativewindow_bindgen as ffi;
pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};

use binder::{
    binder_impl::{
        BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize,
        SerializeArray, SerializeOption, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG,
    },
    binder_impl::{BorrowedParcel, UnstructuredParcelable},
    impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
    unstable_api::{status_result, AsNative},
    StatusCode,
};
@@ -210,57 +208,18 @@ impl Clone for HardwareBuffer {
    }
}

impl Serialize for HardwareBuffer {
    fn serialize(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
        SerializeOption::serialize_option(Some(self), parcel)
    }
}

impl SerializeOption for HardwareBuffer {
    fn serialize_option(
        this: Option<&Self>,
        parcel: &mut BorrowedParcel,
    ) -> Result<(), StatusCode> {
        if let Some(this) = this {
            parcel.write(&NON_NULL_PARCELABLE_FLAG)?;

impl UnstructuredParcelable for HardwareBuffer {
    fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
        let status =
        // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
        // because it must have been allocated by `AHardwareBuffer_allocate`,
        // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
        // released it.
                unsafe { AHardwareBuffer_writeToParcel(this.0.as_ptr(), parcel.as_native_mut()) };
            unsafe { AHardwareBuffer_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) };
        status_result(status)
        } else {
            parcel.write(&NULL_PARCELABLE_FLAG)
    }
    }
}

impl Deserialize for HardwareBuffer {
    type UninitType = Option<Self>;

    fn uninit() -> Option<Self> {
        None
    }

    fn from_init(value: Self) -> Option<Self> {
        Some(value)
    }

    fn deserialize(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
        DeserializeOption::deserialize_option(parcel)
            .transpose()
            .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
    }
}

impl DeserializeOption for HardwareBuffer {
    fn deserialize_option(parcel: &BorrowedParcel) -> Result<Option<Self>, StatusCode> {
        let present: i32 = parcel.read()?;
        match present {
            NULL_PARCELABLE_FLAG => Ok(None),
            NON_NULL_PARCELABLE_FLAG => {
    fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
        let mut buffer = null_mut();

        let status =
@@ -273,18 +232,16 @@ impl DeserializeOption for HardwareBuffer {

        status_result(status)?;

                Ok(Some(Self(NonNull::new(buffer).expect(
        Ok(Self(
            NonNull::new(buffer).expect(
                "AHardwareBuffer_readFromParcel returned success but didn't allocate buffer",
                ))))
            }
            _ => Err(StatusCode::BAD_VALUE),
            ),
        ))
    }
}
}

impl SerializeArray for HardwareBuffer {}

impl DeserializeArray for HardwareBuffer {}
impl_deserialize_for_unstructured_parcelable!(HardwareBuffer);
impl_serialize_for_unstructured_parcelable!(HardwareBuffer);

// SAFETY: The underlying *AHardwareBuffers can be moved between threads.
unsafe impl Send for HardwareBuffer {}