86 lines
2.1 KiB
Rust
86 lines
2.1 KiB
Rust
use crate::Readiness;
|
|
use rustix::{event::PollFd, fd::AsFd};
|
|
use std::num::NonZeroUsize;
|
|
|
|
pub use std::io::{Error, Result};
|
|
|
|
pub enum InProgress<T> {
|
|
Ready(T),
|
|
InProgress,
|
|
}
|
|
|
|
pub enum Nonblocking<T> {
|
|
Ready(T),
|
|
WouldBlock,
|
|
}
|
|
|
|
pub enum ReadBytes {
|
|
Read(NonZeroUsize),
|
|
EOF,
|
|
}
|
|
|
|
impl<T> Nonblocking<T> {
|
|
pub fn map<U>(self, callback: impl FnOnce(T) -> U) -> Nonblocking<U> {
|
|
match self {
|
|
Self::Ready(t) => Nonblocking::Ready((callback)(t)),
|
|
Self::WouldBlock => Nonblocking::WouldBlock,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> InProgress<T> {
|
|
pub fn map<U>(self, callback: impl FnOnce(T) -> U) -> InProgress<U> {
|
|
match self {
|
|
Self::Ready(t) => InProgress::Ready((callback)(t)),
|
|
Self::InProgress => InProgress::InProgress,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<usize> for ReadBytes {
|
|
fn from(n: usize) -> Self {
|
|
n.try_into().map(Self::Read).unwrap_or(Self::EOF)
|
|
}
|
|
}
|
|
|
|
impl From<ReadBytes> for usize {
|
|
fn from(n: ReadBytes) -> Self {
|
|
match n {
|
|
ReadBytes::EOF => 0,
|
|
ReadBytes::Read(n) => n.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn try_ready<A: AsFd>(fd: &A, interest: Readiness) -> Result<Nonblocking<Readiness>> {
|
|
let mut fds = [PollFd::new(fd, interest.into())];
|
|
rustix::event::poll(&mut fds, 0)?;
|
|
let revents: Readiness = fds[0].revents().into();
|
|
|
|
let out = revents & interest;
|
|
|
|
if out.is_empty() {
|
|
return Ok(Nonblocking::WouldBlock);
|
|
}
|
|
|
|
Ok(Nonblocking::Ready(out))
|
|
}
|
|
|
|
pub(crate) fn in_progress<T>(res: rustix::io::Result<T>) -> Result<InProgress<T>> {
|
|
match res {
|
|
Ok(t) => Ok(InProgress::Ready(t)),
|
|
Err(e) if e == rustix::io::Errno::INPROGRESS => Ok(InProgress::InProgress),
|
|
Err(e) => Err(e.into()),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn nonblocking<T>(res: rustix::io::Result<T>) -> Result<Nonblocking<T>> {
|
|
match res {
|
|
Ok(t) => Ok(Nonblocking::Ready(t)),
|
|
Err(e) if e == rustix::io::Errno::WOULDBLOCK || e == rustix::io::Errno::AGAIN => {
|
|
Ok(Nonblocking::WouldBlock)
|
|
}
|
|
Err(e) => Err(e.into()),
|
|
}
|
|
}
|