1 use super::{dealloc, Channel};
2 use core::fmt;
3 use core::mem;
4 use core::ptr::NonNull;
5 
6 /// An error returned when trying to send on a closed channel. Returned from
7 /// [`Sender::send`](crate::Sender::send) if the corresponding [`Receiver`](crate::Receiver)
8 /// has already been dropped.
9 ///
10 /// The message that could not be sent can be retreived again with [`SendError::into_inner`].
11 pub struct SendError<T> {
12     channel_ptr: NonNull<Channel<T>>,
13 }
14 
15 unsafe impl<T: Send> Send for SendError<T> {}
16 unsafe impl<T: Sync> Sync for SendError<T> {}
17 
18 impl<T> SendError<T> {
19     /// # Safety
20     ///
21     /// By calling this function, the caller semantically transfers ownership of the
22     /// channel's resources to the created `SendError`. Thus the caller must ensure that the
23     /// pointer is not used in a way which would violate this ownership transfer. Moreover,
24     /// the caller must assert that the channel contains a valid, initialized message.
new(channel_ptr: NonNull<Channel<T>>) -> Self25     pub(crate) const unsafe fn new(channel_ptr: NonNull<Channel<T>>) -> Self {
26         Self { channel_ptr }
27     }
28 
29     /// Consumes the error and returns the message that failed to be sent.
30     #[inline]
into_inner(self) -> T31     pub fn into_inner(self) -> T {
32         let channel_ptr = self.channel_ptr;
33 
34         // Don't run destructor if we consumed ourselves. Freeing happens here.
35         mem::forget(self);
36 
37         // SAFETY: we have ownership of the channel
38         let channel: &Channel<T> = unsafe { channel_ptr.as_ref() };
39 
40         // SAFETY: we know that the message is initialized according to the safety requirements of
41         // `new`
42         let message = unsafe { channel.take_message() };
43 
44         // SAFETY: we own the channel
45         unsafe { dealloc(channel_ptr) };
46 
47         message
48     }
49 
50     /// Get a reference to the message that failed to be sent.
51     #[inline]
as_inner(&self) -> &T52     pub fn as_inner(&self) -> &T {
53         unsafe { self.channel_ptr.as_ref().message().assume_init_ref() }
54     }
55 }
56 
57 impl<T> Drop for SendError<T> {
drop(&mut self)58     fn drop(&mut self) {
59         // SAFETY: we have ownership of the channel and require that the message is initialized
60         // upon construction
61         unsafe {
62             self.channel_ptr.as_ref().drop_message();
63             dealloc(self.channel_ptr);
64         }
65     }
66 }
67 
68 impl<T> fmt::Display for SendError<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result69     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70         "sending on a closed channel".fmt(f)
71     }
72 }
73 
74 impl<T> fmt::Debug for SendError<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result75     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76         write!(f, "SendError<{}>(_)", stringify!(T))
77     }
78 }
79 
80 #[cfg(feature = "std")]
81 impl<T> std::error::Error for SendError<T> {}
82 
83 /// An error returned from the blocking [`Receiver::recv`](crate::Receiver::recv) method.
84 ///
85 /// The receive operation can only fail if the corresponding [`Sender`](crate::Sender) was dropped
86 /// before sending any message, or if a message has already been sent and received on the channel.
87 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
88 pub struct RecvError;
89 
90 impl fmt::Display for RecvError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result91     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92         "receiving on a closed channel".fmt(f)
93     }
94 }
95 
96 #[cfg(feature = "std")]
97 impl std::error::Error for RecvError {}
98 
99 /// An error returned when failing to receive a message in the non-blocking
100 /// [`Receiver::try_recv`](crate::Receiver::try_recv).
101 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
102 pub enum TryRecvError {
103     /// The channel is still open, but there was no message present in it.
104     Empty,
105 
106     /// The channel is closed. Either the sender was dropped before sending any message, or the
107     /// message has already been extracted from the receiver.
108     Disconnected,
109 }
110 
111 impl fmt::Display for TryRecvError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result112     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113         let msg = match self {
114             TryRecvError::Empty => "receiving on an empty channel",
115             TryRecvError::Disconnected => "receiving on a closed channel",
116         };
117         msg.fmt(f)
118     }
119 }
120 
121 #[cfg(feature = "std")]
122 impl std::error::Error for TryRecvError {}
123 
124 /// An error returned when failing to receive a message in
125 /// [`Receiver::recv_timeout`](crate::Receiver::recv_timeout).
126 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
127 pub enum RecvTimeoutError {
128     /// No message arrived on the channel before the timeout was reached. The channel is still open.
129     Timeout,
130 
131     /// The channel is closed. Either the sender was dropped before sending any message, or the
132     /// message has already been extracted from the receiver.
133     Disconnected,
134 }
135 
136 impl fmt::Display for RecvTimeoutError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result137     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138         let msg = match self {
139             RecvTimeoutError::Timeout => "timed out waiting on channel",
140             RecvTimeoutError::Disconnected => "channel is empty and sending half is closed",
141         };
142         msg.fmt(f)
143     }
144 }
145 
146 #[cfg(feature = "std")]
147 impl std::error::Error for RecvTimeoutError {}
148