summaryrefslogtreecommitdiffstats
path: root/third_party/rust/mio/src/event
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/mio/src/event
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/mio/src/event')
-rw-r--r--third_party/rust/mio/src/event/event.rs230
-rw-r--r--third_party/rust/mio/src/event/events.rs230
-rw-r--r--third_party/rust/mio/src/event/mod.rs10
-rw-r--r--third_party/rust/mio/src/event/source.rs139
4 files changed, 609 insertions, 0 deletions
diff --git a/third_party/rust/mio/src/event/event.rs b/third_party/rust/mio/src/event/event.rs
new file mode 100644
index 0000000000..1b4f7b7fbc
--- /dev/null
+++ b/third_party/rust/mio/src/event/event.rs
@@ -0,0 +1,230 @@
+use crate::{sys, Token};
+
+use std::fmt;
+
+/// A readiness event.
+///
+/// `Event` is a readiness state paired with a [`Token`]. It is returned by
+/// [`Poll::poll`].
+///
+/// For more documentation on polling and events, see [`Poll`].
+///
+/// [`Poll::poll`]: ../struct.Poll.html#method.poll
+/// [`Poll`]: ../struct.Poll.html
+/// [`Token`]: ../struct.Token.html
+#[derive(Clone)]
+#[repr(transparent)]
+pub struct Event {
+ inner: sys::Event,
+}
+
+impl Event {
+ /// Returns the event's token.
+ pub fn token(&self) -> Token {
+ sys::event::token(&self.inner)
+ }
+
+ /// Returns true if the event contains readable readiness.
+ ///
+ /// # Notes
+ ///
+ /// Out-of-band (OOB) data also triggers readable events. But must
+ /// application don't actually read OOB data, this could leave an
+ /// application open to a Denial-of-Service (Dos) attack, see
+ /// <https://github.com/sandstorm-io/sandstorm-website/blob/58f93346028c0576e8147627667328eaaf4be9fa/_posts/2015-04-08-osx-security-bug.md>.
+ /// However because Mio uses edge-triggers it will not result in an infinite
+ /// loop as described in the article above.
+ pub fn is_readable(&self) -> bool {
+ sys::event::is_readable(&self.inner)
+ }
+
+ /// Returns true if the event contains writable readiness.
+ pub fn is_writable(&self) -> bool {
+ sys::event::is_writable(&self.inner)
+ }
+
+ /// Returns true if the event contains error readiness.
+ ///
+ /// Error events occur when the socket enters an error state. In this case,
+ /// the socket will also receive a readable or writable event. Reading or
+ /// writing to the socket will result in an error.
+ ///
+ /// # Notes
+ ///
+ /// Method is available on all platforms, but not all platforms trigger the
+ /// error event.
+ ///
+ /// The table below shows what flags are checked on what OS.
+ ///
+ /// | [OS selector] | Flag(s) checked |
+ /// |---------------|-----------------|
+ /// | [epoll] | `EPOLLERR` |
+ /// | [kqueue] | `EV_ERROR` and `EV_EOF` with `fflags` set to `0`. |
+ ///
+ /// [OS selector]: ../struct.Poll.html#implementation-notes
+ /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
+ /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+ pub fn is_error(&self) -> bool {
+ sys::event::is_error(&self.inner)
+ }
+
+ /// Returns true if the event contains read closed readiness.
+ ///
+ /// # Notes
+ ///
+ /// Read closed readiness can be expected after any of the following have
+ /// occurred:
+ /// * The local stream has shutdown the read half of its socket
+ /// * The local stream has shutdown both the read half and the write half
+ /// of its socket
+ /// * The peer stream has shutdown the write half its socket; this sends a
+ /// `FIN` packet that has been received by the local stream
+ ///
+ /// Method is a best effort implementation. While some platforms may not
+ /// return readiness when read half is closed, it is guaranteed that
+ /// false-positives will not occur.
+ ///
+ /// The table below shows what flags are checked on what OS.
+ ///
+ /// | [OS selector] | Flag(s) checked |
+ /// |---------------|-----------------|
+ /// | [epoll] | `EPOLLHUP`, or |
+ /// | | `EPOLLIN` and `EPOLLRDHUP` |
+ /// | [kqueue] | `EV_EOF` |
+ ///
+ /// [OS selector]: ../struct.Poll.html#implementation-notes
+ /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
+ /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+ pub fn is_read_closed(&self) -> bool {
+ sys::event::is_read_closed(&self.inner)
+ }
+
+ /// Returns true if the event contains write closed readiness.
+ ///
+ /// # Notes
+ ///
+ /// On [epoll] this is essentially a check for `EPOLLHUP` flag as the
+ /// local stream shutting down its write half does not trigger this event.
+ ///
+ /// On [kqueue] the local stream shutting down the write half of its
+ /// socket will trigger this event.
+ ///
+ /// Method is a best effort implementation. While some platforms may not
+ /// return readiness when write half is closed, it is guaranteed that
+ /// false-positives will not occur.
+ ///
+ /// The table below shows what flags are checked on what OS.
+ ///
+ /// | [OS selector] | Flag(s) checked |
+ /// |---------------|-----------------|
+ /// | [epoll] | `EPOLLHUP`, or |
+ /// | | only `EPOLLERR`, or |
+ /// | | `EPOLLOUT` and `EPOLLERR` |
+ /// | [kqueue] | `EV_EOF` |
+ ///
+ /// [OS selector]: ../struct.Poll.html#implementation-notes
+ /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
+ /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+ pub fn is_write_closed(&self) -> bool {
+ sys::event::is_write_closed(&self.inner)
+ }
+
+ /// Returns true if the event contains priority readiness.
+ ///
+ /// # Notes
+ ///
+ /// Method is available on all platforms, but not all platforms trigger the
+ /// priority event.
+ ///
+ /// The table below shows what flags are checked on what OS.
+ ///
+ /// | [OS selector] | Flag(s) checked |
+ /// |---------------|-----------------|
+ /// | [epoll] | `EPOLLPRI` |
+ /// | [kqueue] | *Not supported* |
+ ///
+ /// [OS selector]: ../struct.Poll.html#implementation-notes
+ /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
+ /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+ #[inline]
+ pub fn is_priority(&self) -> bool {
+ sys::event::is_priority(&self.inner)
+ }
+
+ /// Returns true if the event contains AIO readiness.
+ ///
+ /// # Notes
+ ///
+ /// Method is available on all platforms, but not all platforms support AIO.
+ ///
+ /// The table below shows what flags are checked on what OS.
+ ///
+ /// | [OS selector] | Flag(s) checked |
+ /// |---------------|-----------------|
+ /// | [epoll] | *Not supported* |
+ /// | [kqueue]<sup>1</sup> | `EVFILT_AIO` |
+ ///
+ /// 1: Only supported on DragonFly BSD, FreeBSD, iOS and macOS.
+ ///
+ /// [OS selector]: ../struct.Poll.html#implementation-notes
+ /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
+ /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+ pub fn is_aio(&self) -> bool {
+ sys::event::is_aio(&self.inner)
+ }
+
+ /// Returns true if the event contains LIO readiness.
+ ///
+ /// # Notes
+ ///
+ /// Method is available on all platforms, but only FreeBSD supports LIO. On
+ /// FreeBSD this method checks the `EVFILT_LIO` flag.
+ pub fn is_lio(&self) -> bool {
+ sys::event::is_lio(&self.inner)
+ }
+
+ /// Create a reference to an `Event` from a platform specific event.
+ pub(crate) fn from_sys_event_ref(sys_event: &sys::Event) -> &Event {
+ unsafe {
+ // This is safe because the memory layout of `Event` is
+ // the same as `sys::Event` due to the `repr(transparent)` attribute.
+ &*(sys_event as *const sys::Event as *const Event)
+ }
+ }
+}
+
+/// When the [alternate] flag is enabled this will print platform specific
+/// details, for example the fields of the `kevent` structure on platforms that
+/// use `kqueue(2)`. Note however that the output of this implementation is
+/// **not** consider a part of the stable API.
+///
+/// [alternate]: fmt::Formatter::alternate
+impl fmt::Debug for Event {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let alternate = f.alternate();
+ let mut d = f.debug_struct("Event");
+ d.field("token", &self.token())
+ .field("readable", &self.is_readable())
+ .field("writable", &self.is_writable())
+ .field("error", &self.is_error())
+ .field("read_closed", &self.is_read_closed())
+ .field("write_closed", &self.is_write_closed())
+ .field("priority", &self.is_priority())
+ .field("aio", &self.is_aio())
+ .field("lio", &self.is_lio());
+
+ if alternate {
+ struct EventDetails<'a>(&'a sys::Event);
+
+ impl<'a> fmt::Debug for EventDetails<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ sys::event::debug_details(f, self.0)
+ }
+ }
+
+ d.field("details", &EventDetails(&self.inner)).finish()
+ } else {
+ d.finish()
+ }
+ }
+}
diff --git a/third_party/rust/mio/src/event/events.rs b/third_party/rust/mio/src/event/events.rs
new file mode 100644
index 0000000000..f3c5a2f02f
--- /dev/null
+++ b/third_party/rust/mio/src/event/events.rs
@@ -0,0 +1,230 @@
+use crate::event::Event;
+use crate::sys;
+
+use std::fmt;
+
+/// A collection of readiness events.
+///
+/// `Events` is passed as an argument to [`Poll::poll`] and will be used to
+/// receive any new readiness events received since the last poll. Usually, a
+/// single `Events` instance is created at the same time as a [`Poll`] and
+/// reused on each call to [`Poll::poll`].
+///
+/// See [`Poll`] for more documentation on polling.
+///
+/// [`Poll::poll`]: ../struct.Poll.html#method.poll
+/// [`Poll`]: ../struct.Poll.html
+///
+/// # Examples
+///
+#[cfg_attr(feature = "os-poll", doc = "```")]
+#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
+/// # use std::error::Error;
+/// # fn main() -> Result<(), Box<dyn Error>> {
+/// use mio::{Events, Poll};
+/// use std::time::Duration;
+///
+/// let mut events = Events::with_capacity(1024);
+/// let mut poll = Poll::new()?;
+/// #
+/// # assert!(events.is_empty());
+///
+/// // Register `event::Source`s with `poll`.
+///
+/// poll.poll(&mut events, Some(Duration::from_millis(100)))?;
+///
+/// for event in events.iter() {
+/// println!("Got an event for {:?}", event.token());
+/// }
+/// # Ok(())
+/// # }
+/// ```
+pub struct Events {
+ inner: sys::Events,
+}
+
+/// [`Events`] iterator.
+///
+/// This struct is created by the [`iter`] method on [`Events`].
+///
+/// [`Events`]: struct.Events.html
+/// [`iter`]: struct.Events.html#method.iter
+///
+/// # Examples
+///
+#[cfg_attr(feature = "os-poll", doc = "```")]
+#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
+/// # use std::error::Error;
+/// # fn main() -> Result<(), Box<dyn Error>> {
+/// use mio::{Events, Poll};
+/// use std::time::Duration;
+///
+/// let mut events = Events::with_capacity(1024);
+/// let mut poll = Poll::new()?;
+///
+/// // Register handles with `poll`.
+///
+/// poll.poll(&mut events, Some(Duration::from_millis(100)))?;
+///
+/// for event in events.iter() {
+/// println!("Got an event for {:?}", event.token());
+/// }
+/// # Ok(())
+/// # }
+/// ```
+#[derive(Debug, Clone)]
+pub struct Iter<'a> {
+ inner: &'a Events,
+ pos: usize,
+}
+
+impl Events {
+ /// Return a new `Events` capable of holding up to `capacity` events.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use mio::Events;
+ ///
+ /// let events = Events::with_capacity(1024);
+ /// assert_eq!(1024, events.capacity());
+ /// ```
+ pub fn with_capacity(capacity: usize) -> Events {
+ Events {
+ inner: sys::Events::with_capacity(capacity),
+ }
+ }
+
+ /// Returns the number of `Event` values that `self` can hold.
+ ///
+ /// ```
+ /// use mio::Events;
+ ///
+ /// let events = Events::with_capacity(1024);
+ /// assert_eq!(1024, events.capacity());
+ /// ```
+ pub fn capacity(&self) -> usize {
+ self.inner.capacity()
+ }
+
+ /// Returns `true` if `self` contains no `Event` values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use mio::Events;
+ ///
+ /// let events = Events::with_capacity(1024);
+ /// assert!(events.is_empty());
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ self.inner.is_empty()
+ }
+
+ /// Returns an iterator over the `Event` values.
+ ///
+ /// # Examples
+ ///
+ #[cfg_attr(feature = "os-poll", doc = "```")]
+ #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
+ /// # use std::error::Error;
+ /// # fn main() -> Result<(), Box<dyn Error>> {
+ /// use mio::{Events, Poll};
+ /// use std::time::Duration;
+ ///
+ /// let mut events = Events::with_capacity(1024);
+ /// let mut poll = Poll::new()?;
+ ///
+ /// // Register handles with `poll`.
+ ///
+ /// poll.poll(&mut events, Some(Duration::from_millis(100)))?;
+ ///
+ /// for event in events.iter() {
+ /// println!("Got an event for {:?}", event.token());
+ /// }
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn iter(&self) -> Iter<'_> {
+ Iter {
+ inner: self,
+ pos: 0,
+ }
+ }
+
+ /// Clearing all `Event` values from container explicitly.
+ ///
+ /// # Notes
+ ///
+ /// Events are cleared before every `poll`, so it is not required to call
+ /// this manually.
+ ///
+ /// # Examples
+ ///
+ #[cfg_attr(feature = "os-poll", doc = "```")]
+ #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
+ /// # use std::error::Error;
+ /// # fn main() -> Result<(), Box<dyn Error>> {
+ /// use mio::{Events, Poll};
+ /// use std::time::Duration;
+ ///
+ /// let mut events = Events::with_capacity(1024);
+ /// let mut poll = Poll::new()?;
+ ///
+ /// // Register handles with `poll`.
+ ///
+ /// poll.poll(&mut events, Some(Duration::from_millis(100)))?;
+ ///
+ /// // Clear all events.
+ /// events.clear();
+ /// assert!(events.is_empty());
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn clear(&mut self) {
+ self.inner.clear();
+ }
+
+ /// Returns the inner `sys::Events`.
+ pub(crate) fn sys(&mut self) -> &mut sys::Events {
+ &mut self.inner
+ }
+}
+
+impl<'a> IntoIterator for &'a Events {
+ type Item = &'a Event;
+ type IntoIter = Iter<'a>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a> Iterator for Iter<'a> {
+ type Item = &'a Event;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let ret = self
+ .inner
+ .inner
+ .get(self.pos)
+ .map(Event::from_sys_event_ref);
+ self.pos += 1;
+ ret
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let size = self.inner.inner.len();
+ (size, Some(size))
+ }
+
+ fn count(self) -> usize {
+ self.inner.inner.len()
+ }
+}
+
+impl fmt::Debug for Events {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self).finish()
+ }
+}
diff --git a/third_party/rust/mio/src/event/mod.rs b/third_party/rust/mio/src/event/mod.rs
new file mode 100644
index 0000000000..8e17f82ee5
--- /dev/null
+++ b/third_party/rust/mio/src/event/mod.rs
@@ -0,0 +1,10 @@
+//! Readiness event types and utilities.
+
+#[allow(clippy::module_inception)]
+mod event;
+mod events;
+mod source;
+
+pub use self::event::Event;
+pub use self::events::{Events, Iter};
+pub use self::source::Source;
diff --git a/third_party/rust/mio/src/event/source.rs b/third_party/rust/mio/src/event/source.rs
new file mode 100644
index 0000000000..4f9c6635a1
--- /dev/null
+++ b/third_party/rust/mio/src/event/source.rs
@@ -0,0 +1,139 @@
+use crate::{Interest, Registry, Token};
+
+use std::io;
+
+/// An event source that may be registered with [`Registry`].
+///
+/// Types that implement `event::Source` can be registered with
+/// `Registry`. Users of Mio **should not** use the `event::Source` trait
+/// functions directly. Instead, the equivalent functions on `Registry` should
+/// be used.
+///
+/// See [`Registry`] for more details.
+///
+/// [`Registry`]: ../struct.Registry.html
+///
+/// # Implementing `event::Source`
+///
+/// Event sources are always backed by system handles, such as sockets or other
+/// system handles. These `event::Source`s will be monitored by the system
+/// selector. An implementation of `Source` will almost always delegates to a
+/// lower level handle. Examples of this are [`TcpStream`]s, or the *unix only*
+/// [`SourceFd`].
+///
+/// [`TcpStream`]: ../net/struct.TcpStream.html
+/// [`SourceFd`]: ../unix/struct.SourceFd.html
+///
+/// # Dropping `event::Source`s
+///
+/// All `event::Source`s, unless otherwise specified, need to be [deregistered]
+/// before being dropped for them to not leak resources. This goes against the
+/// normal drop behaviour of types in Rust which cleanup after themselves, e.g.
+/// a `File` will close itself. However since deregistering needs access to
+/// [`Registry`] this cannot be done while being dropped.
+///
+/// [deregistered]: ../struct.Registry.html#method.deregister
+///
+/// # Examples
+///
+/// Implementing `Source` on a struct containing a socket:
+///
+#[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
+#[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
+/// use mio::{Interest, Registry, Token};
+/// use mio::event::Source;
+/// use mio::net::TcpStream;
+///
+/// use std::io;
+///
+/// # #[allow(dead_code)]
+/// pub struct MySource {
+/// socket: TcpStream,
+/// }
+///
+/// impl Source for MySource {
+/// fn register(&mut self, registry: &Registry, token: Token, interests: Interest)
+/// -> io::Result<()>
+/// {
+/// // Delegate the `register` call to `socket`
+/// self.socket.register(registry, token, interests)
+/// }
+///
+/// fn reregister(&mut self, registry: &Registry, token: Token, interests: Interest)
+/// -> io::Result<()>
+/// {
+/// // Delegate the `reregister` call to `socket`
+/// self.socket.reregister(registry, token, interests)
+/// }
+///
+/// fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
+/// // Delegate the `deregister` call to `socket`
+/// self.socket.deregister(registry)
+/// }
+/// }
+/// ```
+pub trait Source {
+ /// Register `self` with the given `Registry` instance.
+ ///
+ /// This function should not be called directly. Use [`Registry::register`]
+ /// instead. Implementors should handle registration by delegating the call
+ /// to another `Source` type.
+ ///
+ /// [`Registry::register`]: ../struct.Registry.html#method.register
+ fn register(
+ &mut self,
+ registry: &Registry,
+ token: Token,
+ interests: Interest,
+ ) -> io::Result<()>;
+
+ /// Re-register `self` with the given `Registry` instance.
+ ///
+ /// This function should not be called directly. Use
+ /// [`Registry::reregister`] instead. Implementors should handle
+ /// re-registration by either delegating the call to another `Source` type.
+ ///
+ /// [`Registry::reregister`]: ../struct.Registry.html#method.reregister
+ fn reregister(
+ &mut self,
+ registry: &Registry,
+ token: Token,
+ interests: Interest,
+ ) -> io::Result<()>;
+
+ /// Deregister `self` from the given `Registry` instance.
+ ///
+ /// This function should not be called directly. Use
+ /// [`Registry::deregister`] instead. Implementors should handle
+ /// deregistration by delegating the call to another `Source` type.
+ ///
+ /// [`Registry::deregister`]: ../struct.Registry.html#method.deregister
+ fn deregister(&mut self, registry: &Registry) -> io::Result<()>;
+}
+
+impl<T> Source for Box<T>
+where
+ T: Source + ?Sized,
+{
+ fn register(
+ &mut self,
+ registry: &Registry,
+ token: Token,
+ interests: Interest,
+ ) -> io::Result<()> {
+ (&mut **self).register(registry, token, interests)
+ }
+
+ fn reregister(
+ &mut self,
+ registry: &Registry,
+ token: Token,
+ interests: Interest,
+ ) -> io::Result<()> {
+ (&mut **self).reregister(registry, token, interests)
+ }
+
+ fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
+ (&mut **self).deregister(registry)
+ }
+}