use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use crate::protocol::{self, ProtocolError, Transport};
use super::{ClientEnd, Method, ResponseBuffer};
#[repr(transparent)]
pub struct ClientSender<T: Transport, P> {
sender: protocol::ClientSender<T>,
_protocol: PhantomData<P>,
}
impl<T: Transport, P> ClientSender<T, P> {
pub fn wrap_untyped(client: &protocol::ClientSender<T>) -> &Self {
unsafe { &*(client as *const protocol::ClientSender<T>).cast() }
}
pub fn as_untyped(&self) -> &protocol::ClientSender<T> {
&self.sender
}
pub fn close(&self) {
self.as_untyped().close();
}
}
impl<T: Transport, P> Clone for ClientSender<T, P> {
fn clone(&self) -> Self {
Self { sender: self.sender.clone(), _protocol: PhantomData }
}
}
pub trait ClientProtocol<T: Transport, H>: Sized {
fn on_event(
handler: &mut H,
sender: &ClientSender<T, Self>,
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,
sender: &protocol::ClientSender<T>,
ordinal: u64,
buffer: T::RecvBuffer,
) {
P::on_event(&mut self.handler, ClientSender::wrap_untyped(sender), ordinal, buffer)
}
}
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 {
Self { client: protocol::Client::new(client_end.into_untyped()), _protocol: PhantomData }
}
pub fn sender(&self) -> &ClientSender<T, P> {
ClientSender::wrap_untyped(self.client.sender())
}
pub fn from_untyped(client: protocol::Client<T>) -> Self {
Self { client, _protocol: PhantomData }
}
pub async fn run<H>(&mut self, handler: H) -> Result<(), ProtocolError<T::Error>>
where
P: ClientProtocol<T, H>,
{
self.client.run(ClientAdapter { handler, _protocol: PhantomData::<P> }).await
}
}
pub struct ResponseFuture<'a, T: Transport, M> {
future: protocol::ResponseFuture<'a, T>,
_method: PhantomData<M>,
}
impl<'a, T: Transport, M> ResponseFuture<'a, T, M> {
pub fn from_untyped(future: protocol::ResponseFuture<'a, T>) -> Self {
Self { future, _method: PhantomData }
}
}
impl<T, M> Future for ResponseFuture<'_, 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)
}
}