1 //! Helper traits to ease non-blocking handling.
2 
3 use std::{
4     io::{Error as IoError, ErrorKind as IoErrorKind},
5     result::Result as StdResult,
6 };
7 
8 use crate::error::Error;
9 
10 /// Non-blocking IO handling.
11 pub trait NonBlockingError: Sized {
12     /// Convert WouldBlock to None and don't touch other errors.
into_non_blocking(self) -> Option<Self>13     fn into_non_blocking(self) -> Option<Self>;
14 }
15 
16 impl NonBlockingError for IoError {
into_non_blocking(self) -> Option<Self>17     fn into_non_blocking(self) -> Option<Self> {
18         match self.kind() {
19             IoErrorKind::WouldBlock => None,
20             _ => Some(self),
21         }
22     }
23 }
24 
25 impl NonBlockingError for Error {
into_non_blocking(self) -> Option<Self>26     fn into_non_blocking(self) -> Option<Self> {
27         match self {
28             Error::Io(e) => e.into_non_blocking().map(|e| e.into()),
29             x => Some(x),
30         }
31     }
32 }
33 
34 /// Non-blocking IO wrapper.
35 ///
36 /// This trait is implemented for `Result<T, E: NonBlockingError>`.
37 pub trait NonBlockingResult {
38     /// Type of the converted result: `Result<Option<T>, E>`
39     type Result;
40     /// Perform the non-block conversion.
no_block(self) -> Self::Result41     fn no_block(self) -> Self::Result;
42 }
43 
44 impl<T, E> NonBlockingResult for StdResult<T, E>
45 where
46     E: NonBlockingError,
47 {
48     type Result = StdResult<Option<T>, E>;
no_block(self) -> Self::Result49     fn no_block(self) -> Self::Result {
50         match self {
51             Ok(x) => Ok(Some(x)),
52             Err(e) => match e.into_non_blocking() {
53                 Some(e) => Err(e),
54                 None => Ok(None),
55             },
56         }
57     }
58 }
59