Add UnstructuredParcelable trait and macros.

Bug: 303064346
Test: atest aidl_integration_test
Change-Id: I067e05d5f03b678c963ac159574116ef3e33c9ed
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 7f9348d..16049f2 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -136,8 +136,8 @@
     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};
 }
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index f9f135d..3bfc425 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -34,7 +34,7 @@
 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};
 
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 9008a3c..df25fac 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -27,7 +27,7 @@
 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,25 @@
     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>;
+}
+
 /// 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 +1021,91 @@
     };
 }
 
+/// 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))
+            }
+        }
+
+        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),
+                }
+            }
+        }
+    };
+}
+
 impl<T: Serialize> Serialize for Box<T> {
     fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         Serialize::serialize(&**self, parcel)
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs
index 6f86c4a..e416517 100644
--- a/libs/nativewindow/rust/src/lib.rs
+++ b/libs/nativewindow/rust/src/lib.rs
@@ -19,10 +19,8 @@
 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,81 +208,40 @@
     }
 }
 
-impl Serialize for HardwareBuffer {
-    fn serialize(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
-        SerializeOption::serialize_option(Some(self), parcel)
+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(self.0.as_ptr(), parcel.as_native_mut()) };
+        status_result(status)
+    }
+
+    fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
+        let mut buffer = null_mut();
+
+        let status =
+        // SAFETY: Both pointers must be valid because they are obtained from references.
+        // `AHardwareBuffer_readFromParcel` doesn't store them or do anything else special
+        // with them. If it returns success then it will have allocated a new
+        // `AHardwareBuffer` and incremented the reference count, so we can use it until we
+        // release it.
+            unsafe { AHardwareBuffer_readFromParcel(parcel.as_native(), &mut buffer) };
+
+        status_result(status)?;
+
+        Ok(Self(
+            NonNull::new(buffer).expect(
+                "AHardwareBuffer_readFromParcel returned success but didn't allocate buffer",
+            ),
+        ))
     }
 }
 
-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)?;
-
-            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()) };
-            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 => {
-                let mut buffer = null_mut();
-
-                let status =
-                // SAFETY: Both pointers must be valid because they are obtained from references.
-                // `AHardwareBuffer_readFromParcel` doesn't store them or do anything else special
-                // with them. If it returns success then it will have allocated a new
-                // `AHardwareBuffer` and incremented the reference count, so we can use it until we
-                // release it.
-                    unsafe { AHardwareBuffer_readFromParcel(parcel.as_native(), &mut buffer) };
-
-                status_result(status)?;
-
-                Ok(Some(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 {}