Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/io/interest.rs
Line
Count
Source
1
#![cfg_attr(not(feature = "net"), allow(dead_code, unreachable_pub))]
2
3
use crate::io::ready::Ready;
4
5
use std::fmt;
6
use std::ops;
7
8
// These must be unique.
9
// same as mio
10
const READABLE: usize = 0b0001;
11
const WRITABLE: usize = 0b0010;
12
// The following are not available on all platforms.
13
#[cfg(target_os = "freebsd")]
14
const AIO: usize = 0b0100;
15
#[cfg(target_os = "freebsd")]
16
const LIO: usize = 0b1000;
17
#[cfg(any(target_os = "linux", target_os = "android"))]
18
const PRIORITY: usize = 0b0001_0000;
19
// error is available on all platforms, but behavior is platform-specific
20
// mio does not have this interest
21
const ERROR: usize = 0b0010_0000;
22
23
/// Readiness event interest.
24
///
25
/// Specifies the readiness events the caller is interested in when awaiting on
26
/// I/O resource readiness states.
27
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
28
#[derive(Clone, Copy, Eq, PartialEq)]
29
pub struct Interest(usize);
30
31
impl Interest {
32
    // The non-FreeBSD definitions in this block are active only when
33
    // building documentation.
34
    cfg_aio! {
35
        /// Interest for POSIX AIO.
36
        #[cfg(target_os = "freebsd")]
37
        pub const AIO: Interest = Interest(AIO);
38
39
        /// Interest for POSIX AIO.
40
        #[cfg(not(target_os = "freebsd"))]
41
        pub const AIO: Interest = Interest(READABLE);
42
43
        /// Interest for POSIX AIO `lio_listio` events.
44
        #[cfg(target_os = "freebsd")]
45
        pub const LIO: Interest = Interest(LIO);
46
47
        /// Interest for POSIX AIO `lio_listio` events.
48
        #[cfg(not(target_os = "freebsd"))]
49
        pub const LIO: Interest = Interest(READABLE);
50
    }
51
52
    /// Interest in all readable events.
53
    ///
54
    /// Readable interest includes read-closed events.
55
    pub const READABLE: Interest = Interest(READABLE);
56
57
    /// Interest in all writable events.
58
    ///
59
    /// Writable interest includes write-closed events.
60
    pub const WRITABLE: Interest = Interest(WRITABLE);
61
62
    /// Interest in error events.
63
    ///
64
    /// Passes error interest to the underlying OS selector.
65
    /// Behavior is platform-specific, read your platform's documentation.
66
    pub const ERROR: Interest = Interest(ERROR);
67
68
    /// Returns a `Interest` set representing priority completion interests.
69
    #[cfg(any(target_os = "linux", target_os = "android"))]
70
    #[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "android"))))]
71
    pub const PRIORITY: Interest = Interest(PRIORITY);
72
73
    /// Returns true if the value includes readable interest.
74
    ///
75
    /// # Examples
76
    ///
77
    /// ```
78
    /// use tokio::io::Interest;
79
    ///
80
    /// assert!(Interest::READABLE.is_readable());
81
    /// assert!(!Interest::WRITABLE.is_readable());
82
    ///
83
    /// let both = Interest::READABLE | Interest::WRITABLE;
84
    /// assert!(both.is_readable());
85
    /// ```
86
0
    pub const fn is_readable(self) -> bool {
87
0
        self.0 & READABLE != 0
88
0
    }
89
90
    /// Returns true if the value includes writable interest.
91
    ///
92
    /// # Examples
93
    ///
94
    /// ```
95
    /// use tokio::io::Interest;
96
    ///
97
    /// assert!(!Interest::READABLE.is_writable());
98
    /// assert!(Interest::WRITABLE.is_writable());
99
    ///
100
    /// let both = Interest::READABLE | Interest::WRITABLE;
101
    /// assert!(both.is_writable());
102
    /// ```
103
0
    pub const fn is_writable(self) -> bool {
104
0
        self.0 & WRITABLE != 0
105
0
    }
106
107
    /// Returns true if the value includes error interest.
108
    ///
109
    /// # Examples
110
    ///
111
    /// ```
112
    /// use tokio::io::Interest;
113
    ///
114
    /// assert!(Interest::ERROR.is_error());
115
    /// assert!(!Interest::WRITABLE.is_error());
116
    ///
117
    /// let combined = Interest::READABLE | Interest::ERROR;
118
    /// assert!(combined.is_error());
119
    /// ```
120
0
    pub const fn is_error(self) -> bool {
121
0
        self.0 & ERROR != 0
122
0
    }
123
124
    #[cfg(target_os = "freebsd")]
125
    const fn is_aio(self) -> bool {
126
        self.0 & AIO != 0
127
    }
128
129
    #[cfg(target_os = "freebsd")]
130
    const fn is_lio(self) -> bool {
131
        self.0 & LIO != 0
132
    }
133
134
    /// Returns true if the value includes priority interest.
135
    ///
136
    /// # Examples
137
    ///
138
    /// ```
139
    /// use tokio::io::Interest;
140
    ///
141
    /// assert!(!Interest::READABLE.is_priority());
142
    /// assert!(Interest::PRIORITY.is_priority());
143
    ///
144
    /// let both = Interest::READABLE | Interest::PRIORITY;
145
    /// assert!(both.is_priority());
146
    /// ```
147
    #[cfg(any(target_os = "linux", target_os = "android"))]
148
    #[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "android"))))]
149
0
    pub const fn is_priority(self) -> bool {
150
0
        self.0 & PRIORITY != 0
151
0
    }
152
153
    /// Add together two `Interest` values.
154
    ///
155
    /// This function works from a `const` context.
156
    ///
157
    /// # Examples
158
    ///
159
    /// ```
160
    /// use tokio::io::Interest;
161
    ///
162
    /// const BOTH: Interest = Interest::READABLE.add(Interest::WRITABLE);
163
    ///
164
    /// assert!(BOTH.is_readable());
165
    /// assert!(BOTH.is_writable());
166
    #[must_use = "this returns the result of the operation, without modifying the original"]
167
0
    pub const fn add(self, other: Interest) -> Interest {
168
0
        Self(self.0 | other.0)
169
0
    }
170
171
    /// Remove `Interest` from `self`.
172
    ///
173
    /// Interests present in `other` but *not* in `self` are ignored.
174
    ///
175
    /// Returns `None` if the set would be empty after removing `Interest`.
176
    ///
177
    /// # Examples
178
    ///
179
    /// ```
180
    /// use tokio::io::Interest;
181
    ///
182
    /// const RW_INTEREST: Interest = Interest::READABLE.add(Interest::WRITABLE);
183
    ///
184
    /// let w_interest = RW_INTEREST.remove(Interest::READABLE).unwrap();
185
    /// assert!(!w_interest.is_readable());
186
    /// assert!(w_interest.is_writable());
187
    ///
188
    /// // Removing all interests from the set returns `None`.
189
    /// assert_eq!(w_interest.remove(Interest::WRITABLE), None);
190
    ///
191
    /// // Remove all interests at once.
192
    /// assert_eq!(RW_INTEREST.remove(RW_INTEREST), None);
193
    /// ```
194
    #[must_use = "this returns the result of the operation, without modifying the original"]
195
0
    pub fn remove(self, other: Interest) -> Option<Interest> {
196
0
        let value = self.0 & !other.0;
197
198
0
        if value != 0 {
199
0
            Some(Self(value))
200
        } else {
201
0
            None
202
        }
203
0
    }
204
205
    // This function must be crate-private to avoid exposing a `mio` dependency.
206
0
    pub(crate) fn to_mio(self) -> mio::Interest {
207
0
        fn mio_add(wrapped: &mut Option<mio::Interest>, add: mio::Interest) {
208
0
            match wrapped {
209
0
                Some(inner) => *inner |= add,
210
0
                None => *wrapped = Some(add),
211
            }
212
0
        }
213
214
        // mio does not allow and empty interest, so use None for empty
215
0
        let mut mio = None;
216
217
0
        if self.is_readable() {
218
0
            mio_add(&mut mio, mio::Interest::READABLE);
219
0
        }
220
221
0
        if self.is_writable() {
222
0
            mio_add(&mut mio, mio::Interest::WRITABLE);
223
0
        }
224
225
        #[cfg(any(target_os = "linux", target_os = "android"))]
226
0
        if self.is_priority() {
227
0
            mio_add(&mut mio, mio::Interest::PRIORITY);
228
0
        }
229
230
        #[cfg(target_os = "freebsd")]
231
        if self.is_aio() {
232
            mio_add(&mut mio, mio::Interest::AIO);
233
        }
234
235
        #[cfg(target_os = "freebsd")]
236
        if self.is_lio() {
237
            mio_add(&mut mio, mio::Interest::LIO);
238
        }
239
240
0
        if self.is_error() {
241
0
            // There is no error interest in mio, because error events are always reported.
242
0
            // But mio interests cannot be empty and an interest is needed just for the registration.
243
0
            //
244
0
            // read readiness is filtered out in `Interest::mask` or `Ready::from_interest` if
245
0
            // the read interest was not specified by the user.
246
0
            mio_add(&mut mio, mio::Interest::READABLE);
247
0
        }
248
249
        // the default `mio::Interest::READABLE` should never be used in practice. Either
250
        //
251
        // - at least one tokio interest with a mio counterpart was used
252
        // - only the error tokio interest was specified
253
        //
254
        // in both cases, `mio` is Some already
255
0
        mio.unwrap_or(mio::Interest::READABLE)
256
0
    }
257
258
0
    pub(crate) fn mask(self) -> Ready {
259
0
        match self {
260
0
            Interest::READABLE => Ready::READABLE | Ready::READ_CLOSED,
261
0
            Interest::WRITABLE => Ready::WRITABLE | Ready::WRITE_CLOSED,
262
            #[cfg(any(target_os = "linux", target_os = "android"))]
263
0
            Interest::PRIORITY => Ready::PRIORITY | Ready::READ_CLOSED,
264
0
            Interest::ERROR => Ready::ERROR,
265
0
            _ => Ready::EMPTY,
266
        }
267
0
    }
268
}
269
270
impl ops::BitOr for Interest {
271
    type Output = Self;
272
273
    #[inline]
274
0
    fn bitor(self, other: Self) -> Self {
275
0
        self.add(other)
276
0
    }
277
}
278
279
impl ops::BitOrAssign for Interest {
280
    #[inline]
281
0
    fn bitor_assign(&mut self, other: Self) {
282
0
        *self = *self | other;
283
0
    }
284
}
285
286
impl fmt::Debug for Interest {
287
0
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
288
0
        let mut separator = false;
289
290
0
        if self.is_readable() {
291
0
            if separator {
292
0
                write!(fmt, " | ")?;
293
0
            }
294
0
            write!(fmt, "READABLE")?;
295
0
            separator = true;
296
0
        }
297
298
0
        if self.is_writable() {
299
0
            if separator {
300
0
                write!(fmt, " | ")?;
301
0
            }
302
0
            write!(fmt, "WRITABLE")?;
303
0
            separator = true;
304
0
        }
305
306
        #[cfg(any(target_os = "linux", target_os = "android"))]
307
0
        if self.is_priority() {
308
0
            if separator {
309
0
                write!(fmt, " | ")?;
310
0
            }
311
0
            write!(fmt, "PRIORITY")?;
312
0
            separator = true;
313
0
        }
314
315
        #[cfg(target_os = "freebsd")]
316
        if self.is_aio() {
317
            if separator {
318
                write!(fmt, " | ")?;
319
            }
320
            write!(fmt, "AIO")?;
321
            separator = true;
322
        }
323
324
        #[cfg(target_os = "freebsd")]
325
        if self.is_lio() {
326
            if separator {
327
                write!(fmt, " | ")?;
328
            }
329
            write!(fmt, "LIO")?;
330
            separator = true;
331
        }
332
333
0
        if self.is_error() {
334
0
            if separator {
335
0
                write!(fmt, " | ")?;
336
0
            }
337
0
            write!(fmt, "ERROR")?;
338
0
            separator = true;
339
0
        }
340
341
0
        let _ = separator;
342
343
0
        Ok(())
344
0
    }
345
}