use fidl::endpoints::{DiscoverableProtocolMarker, RequestStream, ServerEnd, ServiceRequest};
use fuchsia_async as fasync;
use std::marker::PhantomData;
pub trait Service {
type Output;
fn connect(&mut self, channel: zx::Channel) -> Option<Self::Output>;
}
impl<F, O> Service for F
where
F: FnMut(zx::Channel) -> Option<O>,
{
type Output = O;
fn connect(&mut self, channel: zx::Channel) -> Option<Self::Output> {
(self)(channel)
}
}
pub struct FidlService<F, RS, Output>
where
F: FnMut(RS) -> Output,
RS: RequestStream,
{
f: F,
marker: PhantomData<(RS, Output)>,
}
impl<F, RS, Output> From<F> for FidlService<F, RS, Output>
where
F: FnMut(RS) -> Output,
RS: RequestStream,
{
fn from(f: F) -> Self {
Self { f, marker: PhantomData }
}
}
impl<F, RS, Output> Service for FidlService<F, RS, Output>
where
F: FnMut(RS) -> Output,
RS: RequestStream,
{
type Output = Output;
fn connect(&mut self, channel: zx::Channel) -> Option<Self::Output> {
let chan = fasync::Channel::from_channel(channel);
Some((self.f)(RS::from_channel(chan)))
}
}
pub struct FidlServiceServerConnector<F, P, Output>
where
F: FnMut(ServerEnd<P>) -> Output,
P: DiscoverableProtocolMarker,
{
f: F,
marker: PhantomData<(P, Output)>,
}
impl<F, P, Output> From<F> for FidlServiceServerConnector<F, P, Output>
where
F: FnMut(ServerEnd<P>) -> Output,
P: DiscoverableProtocolMarker,
{
fn from(f: F) -> Self {
Self { f, marker: PhantomData }
}
}
impl<F, P, Output> Service for FidlServiceServerConnector<F, P, Output>
where
F: FnMut(ServerEnd<P>) -> Output,
P: DiscoverableProtocolMarker,
{
type Output = Output;
fn connect(&mut self, channel: zx::Channel) -> Option<Self::Output> {
let FidlServiceServerConnector { f, marker: _ } = self;
Some(f(ServerEnd::new(channel)))
}
}
pub struct FidlServiceMember<F, SR, Output>
where
F: FnMut(SR) -> Output,
SR: ServiceRequest,
{
f: F,
member: &'static str,
marker: PhantomData<(SR, Output)>,
}
impl<F, SR, Output> FidlServiceMember<F, SR, Output>
where
F: FnMut(SR) -> Output,
SR: ServiceRequest,
{
pub fn new(f: F, member: &'static str) -> Self {
Self { f, member, marker: PhantomData }
}
}
impl<F, SR, Output> Service for FidlServiceMember<F, SR, Output>
where
F: FnMut(SR) -> Output,
SR: ServiceRequest,
{
type Output = Output;
fn connect(&mut self, channel: zx::Channel) -> Option<Self::Output> {
let chan = fasync::Channel::from_channel(channel);
Some((self.f)(SR::dispatch(self.member, chan)))
}
}
pub struct ServiceObjLocal<'a, Output>(Box<dyn Service<Output = Output> + 'a>);
impl<'a, S: Service + 'a> From<S> for ServiceObjLocal<'a, S::Output> {
fn from(service: S) -> Self {
ServiceObjLocal(Box::new(service))
}
}
pub struct ServiceObj<'a, Output>(Box<dyn Service<Output = Output> + Send + 'a>);
impl<'a, S: Service + Send + 'a> From<S> for ServiceObj<'a, S::Output> {
fn from(service: S) -> Self {
ServiceObj(Box::new(service))
}
}
pub trait ServiceObjTrait {
type Output;
fn service(&mut self) -> &mut dyn Service<Output = Self::Output>;
}
impl<'a, Output> ServiceObjTrait for ServiceObjLocal<'a, Output> {
type Output = Output;
fn service(&mut self) -> &mut dyn Service<Output = Self::Output> {
&mut *self.0
}
}
impl<'a, Output> ServiceObjTrait for ServiceObj<'a, Output> {
type Output = Output;
fn service(&mut self) -> &mut dyn Service<Output = Self::Output> {
&mut *self.0
}
}