1 use crate::backend::c; 2 use crate::backend::conv::borrowed_fd; 3 use crate::backend::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd}; 4 use bitflags::bitflags; 5 use core::marker::PhantomData; 6 #[cfg(windows)] 7 use { 8 crate::backend::fd::{AsSocket, RawFd}, 9 core::fmt, 10 }; 11 12 bitflags! { 13 /// `POLL*` flags for use with [`poll`]. 14 /// 15 /// [`poll`]: crate::event::poll 16 #[repr(transparent)] 17 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] 18 pub struct PollFlags: c::c_short { 19 /// `POLLIN` 20 const IN = c::POLLIN; 21 /// `POLLPRI` 22 #[cfg(not(target_os = "wasi"))] 23 const PRI = c::POLLPRI; 24 /// `POLLOUT` 25 const OUT = c::POLLOUT; 26 /// `POLLRDNORM` 27 const RDNORM = c::POLLRDNORM; 28 /// `POLLWRNORM` 29 #[cfg(not(target_os = "l4re"))] 30 const WRNORM = c::POLLWRNORM; 31 /// `POLLRDBAND` 32 #[cfg(not(any(target_os = "l4re", target_os = "wasi")))] 33 const RDBAND = c::POLLRDBAND; 34 /// `POLLWRBAND` 35 #[cfg(not(any(target_os = "l4re", target_os = "wasi")))] 36 const WRBAND = c::POLLWRBAND; 37 /// `POLLERR` 38 const ERR = c::POLLERR; 39 /// `POLLHUP` 40 const HUP = c::POLLHUP; 41 /// `POLLNVAL` 42 #[cfg(not(target_os = "espidf"))] 43 const NVAL = c::POLLNVAL; 44 /// `POLLRDHUP` 45 #[cfg(all( 46 linux_kernel, 47 not(any(target_arch = "sparc", target_arch = "sparc64"))), 48 )] 49 const RDHUP = c::POLLRDHUP; 50 51 /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> 52 const _ = !0; 53 } 54 } 55 56 /// `struct pollfd`—File descriptor and flags for use with [`poll`]. 57 /// 58 /// [`poll`]: crate::event::poll 59 #[doc(alias = "pollfd")] 60 #[derive(Clone)] 61 #[cfg_attr(not(windows), derive(Debug))] 62 #[repr(transparent)] 63 pub struct PollFd<'fd> { 64 pollfd: c::pollfd, 65 _phantom: PhantomData<BorrowedFd<'fd>>, 66 } 67 68 #[cfg(windows)] 69 impl<'fd> fmt::Debug for PollFd<'fd> { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result70 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 71 fmt.debug_struct("pollfd") 72 .field("fd", &self.pollfd.fd) 73 .field("events", &self.pollfd.events) 74 .field("revents", &self.pollfd.revents) 75 .finish() 76 } 77 } 78 79 impl<'fd> PollFd<'fd> { 80 /// Constructs a new `PollFd` holding `fd` and `events`. 81 #[inline] new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self82 pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self { 83 Self::from_borrowed_fd(fd.as_fd(), events) 84 } 85 86 /// Sets the contained file descriptor to `fd`. 87 #[inline] set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd)88 pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) { 89 self.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd; 90 } 91 92 /// Clears the ready events. 93 #[inline] clear_revents(&mut self)94 pub fn clear_revents(&mut self) { 95 self.pollfd.revents = 0; 96 } 97 98 /// Constructs a new `PollFd` holding `fd` and `events`. 99 /// 100 /// This is the same as `new`, but can be used to avoid borrowing the 101 /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd` 102 /// is a temporary. 103 #[inline] from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self104 pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self { 105 Self { 106 pollfd: c::pollfd { 107 fd: borrowed_fd(fd), 108 events: events.bits(), 109 revents: 0, 110 }, 111 _phantom: PhantomData, 112 } 113 } 114 115 /// Returns the ready events. 116 #[inline] revents(&self) -> PollFlags117 pub fn revents(&self) -> PollFlags { 118 // Use `.unwrap()` here because in theory we know we know all the bits 119 // the OS might set here, but OS's have added extensions in the past. 120 PollFlags::from_bits(self.pollfd.revents).unwrap() 121 } 122 } 123 124 #[cfg(not(windows))] 125 impl<'fd> AsFd for PollFd<'fd> { 126 #[inline] as_fd(&self) -> BorrowedFd<'_>127 fn as_fd(&self) -> BorrowedFd<'_> { 128 // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be 129 // valid for the `'fd` lifetime. 130 unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) } 131 } 132 } 133 134 #[cfg(windows)] 135 impl<'fd> AsSocket for PollFd<'fd> { 136 #[inline] as_socket(&self) -> BorrowedFd<'_>137 fn as_socket(&self) -> BorrowedFd<'_> { 138 // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be 139 // valid for the `'fd` lifetime. 140 unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) } 141 } 142 } 143