oneshot/
errors.rs

1use super::{dealloc, Channel};
2use core::fmt;
3use core::mem;
4use 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`].
11pub struct SendError<T> {
12    channel_ptr: NonNull<Channel<T>>,
13}
14
15unsafe impl<T: Send> Send for SendError<T> {}
16unsafe impl<T: Sync> Sync for SendError<T> {}
17
18impl<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.
25    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]
31    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]
52    pub fn as_inner(&self) -> &T {
53        unsafe { self.channel_ptr.as_ref().message().assume_init_ref() }
54    }
55}
56
57impl<T> Drop for SendError<T> {
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
68impl<T> fmt::Display for SendError<T> {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        "sending on a closed channel".fmt(f)
71    }
72}
73
74impl<T> fmt::Debug for SendError<T> {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        write!(f, "SendError<{}>(_)", stringify!(T))
77    }
78}
79
80#[cfg(feature = "std")]
81impl<T> std::error::Error for SendError<T> {}
82
83/// An error returned from receiving methods that block/wait until a message is available.
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 received on the channel.
87#[cfg(any(feature = "std", feature = "async"))]
88#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
89pub struct RecvError;
90
91#[cfg(any(feature = "std", feature = "async"))]
92impl fmt::Display for RecvError {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        "receiving on a closed channel".fmt(f)
95    }
96}
97
98#[cfg(feature = "std")]
99impl std::error::Error for RecvError {}
100
101/// An error returned when failing to receive a message in the non-blocking
102/// [`Receiver::try_recv`](crate::Receiver::try_recv).
103#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
104pub enum TryRecvError {
105    /// The channel is still open, but there was no message present in it.
106    Empty,
107
108    /// The channel is closed. Either the sender was dropped before sending any message, or the
109    /// message has already been extracted from the receiver.
110    Disconnected,
111}
112
113impl fmt::Display for TryRecvError {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        let msg = match self {
116            TryRecvError::Empty => "receiving on an empty channel",
117            TryRecvError::Disconnected => "receiving on a closed channel",
118        };
119        msg.fmt(f)
120    }
121}
122
123#[cfg(feature = "std")]
124impl std::error::Error for TryRecvError {}
125
126/// An error returned when failing to receive a message in a method that block/wait for a message
127/// for a while, but has a timeout after which it gives up.
128#[cfg(feature = "std")]
129#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
130pub enum RecvTimeoutError {
131    /// No message arrived on the channel before the timeout was reached. The channel is still open.
132    Timeout,
133
134    /// The channel is closed. Either the sender was dropped before sending any message, or the
135    /// message has already been extracted from the receiver.
136    Disconnected,
137}
138
139#[cfg(feature = "std")]
140impl fmt::Display for RecvTimeoutError {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142        let msg = match self {
143            RecvTimeoutError::Timeout => "timed out waiting on channel",
144            RecvTimeoutError::Disconnected => "channel is empty and sending half is closed",
145        };
146        msg.fmt(f)
147    }
148}
149
150#[cfg(feature = "std")]
151impl std::error::Error for RecvTimeoutError {}