Skip to main content

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}