/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.48.0/src/io/ready.rs
Line | Count | Source |
1 | | #![cfg_attr(not(feature = "net"), allow(unreachable_pub))] |
2 | | |
3 | | use crate::io::interest::Interest; |
4 | | |
5 | | use std::fmt; |
6 | | use std::ops; |
7 | | |
8 | | const READABLE: usize = 0b0_01; |
9 | | const WRITABLE: usize = 0b0_10; |
10 | | const READ_CLOSED: usize = 0b0_0100; |
11 | | const WRITE_CLOSED: usize = 0b0_1000; |
12 | | #[cfg(any(target_os = "linux", target_os = "android"))] |
13 | | const PRIORITY: usize = 0b1_0000; |
14 | | const ERROR: usize = 0b10_0000; |
15 | | |
16 | | /// Describes the readiness state of an I/O resources. |
17 | | /// |
18 | | /// `Ready` tracks which operation an I/O resource is ready to perform. |
19 | | #[cfg_attr(docsrs, doc(cfg(feature = "net")))] |
20 | | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] |
21 | | pub struct Ready(usize); |
22 | | |
23 | | impl Ready { |
24 | | /// Returns the empty `Ready` set. |
25 | | pub const EMPTY: Ready = Ready(0); |
26 | | |
27 | | /// Returns a `Ready` representing readable readiness. |
28 | | pub const READABLE: Ready = Ready(READABLE); |
29 | | |
30 | | /// Returns a `Ready` representing writable readiness. |
31 | | pub const WRITABLE: Ready = Ready(WRITABLE); |
32 | | |
33 | | /// Returns a `Ready` representing read closed readiness. |
34 | | pub const READ_CLOSED: Ready = Ready(READ_CLOSED); |
35 | | |
36 | | /// Returns a `Ready` representing write closed readiness. |
37 | | pub const WRITE_CLOSED: Ready = Ready(WRITE_CLOSED); |
38 | | |
39 | | /// Returns a `Ready` representing priority readiness. |
40 | | #[cfg(any(target_os = "linux", target_os = "android"))] |
41 | | #[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "android"))))] |
42 | | pub const PRIORITY: Ready = Ready(PRIORITY); |
43 | | |
44 | | /// Returns a `Ready` representing error readiness. |
45 | | pub const ERROR: Ready = Ready(ERROR); |
46 | | |
47 | | /// Returns a `Ready` representing readiness for all operations. |
48 | | #[cfg(any(target_os = "linux", target_os = "android"))] |
49 | | pub const ALL: Ready = |
50 | | Ready(READABLE | WRITABLE | READ_CLOSED | WRITE_CLOSED | ERROR | PRIORITY); |
51 | | |
52 | | /// Returns a `Ready` representing readiness for all operations. |
53 | | #[cfg(not(any(target_os = "linux", target_os = "android")))] |
54 | | pub const ALL: Ready = Ready(READABLE | WRITABLE | READ_CLOSED | WRITE_CLOSED | ERROR); |
55 | | |
56 | | // Must remain crate-private to avoid adding a public dependency on Mio. |
57 | 0 | pub(crate) fn from_mio(event: &mio::event::Event) -> Ready { |
58 | 0 | let mut ready = Ready::EMPTY; |
59 | | |
60 | | #[cfg(all(target_os = "freebsd", feature = "net"))] |
61 | | { |
62 | | if event.is_aio() { |
63 | | ready |= Ready::READABLE; |
64 | | } |
65 | | |
66 | | if event.is_lio() { |
67 | | ready |= Ready::READABLE; |
68 | | } |
69 | | } |
70 | | |
71 | 0 | if event.is_readable() { |
72 | 0 | ready |= Ready::READABLE; |
73 | 0 | } |
74 | | |
75 | 0 | if event.is_writable() { |
76 | 0 | ready |= Ready::WRITABLE; |
77 | 0 | } |
78 | | |
79 | 0 | if event.is_read_closed() { |
80 | 0 | ready |= Ready::READ_CLOSED; |
81 | 0 | } |
82 | | |
83 | 0 | if event.is_write_closed() { |
84 | 0 | ready |= Ready::WRITE_CLOSED; |
85 | 0 | } |
86 | | |
87 | 0 | if event.is_error() { |
88 | 0 | ready |= Ready::ERROR; |
89 | 0 | } |
90 | | |
91 | | #[cfg(any(target_os = "linux", target_os = "android"))] |
92 | | { |
93 | 0 | if event.is_priority() { |
94 | 0 | ready |= Ready::PRIORITY; |
95 | 0 | } |
96 | | } |
97 | | |
98 | 0 | ready |
99 | 0 | } |
100 | | |
101 | | /// Returns true if `Ready` is the empty set. |
102 | | /// |
103 | | /// # Examples |
104 | | /// |
105 | | /// ``` |
106 | | /// use tokio::io::Ready; |
107 | | /// |
108 | | /// assert!(Ready::EMPTY.is_empty()); |
109 | | /// assert!(!Ready::READABLE.is_empty()); |
110 | | /// ``` |
111 | 0 | pub fn is_empty(self) -> bool { |
112 | 0 | self == Ready::EMPTY |
113 | 0 | } |
114 | | |
115 | | /// Returns `true` if the value includes `readable`. |
116 | | /// |
117 | | /// # Examples |
118 | | /// |
119 | | /// ``` |
120 | | /// use tokio::io::Ready; |
121 | | /// |
122 | | /// assert!(!Ready::EMPTY.is_readable()); |
123 | | /// assert!(Ready::READABLE.is_readable()); |
124 | | /// assert!(Ready::READ_CLOSED.is_readable()); |
125 | | /// assert!(!Ready::WRITABLE.is_readable()); |
126 | | /// ``` |
127 | 0 | pub fn is_readable(self) -> bool { |
128 | 0 | self.contains(Ready::READABLE) || self.is_read_closed() |
129 | 0 | } |
130 | | |
131 | | /// Returns `true` if the value includes writable `readiness`. |
132 | | /// |
133 | | /// # Examples |
134 | | /// |
135 | | /// ``` |
136 | | /// use tokio::io::Ready; |
137 | | /// |
138 | | /// assert!(!Ready::EMPTY.is_writable()); |
139 | | /// assert!(!Ready::READABLE.is_writable()); |
140 | | /// assert!(Ready::WRITABLE.is_writable()); |
141 | | /// assert!(Ready::WRITE_CLOSED.is_writable()); |
142 | | /// ``` |
143 | 0 | pub fn is_writable(self) -> bool { |
144 | 0 | self.contains(Ready::WRITABLE) || self.is_write_closed() |
145 | 0 | } |
146 | | |
147 | | /// Returns `true` if the value includes read-closed `readiness`. |
148 | | /// |
149 | | /// # Examples |
150 | | /// |
151 | | /// ``` |
152 | | /// use tokio::io::Ready; |
153 | | /// |
154 | | /// assert!(!Ready::EMPTY.is_read_closed()); |
155 | | /// assert!(!Ready::READABLE.is_read_closed()); |
156 | | /// assert!(Ready::READ_CLOSED.is_read_closed()); |
157 | | /// ``` |
158 | 0 | pub fn is_read_closed(self) -> bool { |
159 | 0 | self.contains(Ready::READ_CLOSED) |
160 | 0 | } |
161 | | |
162 | | /// Returns `true` if the value includes write-closed `readiness`. |
163 | | /// |
164 | | /// # Examples |
165 | | /// |
166 | | /// ``` |
167 | | /// use tokio::io::Ready; |
168 | | /// |
169 | | /// assert!(!Ready::EMPTY.is_write_closed()); |
170 | | /// assert!(!Ready::WRITABLE.is_write_closed()); |
171 | | /// assert!(Ready::WRITE_CLOSED.is_write_closed()); |
172 | | /// ``` |
173 | 0 | pub fn is_write_closed(self) -> bool { |
174 | 0 | self.contains(Ready::WRITE_CLOSED) |
175 | 0 | } |
176 | | |
177 | | /// Returns `true` if the value includes priority `readiness`. |
178 | | /// |
179 | | /// # Examples |
180 | | /// |
181 | | /// ``` |
182 | | /// use tokio::io::Ready; |
183 | | /// |
184 | | /// assert!(!Ready::EMPTY.is_priority()); |
185 | | /// assert!(!Ready::WRITABLE.is_priority()); |
186 | | /// assert!(Ready::PRIORITY.is_priority()); |
187 | | /// ``` |
188 | | #[cfg(any(target_os = "linux", target_os = "android"))] |
189 | | #[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "android"))))] |
190 | 0 | pub fn is_priority(self) -> bool { |
191 | 0 | self.contains(Ready::PRIORITY) |
192 | 0 | } |
193 | | |
194 | | /// Returns `true` if the value includes error `readiness`. |
195 | | /// |
196 | | /// # Examples |
197 | | /// |
198 | | /// ``` |
199 | | /// use tokio::io::Ready; |
200 | | /// |
201 | | /// assert!(!Ready::EMPTY.is_error()); |
202 | | /// assert!(!Ready::WRITABLE.is_error()); |
203 | | /// assert!(Ready::ERROR.is_error()); |
204 | | /// ``` |
205 | 0 | pub fn is_error(self) -> bool { |
206 | 0 | self.contains(Ready::ERROR) |
207 | 0 | } |
208 | | |
209 | | /// Returns true if `self` is a superset of `other`. |
210 | | /// |
211 | | /// `other` may represent more than one readiness operations, in which case |
212 | | /// the function only returns true if `self` contains all readiness |
213 | | /// specified in `other`. |
214 | 0 | pub(crate) fn contains<T: Into<Self>>(self, other: T) -> bool { |
215 | 0 | let other = other.into(); |
216 | 0 | (self & other) == other |
217 | 0 | } |
218 | | |
219 | | /// Creates a `Ready` instance using the given `usize` representation. |
220 | | /// |
221 | | /// The `usize` representation must have been obtained from a call to |
222 | | /// `Readiness::as_usize`. |
223 | | /// |
224 | | /// This function is mainly provided to allow the caller to get a |
225 | | /// readiness value from an `AtomicUsize`. |
226 | 0 | pub(crate) fn from_usize(val: usize) -> Ready { |
227 | 0 | Ready(val & Ready::ALL.as_usize()) |
228 | 0 | } |
229 | | |
230 | | /// Returns a `usize` representation of the `Ready` value. |
231 | | /// |
232 | | /// This function is mainly provided to allow the caller to store a |
233 | | /// readiness value in an `AtomicUsize`. |
234 | 0 | pub(crate) fn as_usize(self) -> usize { |
235 | 0 | self.0 |
236 | 0 | } |
237 | | |
238 | 0 | pub(crate) fn from_interest(interest: Interest) -> Ready { |
239 | 0 | let mut ready = Ready::EMPTY; |
240 | | |
241 | 0 | if interest.is_readable() { |
242 | 0 | ready |= Ready::READABLE; |
243 | 0 | ready |= Ready::READ_CLOSED; |
244 | 0 | } |
245 | | |
246 | 0 | if interest.is_writable() { |
247 | 0 | ready |= Ready::WRITABLE; |
248 | 0 | ready |= Ready::WRITE_CLOSED; |
249 | 0 | } |
250 | | |
251 | | #[cfg(any(target_os = "linux", target_os = "android"))] |
252 | 0 | if interest.is_priority() { |
253 | 0 | ready |= Ready::PRIORITY; |
254 | 0 | ready |= Ready::READ_CLOSED; |
255 | 0 | } |
256 | | |
257 | 0 | if interest.is_error() { |
258 | 0 | ready |= Ready::ERROR; |
259 | 0 | } |
260 | | |
261 | 0 | ready |
262 | 0 | } |
263 | | |
264 | 0 | pub(crate) fn intersection(self, interest: Interest) -> Ready { |
265 | 0 | Ready(self.0 & Ready::from_interest(interest).0) |
266 | 0 | } |
267 | | |
268 | 0 | pub(crate) fn satisfies(self, interest: Interest) -> bool { |
269 | 0 | self.0 & Ready::from_interest(interest).0 != 0 |
270 | 0 | } |
271 | | } |
272 | | |
273 | | impl ops::BitOr<Ready> for Ready { |
274 | | type Output = Ready; |
275 | | |
276 | | #[inline] |
277 | 0 | fn bitor(self, other: Ready) -> Ready { |
278 | 0 | Ready(self.0 | other.0) |
279 | 0 | } |
280 | | } |
281 | | |
282 | | impl ops::BitOrAssign<Ready> for Ready { |
283 | | #[inline] |
284 | 0 | fn bitor_assign(&mut self, other: Ready) { |
285 | 0 | self.0 |= other.0; |
286 | 0 | } |
287 | | } |
288 | | |
289 | | impl ops::BitAnd<Ready> for Ready { |
290 | | type Output = Ready; |
291 | | |
292 | | #[inline] |
293 | 0 | fn bitand(self, other: Ready) -> Ready { |
294 | 0 | Ready(self.0 & other.0) |
295 | 0 | } |
296 | | } |
297 | | |
298 | | impl ops::Sub<Ready> for Ready { |
299 | | type Output = Ready; |
300 | | |
301 | | #[inline] |
302 | 0 | fn sub(self, other: Ready) -> Ready { |
303 | 0 | Ready(self.0 & !other.0) |
304 | 0 | } |
305 | | } |
306 | | |
307 | | impl fmt::Debug for Ready { |
308 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
309 | 0 | let mut fmt = fmt.debug_struct("Ready"); |
310 | | |
311 | 0 | fmt.field("is_readable", &self.is_readable()) |
312 | 0 | .field("is_writable", &self.is_writable()) |
313 | 0 | .field("is_read_closed", &self.is_read_closed()) |
314 | 0 | .field("is_write_closed", &self.is_write_closed()) |
315 | 0 | .field("is_error", &self.is_error()); |
316 | | |
317 | | #[cfg(any(target_os = "linux", target_os = "android"))] |
318 | 0 | fmt.field("is_priority", &self.is_priority()); |
319 | | |
320 | 0 | fmt.finish() |
321 | 0 | } |
322 | | } |