futures_net/driver/sys/linux/
ready.rs

1use crate::driver::sys::event::{ready_as_usize, ready_from_usize, Ready};
2
3use std::fmt;
4use std::ops;
5
6/// Unix specific extensions to `Ready`
7///
8/// Provides additional readiness event kinds that are available on unix
9/// platforms. Unix platforms are able to provide readiness events for
10/// additional socket events, such as HUP and error.
11///
12/// HUP events occur when the remote end of a socket hangs up. In the TCP case,
13/// this occurs when the remote end of a TCP socket shuts down writes.
14///
15/// Error events occur when the socket enters an error state. In this case, the
16/// socket will also receive a readable or writable event. Reading or writing to
17/// the socket will result in an error.
18///
19/// Conversion traits are implemented between `Ready` and `UnixReady`. See the
20/// examples.
21///
22/// For high level documentation on polling and readiness, see [`Poll`].
23///
24/// # Examples
25///
26/// Most of the time, all that is needed is using bit operations
27///
28/// ```
29/// use futures_net::driver::sys::event::Ready;
30/// use futures_net::driver::sys::UnixReady;
31///
32/// let ready = Ready::readable() | UnixReady::hup();
33///
34/// assert!(ready.is_readable());
35/// assert!(UnixReady::from(ready).is_hup());
36/// ```
37///
38/// Basic conversion between ready types.
39///
40/// ```
41/// use futures_net::driver::sys::event::Ready;
42/// use futures_net::driver::sys::UnixReady;
43///
44/// // Start with a portable ready
45/// let ready = Ready::readable();
46///
47/// // Convert to a unix ready, adding HUP
48/// let mut unix_ready = UnixReady::from(ready) | UnixReady::hup();
49///
50/// unix_ready.insert(UnixReady::error());
51///
52/// // `unix_ready` maintains readable interest
53/// assert!(unix_ready.is_readable());
54/// assert!(unix_ready.is_hup());
55/// assert!(unix_ready.is_error());
56///
57/// // Convert back to `Ready`
58/// let ready = Ready::from(unix_ready);
59///
60/// // Readable is maintained
61/// assert!(ready.is_readable());
62/// ```
63///
64/// Registering readable and error interest on a socket
65///
66/// ```
67/// # use std::error::Error;
68/// # fn try_main() -> Result<(), Box<Error>> {
69/// use futures_net::driver::sys::{Poll, Token};
70/// use futures_net::driver::sys::event::{Ready, PollOpt};
71/// use futures_net::driver::sys::net::TcpStream;
72/// use futures_net::driver::sys::UnixReady;
73///
74/// let addr = "216.58.193.68:80".parse()?;
75/// let socket = TcpStream::connect(&addr)?;
76///
77/// let poll = Poll::new()?;
78///
79/// poll.register(&socket,
80///               Token(0),
81///               Ready::readable() | UnixReady::error(),
82///               PollOpt::edge())?;
83/// #     Ok(())
84/// # }
85/// #
86/// # fn main() {
87/// #     try_main().unwrap();
88/// # }
89/// ```
90///
91/// [`Poll`]: ../struct.Poll.html
92/// [readiness]: struct.Poll.html#readiness-operations
93#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)]
94pub struct UnixReady(Ready);
95
96const ERROR: usize = 0b00_0100;
97const HUP: usize = 0b00_1000;
98
99const LIO: usize = 0b00_0000;
100
101const PRI: usize = 0b100_0000;
102
103// Export to support `Ready::all`
104pub const READY_ALL: usize = ERROR | HUP | LIO | PRI;
105
106#[test]
107fn test_ready_all() {
108    let readable = Ready::readable().as_usize();
109    let writable = Ready::writable().as_usize();
110
111    assert_eq!(
112        READY_ALL | readable | writable,
113        ERROR + HUP + LIO + PRI + readable + writable
114    );
115
116    assert!(!Ready::from(UnixReady::priority()).is_writable());
117}
118
119impl UnixReady {
120    /// Returns a `Ready` representing error readiness.
121    ///
122    /// **Note that only readable and writable readiness is guaranteed to be
123    /// supported on all platforms**. This means that `error` readiness
124    /// should be treated as a hint. For more details, see [readiness] in the
125    /// poll documentation.
126    ///
127    /// See [`Poll`] for more documentation on polling.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use futures_net::driver::sys::UnixReady;
133    ///
134    /// let ready = UnixReady::error();
135    ///
136    /// assert!(ready.is_error());
137    /// ```
138    ///
139    /// [`Poll`]: ../struct.Poll.html
140    /// [readiness]: ../struct.Poll.html#readiness-operations
141    #[inline]
142    pub fn error() -> UnixReady {
143        UnixReady(ready_from_usize(ERROR))
144    }
145
146    /// Returns a `Ready` representing HUP readiness.
147    ///
148    /// A HUP (or hang-up) signifies that a stream socket **peer** closed the
149    /// connection, or shut down the writing half of the connection.
150    ///
151    /// **Note that only readable and writable readiness is guaranteed to be
152    /// supported on all platforms**. This means that `hup` readiness
153    /// should be treated as a hint. For more details, see [readiness] in the
154    /// poll documentation. It is also unclear if HUP readiness will remain in 0.7. See
155    /// [here][issue-941].
156    ///
157    /// See [`Poll`] for more documentation on polling.
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// use futures_net::driver::sys::UnixReady;
163    ///
164    /// let ready = UnixReady::hup();
165    ///
166    /// assert!(ready.is_hup());
167    /// ```
168    ///
169    /// [`Poll`]: ../struct.Poll.html
170    /// [readiness]: ../struct.Poll.html#readiness-operations
171    #[inline]
172    pub fn hup() -> UnixReady {
173        UnixReady(ready_from_usize(HUP))
174    }
175
176    /// Returns a `Ready` representing priority (`EPOLLPRI`) readiness
177    ///
178    /// See [`Poll`] for more documentation on polling.
179    ///
180    /// # Examples
181    ///
182    /// ```
183    /// use futures_net::driver::sys::UnixReady;
184    ///
185    /// let ready = UnixReady::priority();
186    ///
187    /// assert!(ready.is_priority());
188    /// ```
189    ///
190    /// [`Poll`]: struct.Poll.html
191    pub fn priority() -> UnixReady {
192        UnixReady(ready_from_usize(PRI))
193    }
194
195    /// Returns true if the value includes error readiness
196    ///
197    /// **Note that only readable and writable readiness is guaranteed to be
198    /// supported on all platforms**. This means that `error` readiness should
199    /// be treated as a hint. For more details, see [readiness] in the poll
200    /// documentation.
201    ///
202    /// See [`Poll`] for more documentation on polling.
203    ///
204    /// # Examples
205    ///
206    /// ```
207    /// use futures_net::driver::sys::UnixReady;
208    ///
209    /// let ready = UnixReady::error();
210    ///
211    /// assert!(ready.is_error());
212    /// ```
213    ///
214    /// [`Poll`]: ../struct.Poll.html
215    /// [readiness]: ../struct.Poll.html#readiness-operations
216    #[inline]
217    pub fn is_error(&self) -> bool {
218        self.contains(ready_from_usize(ERROR))
219    }
220
221    /// Returns true if the value includes HUP readiness
222    ///
223    /// A HUP (or hang-up) signifies that a stream socket **peer** closed the
224    /// connection, or shut down the writing half of the connection.
225    ///
226    /// **Note that only readable and writable readiness is guaranteed to be
227    /// supported on all platforms**. This means that `hup` readiness
228    /// should be treated as a hint. For more details, see [readiness] in the
229    /// poll documentation.
230    ///
231    /// See [`Poll`] for more documentation on polling.
232    ///
233    /// # Examples
234    ///
235    /// ```
236    /// use futures_net::driver::sys::UnixReady;
237    ///
238    /// let ready = UnixReady::hup();
239    ///
240    /// assert!(ready.is_hup());
241    /// ```
242    ///
243    /// [`Poll`]: ../struct.Poll.html
244    /// [readiness]: ../struct.Poll.html#readiness-operations
245    #[inline]
246    pub fn is_hup(&self) -> bool {
247        self.contains(ready_from_usize(HUP))
248    }
249
250    /// Returns true if `Ready` contains priority (`EPOLLPRI`) readiness
251    ///
252    /// See [`Poll`] for more documentation on polling.
253    ///
254    /// # Examples
255    ///
256    /// ```
257    /// use futures_net::driver::sys::UnixReady;
258    ///
259    /// let ready = UnixReady::priority();
260    ///
261    /// assert!(ready.is_priority());
262    /// ```
263    ///
264    /// [`Poll`]: struct.Poll.html
265    #[inline]
266    pub fn is_priority(&self) -> bool {
267        self.contains(ready_from_usize(PRI))
268    }
269}
270
271impl From<Ready> for UnixReady {
272    fn from(src: Ready) -> UnixReady {
273        UnixReady(src)
274    }
275}
276
277impl From<UnixReady> for Ready {
278    fn from(src: UnixReady) -> Ready {
279        src.0
280    }
281}
282
283impl ops::Deref for UnixReady {
284    type Target = Ready;
285
286    fn deref(&self) -> &Ready {
287        &self.0
288    }
289}
290
291impl ops::DerefMut for UnixReady {
292    fn deref_mut(&mut self) -> &mut Ready {
293        &mut self.0
294    }
295}
296
297impl ops::BitOr for UnixReady {
298    type Output = UnixReady;
299
300    #[inline]
301    fn bitor(self, other: UnixReady) -> UnixReady {
302        (self.0 | other.0).into()
303    }
304}
305
306impl ops::BitXor for UnixReady {
307    type Output = UnixReady;
308
309    #[inline]
310    fn bitxor(self, other: UnixReady) -> UnixReady {
311        (self.0 ^ other.0).into()
312    }
313}
314
315impl ops::BitAnd for UnixReady {
316    type Output = UnixReady;
317
318    #[inline]
319    fn bitand(self, other: UnixReady) -> UnixReady {
320        (self.0 & other.0).into()
321    }
322}
323
324impl ops::Sub for UnixReady {
325    type Output = UnixReady;
326
327    #[inline]
328    fn sub(self, other: UnixReady) -> UnixReady {
329        ready_from_usize(ready_as_usize(self.0) & !ready_as_usize(other.0)).into()
330    }
331}
332
333#[doc(hidden)]
334impl ops::Not for UnixReady {
335    type Output = UnixReady;
336
337    #[inline]
338    fn not(self) -> UnixReady {
339        (!self.0).into()
340    }
341}
342
343impl fmt::Debug for UnixReady {
344    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
345        let mut one = false;
346        let flags = [
347            (UnixReady(Ready::readable()), "Readable"),
348            (UnixReady(Ready::writable()), "Writable"),
349            (UnixReady::error(), "Error"),
350            (UnixReady::hup(), "Hup"),
351            (UnixReady::priority(), "Priority"),
352        ];
353
354        for &(flag, msg) in &flags {
355            if self.contains(flag) {
356                if one {
357                    write!(fmt, " | ")?
358                }
359                write!(fmt, "{}", msg)?;
360
361                one = true
362            }
363        }
364
365        if !one {
366            fmt.write_str("(empty)")?;
367        }
368
369        Ok(())
370    }
371}