pub mod uri;
mod client;
mod server;
pub(crate) use client::{open_staged, OpenStage};
pub use client::{Client, ClientOptions};
#[cfg(feature = "rpc")]
pub use server::Authorizer;
pub use server::{ServeOptions, Server, ServerGuard};
pub use uri::{Endpoint, KernelEndpoint, Uri, UriError, UriErrorKind, WireProfile, WireVersion};
use crate::error::Result;
use crate::{FromIBinder, SIBinder, Strong};
pub fn serve(uri: impl Into<Uri>) -> Result<Server> {
server::new_server(uri.into())
}
pub fn connect<T: FromIBinder + ?Sized>(uri: impl Into<Uri>) -> Result<Strong<T>> {
FromIBinder::try_from(connect_binder(uri)?)
}
pub fn connect_binder(uri: impl Into<Uri>) -> Result<SIBinder> {
let (uri, name) = split_service(uri.into(), "rsbinder::connect")?;
client::new_client(uri, ClientOptions::default())?.binder(&name)
}
#[cfg(feature = "tokio")]
pub fn connect_async<T: FromIBinder + ?Sized + 'static>(
uri: impl Into<Uri>,
) -> impl std::future::Future<Output = Result<Strong<T>>> + 'static {
let uri = uri.into();
async move {
if crate::is_handling_transaction() {
return connect::<T>(uri);
}
if uri.endpoint.is_kernel() {
let (uri, name) = split_service(uri, "rsbinder::connect_async")?;
client::new_client(uri, ClientOptions::default())?;
return crate::wait_for_interface_async::<T>(&name).await;
}
tokio::task::spawn_blocking(move || connect::<T>(uri))
.await
.unwrap_or_else(|e| Err(crate::rt::join_error_status(e)))
}
}
fn split_service(mut uri: Uri, who: &str) -> Result<(Uri, String)> {
uri.validate()?;
let Some(name) = uri.service.take() else {
log::error!(
"{who}: no service in {uri} (use `Uri::with_service`, `#name` or `binder://name`)"
);
return Err(crate::StatusCode::BadValue);
};
Ok((uri, name))
}