Skip to main content

rustix/backend/libc/event/
poll_fd.rs

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