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 {}