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 = 0b0_001; 21 const WRITABLE: u8 = 0b0_010; 22 // The following are not available on all platforms. 23 #[cfg_attr( 24 not(any( 25 target_os = "dragonfly", 26 target_os = "freebsd", 27 target_os = "ios", 28 target_os = "macos" 29 )), 30 allow(dead_code) 31 )] 32 const AIO: u8 = 0b0_100; 33 #[cfg_attr(not(target_os = "freebsd"), allow(dead_code))] 34 const LIO: u8 = 0b1_000; 35 36 impl Interest { 37 /// Returns a `Interest` set representing readable interests. 38 pub const READABLE: Interest = Interest(unsafe { NonZeroU8::new_unchecked(READABLE) }); 39 40 /// Returns a `Interest` set representing writable interests. 41 pub const WRITABLE: Interest = Interest(unsafe { NonZeroU8::new_unchecked(WRITABLE) }); 42 43 /// Returns a `Interest` set representing AIO completion interests. 44 #[cfg(any( 45 target_os = "dragonfly", 46 target_os = "freebsd", 47 target_os = "ios", 48 target_os = "macos" 49 ))] 50 pub const AIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(AIO) }); 51 52 /// Returns a `Interest` set representing LIO completion interests. 53 #[cfg(target_os = "freebsd")] 54 pub const LIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(LIO) }); 55 56 /// Add together two `Interest`. 57 /// 58 /// This does the same thing as the `BitOr` implementation, but is a 59 /// constant function. 60 /// 61 /// ``` 62 /// use mio::Interest; 63 /// 64 /// const INTERESTS: Interest = Interest::READABLE.add(Interest::WRITABLE); 65 /// # fn silent_dead_code_warning(_: Interest) { } 66 /// # silent_dead_code_warning(INTERESTS) 67 /// ``` 68 #[allow(clippy::should_implement_trait)] add(self, other: Interest) -> Interest69 pub const fn add(self, other: Interest) -> Interest { 70 Interest(unsafe { NonZeroU8::new_unchecked(self.0.get() | other.0.get()) }) 71 } 72 73 /// Removes `other` `Interest` from `self`. 74 /// 75 /// Returns `None` if the set would be empty after removing `other`. 76 /// 77 /// ``` 78 /// use mio::Interest; 79 /// 80 /// const RW_INTERESTS: Interest = Interest::READABLE.add(Interest::WRITABLE); 81 /// 82 /// // As long a one interest remain this will return `Some`. 83 /// let w_interest = RW_INTERESTS.remove(Interest::READABLE).unwrap(); 84 /// assert!(!w_interest.is_readable()); 85 /// assert!(w_interest.is_writable()); 86 /// 87 /// // Removing all interests from the set will return `None`. 88 /// assert_eq!(w_interest.remove(Interest::WRITABLE), None); 89 /// 90 /// // Its also possible to remove multiple interests at once. 91 /// assert_eq!(RW_INTERESTS.remove(RW_INTERESTS), None); 92 /// ``` 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. is_readable(self) -> bool98 pub const fn is_readable(self) -> bool { 99 (self.0.get() & READABLE) != 0 100 } 101 102 /// Returns true if the value includes writable readiness. is_writable(self) -> bool103 pub const fn is_writable(self) -> bool { 104 (self.0.get() & WRITABLE) != 0 105 } 106 107 /// Returns true if `Interest` contains AIO readiness is_aio(self) -> bool108 pub const fn is_aio(self) -> bool { 109 (self.0.get() & AIO) != 0 110 } 111 112 /// Returns true if `Interest` contains LIO readiness is_lio(self) -> bool113 pub const fn is_lio(self) -> bool { 114 (self.0.get() & LIO) != 0 115 } 116 } 117 118 impl ops::BitOr for Interest { 119 type Output = Self; 120 121 #[inline] bitor(self, other: Self) -> Self122 fn bitor(self, other: Self) -> Self { 123 self.add(other) 124 } 125 } 126 127 impl ops::BitOrAssign for Interest { 128 #[inline] bitor_assign(&mut self, other: Self)129 fn bitor_assign(&mut self, other: Self) { 130 self.0 = (*self | other).0; 131 } 132 } 133 134 impl fmt::Debug for Interest { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result135 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 136 let mut one = false; 137 if self.is_readable() { 138 if one { 139 write!(fmt, " | ")? 140 } 141 write!(fmt, "READABLE")?; 142 one = true 143 } 144 if self.is_writable() { 145 if one { 146 write!(fmt, " | ")? 147 } 148 write!(fmt, "WRITABLE")?; 149 one = true 150 } 151 #[cfg(any( 152 target_os = "dragonfly", 153 target_os = "freebsd", 154 target_os = "ios", 155 target_os = "macos" 156 ))] 157 { 158 if self.is_aio() { 159 if one { 160 write!(fmt, " | ")? 161 } 162 write!(fmt, "AIO")?; 163 one = true 164 } 165 } 166 #[cfg(any(target_os = "freebsd"))] 167 { 168 if self.is_lio() { 169 if one { 170 write!(fmt, " | ")? 171 } 172 write!(fmt, "LIO")?; 173 one = true 174 } 175 } 176 debug_assert!(one, "printing empty interests"); 177 Ok(()) 178 } 179 } 180