use futures::FutureExt;
use serde::{Serialize, de::DeserializeOwned};
use std::{
fmt,
future::Future,
pin::Pin,
task::{Context, Poll, ready},
};
use super::mpsc;
use crate::{RemoteSend, codec, exec};
mod receiver;
mod sender;
pub use receiver::{Receiver, RecvError, TryRecvError};
pub use sender::{SendError, Sender};
pub fn channel<T, Codec>() -> (Sender<T, Codec>, Receiver<T, Codec>)
where
T: Serialize + DeserializeOwned + Send + 'static,
Codec: codec::Codec,
{
let (tx, rx) = mpsc::channel(1);
let tx = tx.set_buffer();
let rx = rx.set_buffer();
(Sender(tx), Receiver(rx))
}
pub fn forward<T, Codec>(local_rx: tokio::sync::oneshot::Receiver<T>) -> (Forwarding, Receiver<T, Codec>)
where
T: RemoteSend,
Codec: codec::Codec,
{
let (tx, rx) = channel();
let hnd = exec::spawn(async move {
tokio::select! {
biased;
() = tx.closed() => Ok(()),
res = local_rx => {
match res {
Ok(v) => match tx.send(v) {
Ok(_) => Ok(()),
Err(err) if err.is_closed() => Ok(()),
Err(err) => Err(err.without_item()),
},
Err(_) => Ok(()),
}
}
}
});
(Forwarding(hnd), rx)
}
pub struct Forwarding(exec::task::JoinHandle<Result<(), SendError<()>>>);
impl fmt::Debug for Forwarding {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Forwarding").finish()
}
}
impl Future for Forwarding {
type Output = Result<(), SendError<()>>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
match ready!(self.0.poll_unpin(cx)) {
Ok(res) => Poll::Ready(res),
Err(_) => Poll::Ready(Err(SendError::Closed(()))),
}
}
}
impl Forwarding {
pub fn stop(self) {
self.0.abort();
}
}
pub trait OneshotExt<T, Codec, const MAX_ITEM_SIZE: usize> {
fn with_max_item_size<const NEW_MAX_ITEM_SIZE: usize>(
self,
) -> (Sender<T, Codec>, Receiver<T, Codec, NEW_MAX_ITEM_SIZE>);
}
impl<T, Codec, const MAX_ITEM_SIZE: usize> OneshotExt<T, Codec, MAX_ITEM_SIZE>
for (Sender<T, Codec>, Receiver<T, Codec, MAX_ITEM_SIZE>)
where
T: RemoteSend,
Codec: codec::Codec,
{
fn with_max_item_size<const NEW_MAX_ITEM_SIZE: usize>(
self,
) -> (Sender<T, Codec>, Receiver<T, Codec, NEW_MAX_ITEM_SIZE>) {
let (mut tx, rx) = self;
tx.set_max_item_size(NEW_MAX_ITEM_SIZE);
let rx = rx.set_max_item_size();
(tx, rx)
}
}