use core::fmt;
use core::ops::{BitOr, BitOrAssign};
use core::time::Duration;
pub trait Source<ES, E>
where ES: Sink,
{
fn max_timeout(&self) -> Option<Duration>;
fn poll(&mut self, event_sink: &mut ES) -> Result<(), E>;
#[allow(unused_variables)] fn blocking_poll(&mut self, event_sink: &mut ES, timeout: Option<Duration>) -> Result<(), E> {
self.poll(event_sink)
}
}
impl<S, ES, E> Source<ES, E> for &mut S
where S: Source<ES, E>,
ES: Sink,
{
fn max_timeout(&self) -> Option<Duration> {
(&**self).max_timeout()
}
fn poll(&mut self, event_sink: &mut ES) -> Result<(), E> {
(&mut **self).poll(event_sink)
}
fn blocking_poll(&mut self, event_sink: &mut ES, timeout: Option<Duration>) -> Result<(), E> {
(&mut **self).blocking_poll(event_sink, timeout)
}
}
pub trait Sink {
fn capacity_left(&self) -> Capacity;
fn add(&mut self, event: Event);
fn extend<I>(&mut self, events: I)
where I: Iterator<Item = Event>,
{
for event in events {
self.add(event);
}
}
}
impl<'a, ES> Sink for &'a mut ES
where ES: Sink,
{
fn capacity_left(&self) -> Capacity {
(&**self).capacity_left()
}
fn add(&mut self, event: Event) {
(&mut **self).add(event)
}
fn extend<I>(&mut self, events: I)
where I: Iterator<Item = Event>,
{
(&mut **self).extend(events)
}
}
#[cfg(feature = "std")]
impl Sink for Vec<Event> {
fn capacity_left(&self) -> Capacity {
Capacity::Growable
}
fn add(&mut self, event: Event) {
self.push(event);
}
fn extend<I>(&mut self, events: I)
where I: Iterator<Item = Event>,
{
<Self as Extend<Event>>::extend(self, events);
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum Capacity {
Limited(usize),
Growable,
}
impl Capacity {
pub fn min(self, right: usize) -> usize {
match self {
Capacity::Limited(left) => left.min(right),
Capacity::Growable => right,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct Event {
id: Id,
readiness: Ready,
}
impl Event {
pub const fn new(id: Id, readiness: Ready) -> Event {
Event { id, readiness }
}
pub const fn id(&self) -> Id {
self.id
}
pub const fn readiness(&self) -> Ready {
self.readiness
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct Id(pub usize);
impl From<usize> for Id {
fn from(val: usize) -> Id {
Id(val)
}
}
impl From<Id> for usize {
fn from(val: Id) -> usize {
val.0
}
}
impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct Ready(u8);
const READABLE: u8 = 1;
const WRITABLE: u8 = 1 << 1;
const ERROR: u8 = 1 << 2;
const TIMER: u8 = 1 << 3;
#[cfg(unix)]
const HUP: u8 = 1 << 4;
impl Ready {
pub const EMPTY: Ready = Ready(0);
pub const READABLE: Ready = Ready(READABLE);
pub const WRITABLE: Ready = Ready(WRITABLE);
pub const ERROR: Ready = Ready(ERROR);
pub const TIMER: Ready = Ready(TIMER);
#[cfg(unix)]
pub const HUP: Ready = Ready(HUP);
#[inline]
pub const fn contains(self, other: Ready) -> bool {
(self.0 & other.0) == other.0
}
#[inline]
pub const fn is_readable(self) -> bool {
self.contains(Self::READABLE)
}
#[inline]
pub const fn is_writable(self) -> bool {
self.contains(Self::WRITABLE)
}
#[inline]
pub const fn is_error(self) -> bool {
self.contains(Self::ERROR)
}
#[inline]
pub const fn is_timer(self) -> bool {
self.contains(Self::TIMER)
}
#[inline]
#[cfg(unix)]
pub const fn is_hup(self) -> bool {
self.contains(Self::HUP)
}
}
impl BitOr for Ready {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Ready(self.0 | rhs.0)
}
}
impl BitOrAssign for Ready {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0
}
}
macro_rules! fmt_debug {
($self:expr, $f:expr, $($flag:expr),+) => {{
if $self.0 == 0 {
$f.write_str("(empty)")
} else {
let mut first = true;
$(
if $self.0 & $flag != 0 {
if !first {
$f.write_str(" | ")?;
} else {
first = false;
}
$f.write_str(stringify!($flag))?;
}
)+
#[allow(clippy::drop_copy)]
drop(first);
Ok(())
}
}}
}
impl fmt::Debug for Ready {
#[allow(clippy::cognitive_complexity)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt_debug!(self, f, READABLE, WRITABLE, ERROR, TIMER, HUP)
}
}