1 use std::num::NonZeroU8; 2 use std::{fmt, ops}; 3 4 /// Interest used in registering. 5 /// 6 /// Interest are used in [registering] [`event::Source`]s with [`Poll`], they 7 /// indicate what readiness should be monitored for. For example if a socket is 8 /// registered with [readable] interests and the socket becomes writable, no 9 /// event will be returned from a call to [`poll`]. 10 /// 11 /// [registering]: struct.Registry.html#method.register 12 /// [`event::Source`]: ./event/trait.Source.html 13 /// [`Poll`]: struct.Poll.html 14 /// [readable]: struct.Interest.html#associatedconstant.READABLE 15 /// [`poll`]: struct.Poll.html#method.poll 16 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)] 17 pub struct Interest(NonZeroU8); 18 19 // These must be unique. 20 const READABLE: u8 = 0b0001; 21 const WRITABLE: u8 = 0b0010; 22 // The following are not available on all platforms. 23 const AIO: u8 = 0b0100; 24 const LIO: u8 = 0b1000; 25 const PRIORITY: u8 = 0b10000; 26 27 impl Interest { 28 /// Returns a `Interest` set representing readable interests. 29 pub const READABLE: Interest = Interest(unsafe { NonZeroU8::new_unchecked(READABLE) }); 30 31 /// Returns a `Interest` set representing writable interests. 32 pub const WRITABLE: Interest = Interest(unsafe { NonZeroU8::new_unchecked(WRITABLE) }); 33 34 /// Returns a `Interest` set representing AIO completion interests. 35 #[cfg(any( 36 target_os = "dragonfly", 37 target_os = "freebsd", 38 target_os = "ios", 39 target_os = "macos", 40 target_os = "tvos", 41 target_os = "visionos", 42 target_os = "watchos", 43 ))] 44 pub const AIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(AIO) }); 45 46 /// Returns a `Interest` set representing LIO completion interests. 47 #[cfg(target_os = "freebsd")] 48 pub const LIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(LIO) }); 49 50 /// Returns a `Interest` set representing priority completion interests. 51 #[cfg(any(target_os = "linux", target_os = "android"))] 52 pub const PRIORITY: Interest = Interest(unsafe { NonZeroU8::new_unchecked(PRIORITY) }); 53 54 /// Add together two `Interest`. 55 /// 56 /// This does the same thing as the `BitOr` implementation, but is a 57 /// constant function. 58 /// 59 /// ``` 60 /// use mio::Interest; 61 /// 62 /// const INTERESTS: Interest = Interest::READABLE.add(Interest::WRITABLE); 63 /// # fn silent_dead_code_warning(_: Interest) { } 64 /// # silent_dead_code_warning(INTERESTS) 65 /// ``` 66 #[allow(clippy::should_implement_trait)] 67 #[must_use = "this returns the result of the operation, without modifying the original"] add(self, other: Interest) -> Interest68 pub const fn add(self, other: Interest) -> Interest { 69 Interest(unsafe { NonZeroU8::new_unchecked(self.0.get() | other.0.get()) }) 70 } 71 72 /// Removes `other` `Interest` from `self`. 73 /// 74 /// Returns `None` if the set would be empty after removing `other`. 75 /// 76 /// ``` 77 /// use mio::Interest; 78 /// 79 /// const RW_INTERESTS: Interest = Interest::READABLE.add(Interest::WRITABLE); 80 /// 81 /// // As long a one interest remain this will return `Some`. 82 /// let w_interest = RW_INTERESTS.remove(Interest::READABLE).unwrap(); 83 /// assert!(!w_interest.is_readable()); 84 /// assert!(w_interest.is_writable()); 85 /// 86 /// // Removing all interests from the set will return `None`. 87 /// assert_eq!(w_interest.remove(Interest::WRITABLE), None); 88 /// 89 /// // Its also possible to remove multiple interests at once. 90 /// assert_eq!(RW_INTERESTS.remove(RW_INTERESTS), None); 91 /// ``` 92 #[must_use = "this returns the result of the operation, without modifying the original"] remove(self, other: Interest) -> Option<Interest>93 pub fn remove(self, other: Interest) -> Option<Interest> { 94 NonZeroU8::new(self.0.get() & !other.0.get()).map(Interest) 95 } 96 97 /// Returns true if the value includes readable readiness. 98 #[must_use] is_readable(self) -> bool99 pub const fn is_readable(self) -> bool { 100 (self.0.get() & READABLE) != 0 101 } 102 103 /// Returns true if the value includes writable readiness. 104 #[must_use] is_writable(self) -> bool105 pub const fn is_writable(self) -> bool { 106 (self.0.get() & WRITABLE) != 0 107 } 108 109 /// Returns true if `Interest` contains AIO readiness. 110 #[must_use] is_aio(self) -> bool111 pub const fn is_aio(self) -> bool { 112 (self.0.get() & AIO) != 0 113 } 114 115 /// Returns true if `Interest` contains LIO readiness. 116 #[must_use] is_lio(self) -> bool117 pub const fn is_lio(self) -> bool { 118 (self.0.get() & LIO) != 0 119 } 120 121 /// Returns true if `Interest` contains priority readiness. 122 #[must_use] is_priority(self) -> bool123 pub const fn is_priority(self) -> bool { 124 (self.0.get() & PRIORITY) != 0 125 } 126 } 127 128 impl ops::BitOr for Interest { 129 type Output = Self; 130 131 #[inline] bitor(self, other: Self) -> Self132 fn bitor(self, other: Self) -> Self { 133 self.add(other) 134 } 135 } 136 137 impl ops::BitOrAssign for Interest { 138 #[inline] bitor_assign(&mut self, other: Self)139 fn bitor_assign(&mut self, other: Self) { 140 self.0 = (*self | other).0; 141 } 142 } 143 144 impl fmt::Debug for Interest { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result145 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 146 let mut one = false; 147 if self.is_readable() { 148 if one { 149 write!(fmt, " | ")? 150 } 151 write!(fmt, "READABLE")?; 152 one = true 153 } 154 if self.is_writable() { 155 if one { 156 write!(fmt, " | ")? 157 } 158 write!(fmt, "WRITABLE")?; 159 one = true 160 } 161 #[cfg(any( 162 target_os = "dragonfly", 163 target_os = "freebsd", 164 target_os = "ios", 165 target_os = "macos", 166 target_os = "tvos", 167 target_os = "visionos", 168 target_os = "watchos", 169 ))] 170 { 171 if self.is_aio() { 172 if one { 173 write!(fmt, " | ")? 174 } 175 write!(fmt, "AIO")?; 176 one = true 177 } 178 } 179 #[cfg(target_os = "freebsd")] 180 { 181 if self.is_lio() { 182 if one { 183 write!(fmt, " | ")? 184 } 185 write!(fmt, "LIO")?; 186 one = true 187 } 188 } 189 #[cfg(any(target_os = "linux", target_os = "android"))] 190 { 191 if self.is_priority() { 192 if one { 193 write!(fmt, " | ")? 194 } 195 write!(fmt, "PRIORITY")?; 196 one = true 197 } 198 } 199 debug_assert!(one, "printing empty interests"); 200 Ok(()) 201 } 202 } 203