1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use super::super::c;
use super::super::conv::borrowed_fd;
#[cfg(windows)]
use super::super::fd::RawFd;
use super::super::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd};
use bitflags::bitflags;
use core::marker::PhantomData;
#[cfg(windows)]
use std::fmt;

bitflags! {
    /// `POLL*` flags for use with [`poll`].
    ///
    /// [`poll`]: crate::io::poll
    pub struct PollFlags: c::c_short {
        /// `POLLIN`
        const IN = c::POLLIN;
        /// `POLLPRI`
        #[cfg(not(target_os = "wasi"))]
        const PRI = c::POLLPRI;
        /// `POLLOUT`
        const OUT = c::POLLOUT;
        /// `POLLRDNORM`
        #[cfg(not(target_os = "redox"))]
        const RDNORM = c::POLLRDNORM;
        /// `POLLWRNORM`
        #[cfg(not(target_os = "redox"))]
        const WRNORM = c::POLLWRNORM;
        /// `POLLRDBAND`
        #[cfg(not(any(target_os = "redox", target_os = "wasi")))]
        const RDBAND = c::POLLRDBAND;
        /// `POLLWRBAND`
        #[cfg(not(any(target_os = "redox", target_os = "wasi")))]
        const WRBAND = c::POLLWRBAND;
        /// `POLLERR`
        const ERR = c::POLLERR;
        /// `POLLHUP`
        const HUP = c::POLLHUP;
        /// `POLLNVAL`
        const NVAL = c::POLLNVAL;
        /// `POLLRDHUP`
        #[cfg(all(
            any(target_os = "android", target_os = "linux"),
            not(any(target_arch = "sparc", target_arch = "sparc64"))),
        )]
        const RDHUP = c::POLLRDHUP;
    }
}

/// `struct pollfd`—File descriptor and flags for use with [`poll`].
///
/// [`poll`]: crate::io::poll
#[doc(alias = "pollfd")]
#[derive(Clone)]
#[cfg_attr(not(windows), derive(Debug))]
#[repr(transparent)]
pub struct PollFd<'fd> {
    pollfd: c::pollfd,
    _phantom: PhantomData<BorrowedFd<'fd>>,
}

#[cfg(windows)]
impl<'fd> fmt::Debug for PollFd<'fd> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("pollfd")
            .field("fd", &self.pollfd.fd)
            .field("events", &self.pollfd.events)
            .field("revents", &self.pollfd.revents)
            .finish()
    }
}

impl<'fd> PollFd<'fd> {
    /// Constructs a new `PollFd` holding `fd` and `events`.
    #[inline]
    pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self {
        Self::from_borrowed_fd(fd.as_fd(), events)
    }

    /// Sets the contained file descriptor to `fd`.
    #[inline]
    pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) {
        self.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd;
    }

    /// Clears the ready events.
    #[inline]
    pub fn clear_revents(&mut self) {
        self.pollfd.revents = 0;
    }

    /// Constructs a new `PollFd` holding `fd` and `events`.
    ///
    /// This is the same as `new`, but can be used to avoid borrowing the
    /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd`
    /// is a temporary.
    #[inline]
    pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self {
        Self {
            pollfd: c::pollfd {
                fd: borrowed_fd(fd),
                events: events.bits(),
                revents: 0,
            },
            _phantom: PhantomData,
        }
    }

    /// Returns the ready events.
    #[inline]
    pub fn revents(&self) -> PollFlags {
        // Use `unwrap()` here because in theory we know we know all the bits
        // the OS might set here, but OS's have added extensions in the past.
        PollFlags::from_bits(self.pollfd.revents).unwrap()
    }
}

#[cfg(not(windows))]
impl<'fd> AsFd for PollFd<'fd> {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        // Safety: Our constructors and `set_fd` require `pollfd.fd` to be
        // valid for the `fd lifetime.
        unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) }
    }
}

#[cfg(windows)]
impl<'fd> io_lifetimes::AsSocket for PollFd<'fd> {
    #[inline]
    fn as_socket(&self) -> BorrowedFd<'_> {
        // Safety: Our constructors and `set_fd` require `pollfd.fd` to be
        // valid for the `fd lifetime.
        unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) }
    }
}