diff --git a/src/sys/pipe.rs b/src/sys/pipe.rs index 3ff61d7..5e2f228 100644 --- a/src/sys/pipe.rs +++ b/src/sys/pipe.rs @@ -4,6 +4,7 @@ use super::*; use errno::Errno; use std::{error, fmt}; +use std::ops::Drop; /// Kind of pipe error #[derive(Debug)] @@ -31,6 +32,97 @@ pub(crate) fn unix_pipe() -> Result<(i32, i32), Error> } } +/// A writer for a bi-directinoal unix pipe +/// +/// Created by splitting `Pipe`, data written to this is available to be read from its `ReadHalf` counterpart. +#[derive(Debug, PartialEq, Eq)] +pub struct WriteHalf(i32); + +/// A reader for a bi-directional unix pipe. +/// +/// Created by splitting `Pipe`, data read from this is data that was sent to its `WriteHalf` counterpart. +#[derive(Debug, PartialEq, Eq)] +pub struct ReadHalf(i32); + +/// A bi-drectional unix pipe +/// +/// Data written to the pipe is available to be read from it (unless the pipe is mismatched.) +#[derive(Debug, PartialEq, Eq)] +pub struct Pipe +{ + tx: i32, + rx: i32, +} + +impl Pipe +{ + /// Split this pipe into a read and write half. + /// + /// Data written to the `WriteHalf` is sent to the `ReadHalf` (unless the pipe is mismatched.) + #[inline] pub fn split(self) -> (WriteHalf, ReadHalf) + { + (WriteHalf(self.tx), ReadHalf(self.rx)) + } + + /// Create a `Pipe` from two halves. + /// + /// # Mismatched halves + /// The halves do not need to have originated from the same `Pipe`. + /// If they are not, then writing to the `Pipe` will send the data to its original receiver, and reading from it will take the data from its original sender. + #[inline] pub fn unsplit(tx: WriteHalf, rx: ReadHalf) -> Self + { + Self::new_from_raw((tx.0, rx.0)) + } + + /// Create a new `Pipe` from a pair of raw file descriptors. + /// + /// # Safety + /// Does not check that the integers provided are valid and open file descriptors. + #[inline(always)] fn new_from_raw((tx, rx): (i32, i32)) -> Self + { + Self{tx,rx} + } + + /// Create a new `Pipe` from a pair of raw file descriptors. + /// + /// # Safety + /// The caller must check that `tx` and `rx` are valid, open file descriptors + // TODO: When writing the async version make sure to state that the fds need to be non-blocking. + /// Does not check that the integers provided are valid and open file descriptors. + #[inline] pub unsafe fn from_raw(tx: i32, rx: i32) -> Self + { + Self::new_from_raw((tx, rx)) + } +} + +//TODO: Impl io::Read +/ io::Write for the types above + +impl Drop for ReadHalf +{ + fn drop(&mut self) { + unsafe { + libc::close(self.0); + } + } +} +impl Drop for WriteHalf +{ + fn drop(&mut self) { + unsafe { + libc::close(self.0); + } + } +} +impl Drop for Pipe +{ + fn drop(&mut self) { + unsafe { + libc::close(self.tx); + libc::close(self.rx); + } + } +} + impl fmt::Display for ErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result @@ -55,7 +147,7 @@ impl ErrorKind } /// 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(self, fun: F) -> Result - where F: FnOnce() -> T + where F: FnOnce() -> T { Error::or_last_with(self, fun) }