ez_tui/utils/channel.rs
1use crate::{Error, Result};
2use tokio::sync::mpsc;
3
4/// Creates a new unbounded channel of wrappers around [`mpsc::unbounded_channel()`] types to work explicitly with this crates [`Error`] and [`Result`]
5pub(crate) fn unbounded_channel<T>() -> (Sender<T>, Receiver<T>) {
6 let (tx, rx) = mpsc::unbounded_channel();
7 (Sender { inner: tx }, Receiver { inner: rx })
8}
9
10/// A wrapper around [`mpsc::UnboundedSender`] to work explicitly with this crates [`Error`] and [`Result`]
11#[derive(Clone, Debug)]
12pub struct Sender<T> {
13 /// The inner channel sender
14 inner: mpsc::UnboundedSender<T>,
15}
16
17impl<T> Sender<T> {
18 /// Send a message through the channel
19 ///
20 /// # Errors
21 /// Will return an [`Error::Fatal`] if the channel is closed
22 pub fn send(&self, msg: T) -> Result<()> {
23 self.inner
24 .send(msg)
25 .map_err(|err| Error::Fatal(format!("Communication channel closed: {err}")))
26 }
27}
28
29/// A wrapper around [`mpsc::UnboundedReceiver`] to work explicitly with this crates [`Error`] and [`Result`]
30#[derive(Debug)]
31pub struct Receiver<T> {
32 /// The inner channel receiver
33 inner: mpsc::UnboundedReceiver<T>,
34}
35
36impl<T> Receiver<T> {
37 /// Wait for the next message in the channel.
38 ///
39 /// # Errors
40 /// Will return an [`Error::Fatal`] if the channel is closed
41 pub async fn wait_next_message(&mut self) -> Result<T> {
42 self.inner
43 .recv()
44 .await
45 .ok_or(Error::Fatal("Communication channel closed".to_string()))
46 }
47}