1 #![cfg_attr(not(feature = "net"), allow(unreachable_pub))]
2 
3 use std::fmt;
4 use std::ops;
5 
6 const READABLE: usize = 0b0_01;
7 const WRITABLE: usize = 0b0_10;
8 const READ_CLOSED: usize = 0b0_0100;
9 const WRITE_CLOSED: usize = 0b0_1000;
10 
11 /// Describes the readiness state of an I/O resources.
12 ///
13 /// `Ready` tracks which operation an I/O resource is ready to perform.
14 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
15 #[derive(Clone, Copy, PartialEq, PartialOrd)]
16 pub struct Ready(usize);
17 
18 impl Ready {
19     /// Returns the empty `Ready` set.
20     pub const EMPTY: Ready = Ready(0);
21 
22     /// Returns a `Ready` representing readable readiness.
23     pub const READABLE: Ready = Ready(READABLE);
24 
25     /// Returns a `Ready` representing writable readiness.
26     pub const WRITABLE: Ready = Ready(WRITABLE);
27 
28     /// Returns a `Ready` representing read closed readiness.
29     pub const READ_CLOSED: Ready = Ready(READ_CLOSED);
30 
31     /// Returns a `Ready` representing write closed readiness.
32     pub const WRITE_CLOSED: Ready = Ready(WRITE_CLOSED);
33 
34     /// Returns a `Ready` representing readiness for all operations.
35     pub const ALL: Ready = Ready(READABLE | WRITABLE | READ_CLOSED | WRITE_CLOSED);
36 
37     // Must remain crate-private to avoid adding a public dependency on Mio.
from_mio(event: &mio::event::Event) -> Ready38     pub(crate) fn from_mio(event: &mio::event::Event) -> Ready {
39         let mut ready = Ready::EMPTY;
40 
41         if event.is_readable() {
42             ready |= Ready::READABLE;
43         }
44 
45         if event.is_writable() {
46             ready |= Ready::WRITABLE;
47         }
48 
49         if event.is_read_closed() {
50             ready |= Ready::READ_CLOSED;
51         }
52 
53         if event.is_write_closed() {
54             ready |= Ready::WRITE_CLOSED;
55         }
56 
57         ready
58     }
59 
60     /// Returns true if `Ready` is the empty set
61     ///
62     /// # Examples
63     ///
64     /// ```
65     /// use tokio::io::Ready;
66     ///
67     /// assert!(Ready::EMPTY.is_empty());
68     /// assert!(!Ready::READABLE.is_empty());
69     /// ```
is_empty(self) -> bool70     pub fn is_empty(self) -> bool {
71         self == Ready::EMPTY
72     }
73 
74     /// Returns `true` if the value includes `readable`
75     ///
76     /// # Examples
77     ///
78     /// ```
79     /// use tokio::io::Ready;
80     ///
81     /// assert!(!Ready::EMPTY.is_readable());
82     /// assert!(Ready::READABLE.is_readable());
83     /// assert!(Ready::READ_CLOSED.is_readable());
84     /// assert!(!Ready::WRITABLE.is_readable());
85     /// ```
is_readable(self) -> bool86     pub fn is_readable(self) -> bool {
87         self.contains(Ready::READABLE) || self.is_read_closed()
88     }
89 
90     /// Returns `true` if the value includes writable `readiness`
91     ///
92     /// # Examples
93     ///
94     /// ```
95     /// use tokio::io::Ready;
96     ///
97     /// assert!(!Ready::EMPTY.is_writable());
98     /// assert!(!Ready::READABLE.is_writable());
99     /// assert!(Ready::WRITABLE.is_writable());
100     /// assert!(Ready::WRITE_CLOSED.is_writable());
101     /// ```
is_writable(self) -> bool102     pub fn is_writable(self) -> bool {
103         self.contains(Ready::WRITABLE) || self.is_write_closed()
104     }
105 
106     /// Returns `true` if the value includes read-closed `readiness`
107     ///
108     /// # Examples
109     ///
110     /// ```
111     /// use tokio::io::Ready;
112     ///
113     /// assert!(!Ready::EMPTY.is_read_closed());
114     /// assert!(!Ready::READABLE.is_read_closed());
115     /// assert!(Ready::READ_CLOSED.is_read_closed());
116     /// ```
is_read_closed(self) -> bool117     pub fn is_read_closed(self) -> bool {
118         self.contains(Ready::READ_CLOSED)
119     }
120 
121     /// Returns `true` if the value includes write-closed `readiness`
122     ///
123     /// # Examples
124     ///
125     /// ```
126     /// use tokio::io::Ready;
127     ///
128     /// assert!(!Ready::EMPTY.is_write_closed());
129     /// assert!(!Ready::WRITABLE.is_write_closed());
130     /// assert!(Ready::WRITE_CLOSED.is_write_closed());
131     /// ```
is_write_closed(self) -> bool132     pub fn is_write_closed(self) -> bool {
133         self.contains(Ready::WRITE_CLOSED)
134     }
135 
136     /// Returns true if `self` is a superset of `other`.
137     ///
138     /// `other` may represent more than one readiness operations, in which case
139     /// the function only returns true if `self` contains all readiness
140     /// specified in `other`.
contains<T: Into<Self>>(self, other: T) -> bool141     pub(crate) fn contains<T: Into<Self>>(self, other: T) -> bool {
142         let other = other.into();
143         (self & other) == other
144     }
145 
146     /// Create a `Ready` instance using the given `usize` representation.
147     ///
148     /// The `usize` representation must have been obtained from a call to
149     /// `Readiness::as_usize`.
150     ///
151     /// This function is mainly provided to allow the caller to get a
152     /// readiness value from an `AtomicUsize`.
from_usize(val: usize) -> Ready153     pub(crate) fn from_usize(val: usize) -> Ready {
154         Ready(val & Ready::ALL.as_usize())
155     }
156 
157     /// Returns a `usize` representation of the `Ready` value.
158     ///
159     /// This function is mainly provided to allow the caller to store a
160     /// readiness value in an `AtomicUsize`.
as_usize(self) -> usize161     pub(crate) fn as_usize(self) -> usize {
162         self.0
163     }
164 }
165 
166 cfg_io_readiness! {
167     use crate::io::Interest;
168 
169     impl Ready {
170         pub(crate) fn from_interest(interest: Interest) -> Ready {
171             let mut ready = Ready::EMPTY;
172 
173             if interest.is_readable() {
174                 ready |= Ready::READABLE;
175                 ready |= Ready::READ_CLOSED;
176             }
177 
178             if interest.is_writable() {
179                 ready |= Ready::WRITABLE;
180                 ready |= Ready::WRITE_CLOSED;
181             }
182 
183             ready
184         }
185 
186         pub(crate) fn intersection(self, interest: Interest) -> Ready {
187             Ready(self.0 & Ready::from_interest(interest).0)
188         }
189 
190         pub(crate) fn satisfies(self, interest: Interest) -> bool {
191             self.0 & Ready::from_interest(interest).0 != 0
192         }
193     }
194 }
195 
196 impl ops::BitOr<Ready> for Ready {
197     type Output = Ready;
198 
199     #[inline]
bitor(self, other: Ready) -> Ready200     fn bitor(self, other: Ready) -> Ready {
201         Ready(self.0 | other.0)
202     }
203 }
204 
205 impl ops::BitOrAssign<Ready> for Ready {
206     #[inline]
bitor_assign(&mut self, other: Ready)207     fn bitor_assign(&mut self, other: Ready) {
208         self.0 |= other.0;
209     }
210 }
211 
212 impl ops::BitAnd<Ready> for Ready {
213     type Output = Ready;
214 
215     #[inline]
bitand(self, other: Ready) -> Ready216     fn bitand(self, other: Ready) -> Ready {
217         Ready(self.0 & other.0)
218     }
219 }
220 
221 impl ops::Sub<Ready> for Ready {
222     type Output = Ready;
223 
224     #[inline]
sub(self, other: Ready) -> Ready225     fn sub(self, other: Ready) -> Ready {
226         Ready(self.0 & !other.0)
227     }
228 }
229 
230 impl fmt::Debug for Ready {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result231     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
232         fmt.debug_struct("Ready")
233             .field("is_readable", &self.is_readable())
234             .field("is_writable", &self.is_writable())
235             .field("is_read_closed", &self.is_read_closed())
236             .field("is_write_closed", &self.is_write_closed())
237             .finish()
238     }
239 }
240