1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use std::num::NonZeroU8; 15 16 /// The interested events, such as readable, writeable. 17 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)] 18 pub struct Interest(NonZeroU8); 19 use std::ops; 20 21 const READABLE: u8 = 0b0001; 22 const WRITABLE: u8 = 0b0010; 23 24 /// A wrapper that wraps around fd events 25 impl Interest { 26 /// An interest for readable events 27 pub const READABLE: Interest = Interest(unsafe { NonZeroU8::new_unchecked(READABLE) }); 28 /// An interest for writeable events 29 pub const WRITABLE: Interest = Interest(unsafe { NonZeroU8::new_unchecked(WRITABLE) }); 30 31 /// Combines two Interest into one. add(self, other: Interest) -> Interest32 pub const fn add(self, other: Interest) -> Interest { 33 Interest(unsafe { NonZeroU8::new_unchecked(self.0.get() | other.0.get()) }) 34 } 35 36 /// Checks if the interest is for readable events. is_readable(self) -> bool37 pub const fn is_readable(self) -> bool { 38 (self.0.get() & READABLE) != 0 39 } 40 41 /// Checks if the interest is for writeable events. is_writable(self) -> bool42 pub const fn is_writable(self) -> bool { 43 (self.0.get() & WRITABLE) != 0 44 } 45 46 /// Convert interest to the event value. 47 #[cfg(target_os = "linux")] into_io_event(self) -> libc::c_uint48 pub fn into_io_event(self) -> libc::c_uint { 49 let mut io_event = libc::EPOLLET as u32; 50 51 if self.is_readable() { 52 io_event |= libc::EPOLLIN as u32; 53 io_event |= libc::EPOLLRDHUP as u32; 54 } 55 56 if self.is_writable() { 57 io_event |= libc::EPOLLOUT as u32; 58 } 59 60 io_event as libc::c_uint 61 } 62 } 63 64 impl ops::BitOr for Interest { 65 type Output = Self; 66 67 #[inline] bitor(self, other: Self) -> Self68 fn bitor(self, other: Self) -> Self { 69 self.add(other) 70 } 71 } 72 73 #[cfg(test)] 74 mod test { 75 /// UT cases for `into_io_event`. 76 /// 77 /// # Brief 78 /// 1. Create different kinds of Interest 79 /// 2. Turn the Interest into IO Event 80 #[cfg(target_os = "linux")] 81 #[test] ut_interest_to_io_event()82 fn ut_interest_to_io_event() { 83 use std::num::NonZeroU8; 84 85 use libc::c_int; 86 87 use crate::Interest; 88 89 #[allow(clippy::init_numbered_fields)] 90 let interest = Interest { 91 0: NonZeroU8::new(4).unwrap(), 92 }; 93 let event = interest.into_io_event(); 94 assert_eq!(event as c_int, libc::EPOLLET); 95 96 let interest = Interest::READABLE; 97 let event = interest.into_io_event(); 98 assert_eq!( 99 event as c_int, 100 libc::EPOLLET | libc::EPOLLIN | libc::EPOLLRDHUP 101 ); 102 103 let interest = Interest::WRITABLE; 104 let event = interest.into_io_event(); 105 assert_eq!(event as c_int, libc::EPOLLET | libc::EPOLLOUT); 106 107 let interest = Interest::READABLE | Interest::WRITABLE; 108 let event = interest.into_io_event(); 109 assert_eq!( 110 event as c_int, 111 libc::EPOLLET | libc::EPOLLIN | libc::EPOLLRDHUP | libc::EPOLLOUT 112 ); 113 } 114 } 115