use binder::binder_impl::BinderAsyncRuntime;
use binder::{BinderAsyncPool, BoxFuture, FromIBinder, StatusCode, Strong};
use std::future::Future;
pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(
name: &str,
) -> Result<Strong<T>, StatusCode> {
if binder::is_handling_transaction() {
return binder::get_interface::<T>(name);
}
let name = name.to_string();
let res = tokio::task::spawn_blocking(move || binder::get_interface::<T>(&name)).await;
match res {
Ok(Ok(service)) => Ok(service),
Ok(Err(err)) => Err(err),
Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION),
Err(_) => Err(StatusCode::UNKNOWN_ERROR),
}
}
pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(
name: &str,
) -> Result<Strong<T>, StatusCode> {
if binder::is_handling_transaction() {
return binder::wait_for_interface::<T>(name);
}
let name = name.to_string();
let res = tokio::task::spawn_blocking(move || binder::wait_for_interface::<T>(&name)).await;
match res {
Ok(Ok(service)) => Ok(service),
Ok(Err(err)) => Err(err),
Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION),
Err(_) => Err(StatusCode::UNKNOWN_ERROR),
}
}
pub enum Tokio {}
impl BinderAsyncPool for Tokio {
fn spawn<'a, F1, F2, Fut, A, B, E>(spawn_me: F1, after_spawn: F2) -> BoxFuture<'a, Result<B, E>>
where
F1: FnOnce() -> A,
F2: FnOnce(A) -> Fut,
Fut: Future<Output = Result<B, E>>,
F1: Send + 'static,
F2: Send + 'a,
Fut: Send + 'a,
A: Send + 'static,
B: Send + 'a,
E: From<crate::StatusCode>,
{
if binder::is_handling_transaction() {
let result = spawn_me();
Box::pin(after_spawn(result))
} else {
let handle = tokio::task::spawn_blocking(spawn_me);
Box::pin(async move {
match handle.await {
Ok(res) => after_spawn(res).await,
Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION.into()),
Err(_) => Err(StatusCode::UNKNOWN_ERROR.into()),
}
})
}
}
}
pub struct TokioRuntime<R>(pub R);
impl BinderAsyncRuntime for TokioRuntime<tokio::runtime::Runtime> {
fn block_on<F: Future>(&self, future: F) -> F::Output {
self.0.block_on(future)
}
}
impl BinderAsyncRuntime for TokioRuntime<std::sync::Arc<tokio::runtime::Runtime>> {
fn block_on<F: Future>(&self, future: F) -> F::Output {
self.0.block_on(future)
}
}
impl BinderAsyncRuntime for TokioRuntime<tokio::runtime::Handle> {
fn block_on<F: Future>(&self, future: F) -> F::Output {
self.0.block_on(future)
}
}