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}