Skip to main content

nuclei/sync/mpsc/
error.rs

1//! Error types of the multi-producer, single-consumer channels.
2//!
3//! They carry the unsent value back to the caller, so a failed send never
4//! loses it, and their `Display` text is the established one.
5
6use core::fmt;
7use std::error::Error;
8
9/// Error returned by [`Sender::send`](super::Sender::send),
10/// [`UnboundedSender::send`](super::UnboundedSender::send) and the other sends
11/// that wait.
12///
13/// The channel is closed: the receiver was dropped or closed. The value that
14/// could not be sent is returned in the error.
15///
16/// ```
17/// use nuclei::sync::mpsc;
18///
19/// let (tx, rx) = mpsc::unbounded_channel();
20/// drop(rx);
21/// let err = tx.send("lost").unwrap_err();
22/// assert_eq!(err.0, "lost");
23/// assert_eq!(err.to_string(), "channel closed");
24/// ```
25#[derive(PartialEq, Eq, Clone, Copy)]
26pub struct SendError<T>(pub T);
27
28impl<T> fmt::Debug for SendError<T> {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        f.debug_struct("SendError").finish_non_exhaustive()
31    }
32}
33
34impl<T> fmt::Display for SendError<T> {
35    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
36        write!(fmt, "channel closed")
37    }
38}
39
40impl<T> Error for SendError<T> {}
41
42/// Error returned by [`Sender::try_send`](super::Sender::try_send) and the
43/// other sends and reservations that never wait.
44///
45/// ```
46/// use nuclei::sync::mpsc::{self, error::TrySendError};
47///
48/// let (tx, rx) = mpsc::channel(1);
49/// tx.try_send(1).unwrap();
50/// assert!(matches!(tx.try_send(2), Err(TrySendError::Full(2))));
51/// drop(rx);
52/// assert!(matches!(tx.try_send(3), Err(TrySendError::Closed(3))));
53/// ```
54#[derive(PartialEq, Eq, Clone, Copy)]
55pub enum TrySendError<T> {
56    /// The data could not be sent on the channel because the channel is
57    /// currently full and sending would require blocking.
58    Full(T),
59
60    /// The receive half of the channel was explicitly closed or has been
61    /// dropped.
62    Closed(T),
63}
64
65impl<T> TrySendError<T> {
66    /// Consume the `TrySendError`, returning the unsent value.
67    pub fn into_inner(self) -> T {
68        match self {
69            TrySendError::Full(val) => val,
70            TrySendError::Closed(val) => val,
71        }
72    }
73
74    /// The same refusal, carrying `value` in place of this one's.
75    pub(super) fn with_value<U>(self, value: U) -> TrySendError<U> {
76        match self {
77            TrySendError::Full(_) => TrySendError::Full(value),
78            TrySendError::Closed(_) => TrySendError::Closed(value),
79        }
80    }
81}
82
83impl<T> fmt::Debug for TrySendError<T> {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        match *self {
86            TrySendError::Full(..) => "Full(..)".fmt(f),
87            TrySendError::Closed(..) => "Closed(..)".fmt(f),
88        }
89    }
90}
91
92impl<T> fmt::Display for TrySendError<T> {
93    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
94        write!(
95            fmt,
96            "{}",
97            match self {
98                TrySendError::Full(..) => "no available capacity",
99                TrySendError::Closed(..) => "channel closed",
100            }
101        )
102    }
103}
104
105impl<T> Error for TrySendError<T> {}
106
107impl<T> From<SendError<T>> for TrySendError<T> {
108    fn from(src: SendError<T>) -> TrySendError<T> {
109        TrySendError::Closed(src.0)
110    }
111}
112
113/// Error returned by [`Sender::send_timeout`](super::Sender::send_timeout):
114/// the value was not sent, and comes back.
115#[derive(PartialEq, Eq, Clone, Copy)]
116pub enum SendTimeoutError<T> {
117    /// The channel stayed full until the timeout.
118    Timeout(T),
119
120    /// The receive half of the channel was explicitly closed or has been
121    /// dropped.
122    Closed(T),
123}
124
125impl<T> SendTimeoutError<T> {
126    /// Consume the `SendTimeoutError`, returning the unsent value.
127    pub fn into_inner(self) -> T {
128        match self {
129            SendTimeoutError::Timeout(val) => val,
130            SendTimeoutError::Closed(val) => val,
131        }
132    }
133}
134
135impl<T> fmt::Debug for SendTimeoutError<T> {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        match *self {
138            SendTimeoutError::Timeout(..) => "Timeout(..)".fmt(f),
139            SendTimeoutError::Closed(..) => "Closed(..)".fmt(f),
140        }
141    }
142}
143
144impl<T> fmt::Display for SendTimeoutError<T> {
145    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
146        fmt.write_str(match self {
147            SendTimeoutError::Timeout(..) => "timed out waiting on send operation",
148            SendTimeoutError::Closed(..) => "channel closed",
149        })
150    }
151}
152
153impl<T> Error for SendTimeoutError<T> {}
154
155/// Error returned by [`Receiver::try_recv`](super::Receiver::try_recv) and
156/// [`UnboundedReceiver::try_recv`](super::UnboundedReceiver::try_recv).
157///
158/// ```
159/// use nuclei::sync::mpsc::{self, error::TryRecvError};
160///
161/// let (tx, mut rx) = mpsc::unbounded_channel::<u8>();
162/// assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
163/// drop(tx);
164/// assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
165/// ```
166#[derive(PartialEq, Eq, Clone, Copy, Debug)]
167pub enum TryRecvError {
168    /// This **channel** is currently empty, but the **Sender**(s) have not yet
169    /// disconnected, so data may yet become available.
170    Empty,
171    /// The **channel**'s sending half has become disconnected, and there will
172    /// never be any more data received on it.
173    Disconnected,
174}
175
176impl fmt::Display for TryRecvError {
177    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
178        match *self {
179            TryRecvError::Empty => "receiving on an empty channel".fmt(fmt),
180            TryRecvError::Disconnected => "receiving on a closed channel".fmt(fmt),
181        }
182    }
183}
184
185impl Error for TryRecvError {}