use tokio::sync::mpsc;
#[derive(Clone, Debug)]
pub struct RequestSender<Req> {
req_tx: mpsc::Sender<Req>,
}
impl<Req> RequestSender<Req> {
pub fn new(req_tx: mpsc::Sender<Req>) -> Self {
Self { req_tx }
}
pub async fn send(&self, item: Req) -> Result<(), crate::error::Error>
where
Req: Send + Sync + 'static,
{
self.req_tx
.send(item)
.await
.map_err(crate::error::Error::io)
}
}
#[derive(Debug)]
pub struct ResponseReceiver<Resp> {
rx: mpsc::Receiver<crate::Result<Resp>>,
}
impl<Resp> ResponseReceiver<Resp> {
pub fn new(rx: mpsc::Receiver<crate::Result<Resp>>) -> Self {
Self { rx }
}
pub async fn recv(&mut self) -> Option<crate::Result<Resp>> {
self.rx.recv().await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_request_sender_and_response_receiver() {
let (req_tx, mut req_rx) = mpsc::channel::<String>(16);
let (resp_tx, resp_rx) = mpsc::channel::<crate::Result<String>>(16);
let sender = RequestSender::new(req_tx);
let mut receiver = ResponseReceiver::new(resp_rx);
sender.send("hello".to_string()).await.unwrap();
assert_eq!(req_rx.recv().await.unwrap(), "hello");
resp_tx.send(Ok("world".to_string())).await.unwrap();
assert_eq!(receiver.recv().await.unwrap().unwrap(), "world");
drop(resp_tx);
assert!(receiver.recv().await.is_none());
}
#[tokio::test]
async fn test_request_sender_send_error() {
use std::error::Error as _;
let (req_tx, req_rx) = mpsc::channel::<String>(16);
let sender = RequestSender::new(req_tx);
drop(req_rx);
let err = sender.send("hello".to_string()).await.unwrap_err();
assert!(err.is_io());
assert!(err.source().is_some());
}
}