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