dope-core 0.8.1

The manifold runtime
Documentation
use std::cell::Cell;
use std::io;
use std::marker::PhantomData;
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};

use crate::backend::PlatformAbi;
use crate::driver::Driver;

pub struct Pipe {
    read: OwnedFd,
    write: OwnedFd,
    _exclusive: PhantomData<Cell<()>>,
}

impl Pipe {
    pub fn new() -> io::Result<Self> {
        let fds = Driver::open_pipe()?;
        Ok(Self::from_fds(fds[0], fds[1]))
    }

    pub fn write_fd(&self) -> RawFd {
        self.write.as_raw_fd()
    }

    pub fn write_end(&self) -> BorrowedFd<'_> {
        self.write.as_fd()
    }

    pub fn try_clone(&self) -> io::Result<Self> {
        Ok(Self {
            read: self.read.try_clone()?,
            write: self.write.try_clone()?,
            _exclusive: PhantomData,
        })
    }

    pub fn from_fds(read: RawFd, write: RawFd) -> Self {
        unsafe {
            Self {
                read: OwnedFd::from_raw_fd(read),
                write: OwnedFd::from_raw_fd(write),
                _exclusive: PhantomData,
            }
        }
    }

    pub fn read_fd(&self) -> RawFd {
        self.read.as_raw_fd()
    }

    pub fn read_end(&self) -> BorrowedFd<'_> {
        self.read.as_fd()
    }

    pub fn notify(&self) -> io::Result<()> {
        let byte = 1u8;
        loop {
            let written =
                unsafe { libc::write(self.write.as_raw_fd(), (&byte as *const u8).cast(), 1) };
            if written == 1 {
                return Ok(());
            }
            let error = io::Error::last_os_error();
            match error.kind() {
                io::ErrorKind::Interrupted => continue,
                io::ErrorKind::WouldBlock => return Ok(()),
                _ => return Err(error),
            }
        }
    }
}