Started `sys/pipe`: Interfacing with raw `pipe()` created streams.

Fortune for comfork's current commit: Middle blessing − 中吉
master
Avril 3 years ago
parent e64abf4f06
commit 6020491a09
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -46,3 +46,13 @@ fn _debug_if_test()
}
}
}
/// Do not compile the code in this block
#[macro_export] macro_rules! remove {
($($tt:tt)*) => {
const _:() = {
$($tt)*
()
};
}
}

@ -41,7 +41,7 @@ fn get_message(raw: RawError) -> String
}
/// A raw C error
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Errno
{
errno: NonZeroI32,
@ -86,7 +86,7 @@ impl Errno
/// Create a new `Result` that returns the last errno value set if it was an error, or calls this function and returns the value returned from it if it was success.
pub fn or_last_with<F, T>(fun: F) -> Result<T, Self>
where F: FnOnce() -> T
where F: FnOnce() -> T
{
Self::last().map(move |_| fun())
}
@ -115,7 +115,80 @@ impl fmt::Display for Errno
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}", self.message())
write!(f, "{} ({})", self.message(), self.errno.get())
}
}
remove! {
/// Wrapping of errno around another Rust error type.
#[derive(Debug)]
pub struct ErrnoWrap<T: ?Sized>
{
error: Errno,
inner: T,
}
impl<T: error::Error + 'static> error::Error for ErrnoWrap<T>
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(&self.inner)
}
}
impl<T: fmt::Display> fmt::Display for ErrnoWrap<T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}: {}", self.inner, self.error)
}
}
impl<T> ErrnoWrap<T>
{
pub fn into_inner(self) -> T
{
self.inner
}
pub fn map_inner<F, U>(self, map: F) -> ErrnoWrap<U>
where F: FnOnce(T) -> U,
U: error::Error + 'static
{
ErrnoWrap {
error: self.error,
inner: map(self.inner)
}
}
}
impl<T: ?Sized> ErrnoWrap<T>
{
pub fn errno(&self) -> &Errno
{
&self.error
}
pub fn inner(&self) -> &T
{
&self.inner
}
}
impl<T: error::Error + 'static> ErrnoWrap<T>
{
pub fn with_errno(error: T, errno: Errno) -> Self
{
Self {
error: errno,
inner: error
}
}
pub fn last(error: T) -> Result<(), Self>
{
Err(Self::with_errno(error, match Errno::last() {
Ok(()) => return Ok(()),
Err(e) => e,
}))
}
}
}

@ -2,3 +2,5 @@
use super::*;
pub mod errno;
pub mod pipe;

@ -0,0 +1,137 @@
//! Wrapper around internal pipes fds.
//!
//! These pipe fds are valid across forks, and can be used for IPC between parent and non-exec()d child process forks.
use super::*;
use errno::Errno;
use std::{error, fmt};
/// Kind of pipe error
#[derive(Debug)]
#[non_exhaustive]
pub enum ErrorKind
{
/// Failed to create pipes
Create,
/// Unknown error
Unknown,
}
/// A raw unix pipe
pub type RawPipe = i32;
/// Create a raw pipe pair.
pub(crate) fn unix_pipe() -> Result<(i32, i32), Error>
{
use libc::pipe;
let mut pipe_fds: [libc::c_int; 2] = [-1;2];
if unsafe{pipe(pipe_fds.as_mut_ptr())} == 0 {
Ok((i32::from(pipe_fds[0]), i32::from(pipe_fds[1])))
} else {
Err(ErrorKind::Create.into_error())
}
}
impl fmt::Display for ErrorKind
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Create => write!(f, "failed to create raw pipes"),
_ => write!(f, "unknown error"),
}
}
}
/// An error on a pipe operation
#[derive(Debug)]
pub struct Error(ErrorKind, Errno);
impl ErrorKind
{
/// Consume into `Error` using the last `errno` value, if it's not set then return `val`.
#[inline] pub(crate) fn try_into_error_or<T>(self, val: T) -> Result<T, Error>
{
Error::or_last(self, val)
}
/// Consume into `Error` using the last `errno` value, if it's not set then return the result of `fun`.
#[inline] pub(crate) fn try_into_error_or_with<F, T>(self, fun: F) -> Result<T, Error>
where F: FnOnce() -> T
{
Error::or_last_with(self, fun)
}
/// Consume into `Error` using the last `errno` value.
pub(crate) fn try_into_error(self) -> Result<(), Error>
{
Error::last(self)
}
/// Consume into an `Error` using the last `errno` value.
///
/// # Panics
/// If `errno` was success.
#[inline] pub(crate) fn into_error(self) -> Error
{
Self::try_into_error(self).expect_err("Expected an error to be set in errno")
}
}
impl Error
{
/// Create a new error of this kind from the last set errno if it's not success.
/// If it is, return `val`.
#[inline] pub(crate) fn or_last<T>(err: ErrorKind, val: T) -> Result<T, Self>
{
Self::or_last_with(err, move || val)
}
/// Create a new error of this kind from the last set errno if it's not success.
/// If it is, return the result of `fun`.
pub(crate) fn or_last_with<F, T>(err: ErrorKind, fun: F) -> Result<T, Self>
where F: FnOnce() -> T
{
Err(Self(err, match Errno::or_last_with(fun) {
Ok(v) => return Ok(v),
Err(e) => e,
}))
}
/// Create a new error of this kind from the last set errno (if it's not success.)
pub(crate) fn last(err: ErrorKind) -> Result<(), Self>
{
Err(Self(err, match Errno::last() {
Ok(()) => return Ok(()),
Err(e) => e,
}))
}
/// Create a new error of this kind with this errno value
#[inline] pub fn new(kind: ErrorKind, err: Errno) -> Self
{
Self(kind, err)
}
/// The kind of pipe error
#[inline] pub fn kind(&self) -> &ErrorKind
{
&self.0
}
/// The errno value
#[inline] pub fn error(&self) -> &Errno
{
&self.1
}
}
impl error::Error for Error
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(&self.1)
}
}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}: {}", self.0, self.1)
}
}
Loading…
Cancel
Save