@@ -27,7 +27,7 @@ use std::os::raw::c_char;
2727use std:: ptr;
2828use std:: slice;
2929
30- /// Super-trait for Binder parcelables.
30+ /// Super-trait for structured Binder parcelables, i.e. those generated from AIDL .
3131///
3232/// This trait is equivalent `android::Parcelable` in C++,
3333/// and defines a common interface that all parcelables need
@@ -50,6 +50,35 @@ pub trait Parcelable {
5050 fn read_from_parcel ( & mut self , parcel : & BorrowedParcel < ' _ > ) -> Result < ( ) > ;
5151}
5252
53+ /// Super-trait for unstructured Binder parcelables, i.e. those implemented manually.
54+ ///
55+ /// These differ from structured parcelables in that they may not have a reasonable default value
56+ /// and so aren't required to implement `Default`.
57+ pub trait UnstructuredParcelable : Sized {
58+ /// Internal serialization function for parcelables.
59+ ///
60+ /// This method is mainly for internal use. `Serialize::serialize` and its variants are
61+ /// generally preferred over calling this function, since the former also prepend a header.
62+ fn write_to_parcel ( & self , parcel : & mut BorrowedParcel < ' _ > ) -> Result < ( ) > ;
63+
64+ /// Internal deserialization function for parcelables.
65+ ///
66+ /// This method is mainly for internal use. `Deserialize::deserialize` and its variants are
67+ /// generally preferred over calling this function, since the former also parse the additional
68+ /// header.
69+ fn from_parcel ( parcel : & BorrowedParcel < ' _ > ) -> Result < Self > ;
70+
71+ /// Internal deserialization function for parcelables.
72+ ///
73+ /// This method is mainly for internal use. `Deserialize::deserialize_from` and its variants are
74+ /// generally preferred over calling this function, since the former also parse the additional
75+ /// header.
76+ fn read_from_parcel ( & mut self , parcel : & BorrowedParcel < ' _ > ) -> Result < ( ) > {
77+ * self = Self :: from_parcel ( parcel) ?;
78+ Ok ( ( ) )
79+ }
80+ }
81+
5382/// A struct whose instances can be written to a [`crate::parcel::Parcel`].
5483// Might be able to hook this up as a serde backend in the future?
5584pub trait Serialize {
@@ -1002,6 +1031,125 @@ macro_rules! impl_deserialize_for_parcelable {
10021031 } ;
10031032}
10041033
1034+ /// Implements `Serialize` trait and friends for an unstructured parcelable.
1035+ ///
1036+ /// The target type must implement the `UnstructuredParcelable` trait.
1037+ #[ macro_export]
1038+ macro_rules! impl_serialize_for_unstructured_parcelable {
1039+ ( $parcelable: ident) => {
1040+ $crate:: impl_serialize_for_unstructured_parcelable!( $parcelable < >) ;
1041+ } ;
1042+ ( $parcelable: ident < $( $param: ident ) ,* , >) => {
1043+ $crate:: impl_serialize_for_unstructured_parcelable!( $parcelable < $( $param) ,* >) ;
1044+ } ;
1045+ ( $parcelable: ident < $( $param: ident ) ,* > ) => {
1046+ impl < $( $param) ,* > $crate:: binder_impl:: Serialize for $parcelable < $( $param) ,* > {
1047+ fn serialize(
1048+ & self ,
1049+ parcel: & mut $crate:: binder_impl:: BorrowedParcel <' _>,
1050+ ) -> std:: result:: Result <( ) , $crate:: StatusCode > {
1051+ <Self as $crate:: binder_impl:: SerializeOption >:: serialize_option( Some ( self ) , parcel)
1052+ }
1053+ }
1054+
1055+ impl < $( $param) ,* > $crate:: binder_impl:: SerializeArray for $parcelable < $( $param) ,* > { }
1056+
1057+ impl < $( $param) ,* > $crate:: binder_impl:: SerializeOption for $parcelable < $( $param) ,* > {
1058+ fn serialize_option(
1059+ this: Option <& Self >,
1060+ parcel: & mut $crate:: binder_impl:: BorrowedParcel <' _>,
1061+ ) -> std:: result:: Result <( ) , $crate:: StatusCode > {
1062+ if let Some ( this) = this {
1063+ use $crate:: binder_impl:: UnstructuredParcelable ;
1064+ parcel. write( & $crate:: binder_impl:: NON_NULL_PARCELABLE_FLAG ) ?;
1065+ this. write_to_parcel( parcel)
1066+ } else {
1067+ parcel. write( & $crate:: binder_impl:: NULL_PARCELABLE_FLAG )
1068+ }
1069+ }
1070+ }
1071+ } ;
1072+ }
1073+
1074+ /// Implement `Deserialize` trait and friends for an unstructured parcelable
1075+ ///
1076+ /// The target type must implement the `UnstructuredParcelable` trait.
1077+ #[ macro_export]
1078+ macro_rules! impl_deserialize_for_unstructured_parcelable {
1079+ ( $parcelable: ident) => {
1080+ $crate:: impl_deserialize_for_unstructured_parcelable!( $parcelable < >) ;
1081+ } ;
1082+ ( $parcelable: ident < $( $param: ident ) ,* , >) => {
1083+ $crate:: impl_deserialize_for_unstructured_parcelable!( $parcelable < $( $param) ,* >) ;
1084+ } ;
1085+ ( $parcelable: ident < $( $param: ident ) ,* > ) => {
1086+ impl < $( $param: Default ) ,* > $crate:: binder_impl:: Deserialize for $parcelable < $( $param) ,* > {
1087+ type UninitType = Option <Self >;
1088+ fn uninit( ) -> Self :: UninitType { None }
1089+ fn from_init( value: Self ) -> Self :: UninitType { Some ( value) }
1090+ fn deserialize(
1091+ parcel: & $crate:: binder_impl:: BorrowedParcel <' _>,
1092+ ) -> std:: result:: Result <Self , $crate:: StatusCode > {
1093+ $crate:: binder_impl:: DeserializeOption :: deserialize_option( parcel)
1094+ . transpose( )
1095+ . unwrap_or( Err ( $crate:: StatusCode :: UNEXPECTED_NULL ) )
1096+ }
1097+ fn deserialize_from(
1098+ & mut self ,
1099+ parcel: & $crate:: binder_impl:: BorrowedParcel <' _>,
1100+ ) -> std:: result:: Result <( ) , $crate:: StatusCode > {
1101+ let status: i32 = parcel. read( ) ?;
1102+ if status == $crate:: binder_impl:: NULL_PARCELABLE_FLAG {
1103+ Err ( $crate:: StatusCode :: UNEXPECTED_NULL )
1104+ } else {
1105+ use $crate:: binder_impl:: UnstructuredParcelable ;
1106+ self . read_from_parcel( parcel)
1107+ }
1108+ }
1109+ }
1110+
1111+ impl < $( $param: Default ) ,* > $crate:: binder_impl:: DeserializeArray for $parcelable < $( $param) ,* > { }
1112+
1113+ impl < $( $param: Default ) ,* > $crate:: binder_impl:: DeserializeOption for $parcelable < $( $param) ,* > {
1114+ fn deserialize_option(
1115+ parcel: & $crate:: binder_impl:: BorrowedParcel <' _>,
1116+ ) -> std:: result:: Result <Option <Self >, $crate:: StatusCode > {
1117+ let present: i32 = parcel. read( ) ?;
1118+ match present {
1119+ $crate:: binder_impl:: NULL_PARCELABLE_FLAG => Ok ( None ) ,
1120+ $crate:: binder_impl:: NON_NULL_PARCELABLE_FLAG => {
1121+ use $crate:: binder_impl:: UnstructuredParcelable ;
1122+ Ok ( Some ( Self :: from_parcel( parcel) ?) )
1123+ }
1124+ _ => Err ( StatusCode :: BAD_VALUE ) ,
1125+ }
1126+ }
1127+ fn deserialize_option_from(
1128+ this: & mut Option <Self >,
1129+ parcel: & $crate:: binder_impl:: BorrowedParcel <' _>,
1130+ ) -> std:: result:: Result <( ) , $crate:: StatusCode > {
1131+ let present: i32 = parcel. read( ) ?;
1132+ match present {
1133+ $crate:: binder_impl:: NULL_PARCELABLE_FLAG => {
1134+ * this = None ;
1135+ Ok ( ( ) )
1136+ }
1137+ $crate:: binder_impl:: NON_NULL_PARCELABLE_FLAG => {
1138+ use $crate:: binder_impl:: UnstructuredParcelable ;
1139+ if let Some ( this) = this {
1140+ this. read_from_parcel( parcel) ?;
1141+ } else {
1142+ * this = Some ( Self :: from_parcel( parcel) ?) ;
1143+ }
1144+ Ok ( ( ) )
1145+ }
1146+ _ => Err ( StatusCode :: BAD_VALUE ) ,
1147+ }
1148+ }
1149+ }
1150+ } ;
1151+ }
1152+
10051153impl < T : Serialize > Serialize for Box < T > {
10061154 fn serialize ( & self , parcel : & mut BorrowedParcel < ' _ > ) -> Result < ( ) > {
10071155 Serialize :: serialize ( & * * self , parcel)
0 commit comments