use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use crate::protocol::{self, DispatcherError, Transport};
use super::{ClientEnd, Method, ResponseBuffer};
pub struct Client<T: Transport, P> {
client: protocol::Client<T>,
_protocol: PhantomData<P>,
}
impl<T: Transport, P> Client<T, P> {
pub fn new(client_end: ClientEnd<T, P>) -> (Self, ClientDispatcher<T, P>) {
let (client, dispatcher) = protocol::Client::new(client_end.into_untyped());
(Self::from_untyped(client), ClientDispatcher::from_untyped(dispatcher))
}
pub fn from_untyped(client: protocol::Client<T>) -> Self {
Self { client, _protocol: PhantomData }
}
pub fn untyped(&self) -> &protocol::Client<T> {
&self.client
}
}
impl<T: Transport, P> Clone for Client<T, P> {
fn clone(&self) -> Self {
Self { client: self.client.clone(), _protocol: PhantomData }
}
}
pub trait ClientProtocol<T: Transport, H> {
fn on_event(handler: &mut H, ordinal: u64, buffer: T::RecvBuffer);
}
pub struct ClientAdapter<P, H> {
handler: H,
_protocol: PhantomData<P>,
}
impl<P, H> ClientAdapter<P, H> {
pub fn from_untyped(handler: H) -> Self {
Self { handler, _protocol: PhantomData }
}
}
impl<T, P, H> protocol::ClientHandler<T> for ClientAdapter<P, H>
where
T: Transport,
P: ClientProtocol<T, H>,
{
fn on_event(&mut self, ordinal: u64, buffer: T::RecvBuffer) {
P::on_event(&mut self.handler, ordinal, buffer)
}
}
pub struct ClientDispatcher<T: Transport, P> {
dispatcher: protocol::ClientDispatcher<T>,
_protocol: PhantomData<P>,
}
impl<T: Transport, P> ClientDispatcher<T, P> {
pub fn from_untyped(dispatcher: protocol::ClientDispatcher<T>) -> Self {
Self { dispatcher, _protocol: PhantomData }
}
pub async fn run<H>(&mut self, handler: H) -> Result<(), DispatcherError<T::Error>>
where
P: ClientProtocol<T, H>,
{
self.dispatcher.run(ClientAdapter { handler, _protocol: PhantomData::<P> }).await
}
}
pub struct TransactionFuture<'a, T: Transport, M> {
future: protocol::TransactionFuture<'a, T>,
_method: PhantomData<M>,
}
impl<'a, T: Transport, M> TransactionFuture<'a, T, M> {
pub fn from_untyped(future: protocol::TransactionFuture<'a, T>) -> Self {
Self { future, _method: PhantomData }
}
}
impl<T, M> Future for TransactionFuture<'_, T, M>
where
T: Transport,
M: Method,
{
type Output = Result<ResponseBuffer<T, M>, T::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let future = unsafe { self.map_unchecked_mut(|this| &mut this.future) };
future.poll(cx).map_ok(ResponseBuffer::from_untyped)
}
}