#[cfg(feature = "async")]
#[macro_export]
macro_rules! __declare_binder_interface {
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
$(
pub trait $native_adapter {
fn as_sync(&self) -> &dyn $interface;
#[allow(dead_code)]
fn as_async(&self) -> &dyn $native_async;
}
pub struct $native(Box<dyn $native_adapter + Send + Sync + 'static>);
impl $native {
pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> {
struct Wrapper<T> {
_inner: T,
}
impl<T> $native_adapter for Wrapper<T>
where
T: $interface + Sync + Send + 'static,
{
fn as_sync(&self) -> &dyn $interface { &self._inner }
fn as_async(&self) -> &dyn $native_async {
unreachable!("{} doesn't support async interface.", stringify!($interface))
}
}
let binder = $crate::native::Binder::new_with_stability($native(Box::new(Wrapper {_inner: inner})), $stability);
$crate::Strong::new(Box::new(binder))
}
}
impl $crate::Remotable for $native {
fn descriptor() -> &'static str where Self: Sized {
$descriptor
}
fn on_transact(&self, code: $crate::TransactionCode, reader: &mut $crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> {
$on_transact(self.0.as_sync(), code, reader, reply)
}
fn on_dump(&self, _writer: &mut dyn std::io::Write, _args: &[String]) -> $crate::Result<()> {
self.0.as_sync().dump(_writer, _args)
}
}
)?
$(
impl<P: $crate::BinderAsyncPool> $crate::FromIBinder for dyn $async_interface<P> {
fn try_from(ibinder: $crate::SIBinder) -> std::result::Result<$crate::Strong<dyn $async_interface<P>>, $crate::StatusCode> {
match <$proxy as $crate::Proxy>::from_binder(ibinder.clone()) {
Some(proxy) => Ok($crate::Strong::new(Box::new(proxy))),
None => {
match $crate::native::Binder::<$native>::try_from(ibinder) {
Ok(native) => {
Ok($crate::Strong::new(Box::new(native.clone())))
}
Err(err) => Err(err),
}
}
}
}
}
impl<P: $crate::BinderAsyncPool> $crate::Serialize for dyn $async_interface<P> + '_ {
fn serialize(&self, parcel: &mut $crate::Parcel) -> std::result::Result<(), $crate::StatusCode> {
let binder = $crate::Interface::as_binder(self);
parcel.write(&binder)
}
}
impl<P: $crate::BinderAsyncPool> $crate::SerializeOption for dyn $async_interface<P> + '_ {
fn serialize_option(this: Option<&Self>, parcel: &mut $crate::Parcel) -> std::result::Result<(), $crate::StatusCode> {
parcel.write(&this.map($crate::Interface::as_binder))
}
}
impl<P: $crate::BinderAsyncPool> std::fmt::Debug for dyn $async_interface<P> + '_ {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad(stringify!($async_interface))
}
}
impl<P: $crate::BinderAsyncPool> $crate::ToAsyncInterface<P> for dyn $interface {
type Target = dyn $async_interface<P>;
}
impl<P: $crate::BinderAsyncPool> $crate::ToSyncInterface for dyn $async_interface<P> {
type Target = dyn $interface;
}
)?
};
}
#[cfg(not(feature = "async"))]
#[macro_export]
macro_rules! __declare_binder_interface {
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
pub struct $native(Box<dyn $interface + Send + Sync + 'static>);
impl $native {
pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> {
let binder = $crate::native::Binder::new_with_stability($native(Box::new(inner)), $stability);
$crate::Strong::new(Box::new(binder))
}
}
impl $crate::Remotable for $native {
fn descriptor() -> &'static str where Self: Sized {
$descriptor
}
fn on_transact(&self, code: $crate::TransactionCode, reader: &mut $crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> {
$on_transact(&*self.0, code, reader, reply)
}
fn on_dump(&self, _writer: &mut dyn std::io::Write, _args: &[String]) -> $crate::Result<()> {
self.0.dump(_writer, _args)
}
}
};
}
#[macro_export]
macro_rules! declare_binder_interface {
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident,
$(r#async: $async_interface:ident,)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {},
$(r#async: $async_interface,)?
stability: $crate::Stability::default(),
}
}
};
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident,
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {},
$(r#async: $async_interface,)?
stability: $stability,
}
}
};
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(r#async: $async_interface,)?
stability: $crate::Stability::default(),
}
}
};
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
@doc[concat!("A binder [`Remotable`]($crate::binder_impl::Remotable) that holds an [`", stringify!($interface), "`] object.")]
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
@doc[concat!("A binder [`Proxy`]($crate::binder_impl::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")]
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(r#async: $async_interface,)?
stability: $stability,
}
}
};
{
$interface:path[$descriptor:expr] {
@doc[$native_doc:expr]
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
@doc[$proxy_doc:expr]
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$( r#async: $async_interface:ident, )?
stability: $stability:expr,
}
} => {
#[doc = $proxy_doc]
pub struct $proxy {
binder: $crate::SIBinder,
$($fname: $fty,)*
}
impl $crate::Interface for $proxy {
fn as_binder(&self) -> $crate::SIBinder {
self.binder.clone()
}
}
impl $crate::Proxy for $proxy
where
$proxy: $interface,
{
fn descriptor() -> &'static str {
$descriptor
}
fn from_binder(binder: $crate::SIBinder) -> std::option::Option<Self> {
if binder.descriptor() != $descriptor {
return None
}
if let Some(_) = binder.as_proxy() {
Some(Self { binder, $($fname: $finit),* })
} else {
None
}
}
}
$crate::__declare_binder_interface!{
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(r#async: $async_interface,)?
stability: $stability,
}
}
impl $crate::FromIBinder for dyn $interface {
fn try_from(binder: $crate::SIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> {
match <$proxy as $crate::Proxy>::from_binder(binder.clone()) {
Some(proxy) => Ok($crate::Strong::new(Box::new(proxy))),
None => {
match $crate::native::Binder::<$native>::try_from(binder) {
Ok(native) => Ok($crate::Strong::new(Box::new(native.clone()))),
Err(err) => Err(err),
}
}
}
}
}
impl $crate::parcelable::Serialize for dyn $interface
where
dyn $interface: $crate::Interface
{
fn serialize(&self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
let binder = $crate::Interface::as_binder(self);
parcel.write(&binder)?;
Ok(())
}
}
impl $crate::parcelable::SerializeOption for dyn $interface {
fn serialize_option(this: Option<&Self>, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
parcel.write(&this.map($crate::Interface::as_binder))
}
}
impl std::fmt::Debug for dyn $interface + '_ {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad(stringify!($interface))
}
}
}
}
#[macro_export]
macro_rules! impl_serialize_for_parcelable {
($parcelable:ident) => {
impl $crate::Serialize for $parcelable {
fn serialize(&self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
<Self as $crate::SerializeOption>::serialize_option(Some(self), parcel)
}
}
impl $crate::SerializeArray for $parcelable {}
impl $crate::SerializeOption for $parcelable {
fn serialize_option(
this: Option<&Self>,
parcel: &mut $crate::Parcel,
) -> $crate::Result<()> {
if let Some(this) = this {
use $crate::Parcelable;
parcel.write(&$crate::NON_NULL_PARCELABLE_FLAG)?;
this.write_to_parcel(parcel)
} else {
parcel.write(&$crate::NULL_PARCELABLE_FLAG)
}
}
}
};
}
#[macro_export]
macro_rules! impl_deserialize_for_parcelable {
($parcelable:ident) => {
impl $crate::Deserialize for $parcelable {
fn deserialize(parcel: &mut $crate::Parcel) -> $crate::Result<Self> {
$crate::DeserializeOption::deserialize_option(parcel)
.transpose()
.unwrap_or(Err($crate::StatusCode::UnexpectedNull.into()))
}
fn deserialize_from(&mut self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
let status: i32 = parcel.read()?;
if status == $crate::NULL_PARCELABLE_FLAG {
Err($crate::StatusCode::UnexpectedNull.into())
} else {
use $crate::Parcelable;
self.read_from_parcel(parcel)
}
}
}
impl $crate::DeserializeArray for $parcelable {}
impl $crate::DeserializeOption for $parcelable {
fn deserialize_option(parcel: &mut $crate::Parcel) -> $crate::Result<Option<Self>> {
let mut result = None;
Self::deserialize_option_from(&mut result, parcel)?;
Ok(result)
}
fn deserialize_option_from(
this: &mut Option<Self>,
parcel: &mut $crate::Parcel,
) -> $crate::Result<()> {
let status: i32 = parcel.read()?;
if status == $crate::NULL_PARCELABLE_FLAG {
*this = None;
Ok(())
} else {
use $crate::Parcelable;
this.get_or_insert_with(Self::default)
.read_from_parcel(parcel)
}
}
}
};
}
#[macro_export]
macro_rules! declare_binder_enum {
{
$( #[$attr:meta] )*
$enum:ident : [$backing:ty; $size:expr] {
$( $( #[$value_attr:meta] )* $name:ident = $value:expr, )*
}
} => {
$( #[$attr] )*
#[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub struct $enum(pub $backing);
impl $enum {
$( $( #[$value_attr] )* #[allow(missing_docs)] pub const $name: Self = Self($value); )*
#[inline(always)]
#[allow(missing_docs)]
pub const fn enum_values() -> [Self; $size] {
[$(Self::$name),*]
}
}
impl $crate::Serialize for $enum {
fn serialize(&self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
parcel.write(&self.0)
}
}
impl $crate::SerializeArray for $enum {
fn serialize_array(slice: &[Self], parcel: &mut $crate::Parcel) -> $crate::Result<()> {
let v: Vec<$backing> = slice.iter().map(|x| x.0).collect();
<$backing as $crate::SerializeArray>::serialize_array(&v[..], parcel)
}
}
impl $crate::Deserialize for $enum {
fn deserialize(parcel: &mut $crate::Parcel) -> $crate::Result<Self> {
let res = parcel.read().map(Self);
res
}
}
impl $crate::DeserializeArray for $enum {
fn deserialize_array(parcel: &mut $crate::Parcel) -> $crate::Result<Option<Vec<Self>>> {
let v: Option<Vec<$backing>> =
<$backing as $crate::DeserializeArray>::deserialize_array(parcel)?;
Ok(v.map(|v| v.into_iter().map(Self).collect()))
}
}
};
}
#[cfg(test)]
mod tests {
use crate::{Binder, Interface, Parcel, Result, TransactionCode};
pub trait IEcho: Interface {
fn echo(&self, echo: &str) -> Result<String>;
}
pub trait IEchoAsyncService: Interface {
#[allow(dead_code)]
fn echo(&self, echo: &str) -> Result<String>;
}
declare_binder_interface! {
IEcho["my.echo"] {
native: {
BnEcho(on_transact),
adapter: BnEchoAdapter,
r#async: IEchoAsyncService,
},
proxy: BpEcho{},
}
}
#[allow(dead_code)]
impl IEcho for Binder<BnEcho> {
#[cfg(feature = "async")]
fn echo(&self, echo: &str) -> Result<String> {
self.0.as_sync().echo(echo)
}
#[cfg(not(feature = "async"))]
fn echo(&self, echo: &str) -> Result<String> {
self.0.echo(echo)
}
}
impl IEcho for BpEcho {
fn echo(&self, _echo: &str) -> Result<String> {
unimplemented!("BpEcho::echo")
}
}
fn on_transact(
_service: &dyn IEcho,
_code: TransactionCode,
_data: &mut Parcel,
_reply: &mut Parcel,
) -> Result<()> {
Ok(())
}
struct EchoService {}
impl Interface for EchoService {}
impl IEcho for EchoService {
fn echo(&self, echo: &str) -> Result<String> {
Ok(echo.to_owned())
}
}
#[test]
fn test_declare_binder_interface() {
let _ = BnEcho::new_binder(EchoService {});
}
#[cfg(feature = "async")]
#[test]
fn test_try_from() {
use async_trait::async_trait;
#[allow(dead_code)]
pub trait IEcho: Interface + Send {
fn echo(&self, echo: &str) -> crate::status::Result<String>;
}
pub trait IEchoAsync<P>: Interface + Send {
#[allow(dead_code)]
fn echo<'a>(
&'a self,
echo: &'a str,
) -> crate::BoxFuture<'a, crate::status::Result<String>>;
}
#[allow(dead_code)]
#[async_trait]
pub trait IEchoAsyncService: Interface + Send {
async fn echo(&self, echo: &str) -> crate::status::Result<String>;
}
pub struct BpEcho {
binder: crate::SIBinder,
}
impl IEcho for BpEcho {
fn echo(&self, _echo: &str) -> crate::status::Result<String> {
todo!()
}
}
impl<P: crate::BinderAsyncPool> IEchoAsync<P> for BpEcho {
fn echo<'a>(
&'a self,
_echo: &'a str,
) -> crate::BoxFuture<'a, crate::status::Result<String>> {
P::spawn(move || 0, |_| async move { Ok("".to_string()) })
}
}
impl Interface for BpEcho {
fn as_binder(&self) -> crate::SIBinder {
self.binder.clone()
}
}
impl crate::Proxy for BpEcho
where
BpEcho: IEcho,
{
fn descriptor() -> &'static str {
"my.echo"
}
fn from_binder(binder: crate::SIBinder) -> std::option::Option<Self> {
if binder.descriptor() != Self::descriptor() {
return None;
}
if binder.as_proxy().is_some() {
Some(Self { binder })
} else {
None
}
}
}
#[allow(dead_code)]
pub trait BnEchoAdapter: Send + Sync {
fn as_sync(&self) -> &dyn IEcho;
fn as_async(&self) -> &dyn IEchoAsyncService;
}
#[allow(dead_code)]
struct Wrapper<T, R> {
inner: T,
rt: R,
}
impl<T, R> Interface for Wrapper<T, R>
where
T: IEchoAsyncService + Sync + Send + 'static,
R: crate::BinderAsyncRuntime + Send + Sync + 'static,
{
fn as_binder(&self) -> crate::SIBinder {
self.inner.as_binder()
}
fn dump(&self, _writer: &mut dyn std::io::Write, _args: &[String]) -> Result<()> {
self.inner.dump(_writer, _args)
}
}
impl<T, R> IEcho for Wrapper<T, R>
where
T: IEchoAsyncService + Sync + Send + 'static,
R: crate::BinderAsyncRuntime + Send + Sync + 'static,
{
fn echo(&self, echo: &str) -> crate::status::Result<String> {
self.rt.block_on(self.inner.echo(echo))
}
}
impl<T, R> BnEchoAdapter for Wrapper<T, R>
where
T: IEchoAsyncService + Sync + Send + 'static,
R: crate::BinderAsyncRuntime + Send + Sync + 'static,
{
fn as_sync(&self) -> &dyn IEcho {
self
}
fn as_async(&self) -> &dyn IEchoAsyncService {
&self.inner
}
}
#[allow(dead_code)]
pub struct BnEcho(Box<dyn BnEchoAdapter>);
impl BnEcho {
pub fn new_binder<T, R>(inner: T, rt: R) -> crate::Strong<dyn IEcho>
where
T: IEchoAsyncService + Sync + Send + 'static,
R: crate::BinderAsyncRuntime + Send + Sync + 'static,
{
let bn = BnEcho(Box::new(Wrapper { inner, rt }));
let binder =
crate::native::Binder::new_with_stability(bn, crate::Stability::default());
crate::Strong::new(Box::new(binder))
}
}
impl crate::Remotable for BnEcho {
fn descriptor() -> &'static str
where
Self: Sized,
{
"my.echo"
}
fn on_transact(
&self,
_code: crate::TransactionCode,
_reader: &mut crate::Parcel,
_reply: &mut crate::Parcel,
) -> crate::Result<()> {
todo!()
}
fn on_dump(
&self,
_writer: &mut dyn std::io::Write,
_args: &[String],
) -> crate::Result<()> {
Ok(())
}
}
impl IEcho for crate::Binder<BnEcho> {
fn echo(&self, echo: &str) -> crate::status::Result<String> {
self.0.as_sync().echo(echo)
}
}
impl<P: crate::BinderAsyncPool> IEchoAsync<P> for crate::Binder<BnEcho> {
fn echo<'a>(
&'a self,
echo: &'a str,
) -> crate::BoxFuture<'a, crate::status::Result<String>> {
self.0.as_async().echo(echo)
}
}
impl crate::FromIBinder for dyn IEcho {
fn try_from(binder: crate::SIBinder) -> crate::Result<crate::Strong<dyn IEcho>> {
match <BpEcho as crate::Proxy>::from_binder(binder.clone()) {
Some(proxy) => Ok(crate::Strong::new(Box::new(proxy))),
None => match crate::native::Binder::<BnEcho>::try_from(binder) {
Ok(native) => Ok(crate::Strong::new(Box::new(native.clone()))),
Err(err) => Err(err),
},
}
}
}
impl<P: crate::BinderAsyncPool> crate::FromIBinder for dyn IEchoAsync<P> {
fn try_from(
binder: crate::SIBinder,
) -> crate::Result<crate::Strong<dyn IEchoAsync<P>>> {
match <BpEcho as crate::Proxy>::from_binder(binder.clone()) {
Some(proxy) => Ok(crate::Strong::new(Box::new(proxy))),
None => {
match crate::native::Binder::<BnEcho>::try_from(binder) {
Ok(native) => Ok(crate::Strong::new(Box::new(native.clone()))),
Err(err) => Err(err),
}
}
}
}
}
impl<P: crate::BinderAsyncPool> crate::ToAsyncInterface<P> for dyn IEcho {
type Target = dyn IEchoAsync<P>;
}
impl<P: crate::BinderAsyncPool> crate::ToSyncInterface for dyn IEchoAsync<P> {
type Target = dyn IEcho;
}
struct MyEcho {}
impl Interface for MyEcho {}
#[async_trait]
impl IEchoAsyncService for MyEcho {
async fn echo(&self, echo: &str) -> crate::status::Result<String> {
Ok(echo.to_owned())
}
}
struct MyRuntime {}
impl crate::BinderAsyncRuntime for MyRuntime {
fn block_on<F: std::future::Future>(&self, _future: F) -> F::Output {
todo!()
}
}
let _echo = BnEcho::new_binder(MyEcho {}, MyRuntime {});
}
}