#[cfg(unix)]
mod pipe_unix;
#[cfg(unix)]
pub use pipe_unix::*;
#[cfg(windows)]
mod pipe_windows;
#[cfg(windows)]
pub use pipe_windows::*;
#[cfg(feature="static_pipe")]
#[macro_use]
mod static_pipe;
#[cfg(feature="static_pipe")]
pub use static_pipe::*;
#[cfg(test)]
mod tests;
mod handle;
pub(crate) use handle::*;
#[cfg(all(feature="channels", not(feature="tokio_channels")))]
use std::sync::mpsc;
#[cfg(all(feature="tokio_channels", not(feature="channels")))]
use tokio::sync::mpsc;
#[derive(Clone, Copy)]
pub enum OnCleanup
{
Delete,
NoDelete
}
impl Pipe
{
pub fn path(&self) -> &std::path::Path
{
&self.path
}
pub fn name(&self) -> Option<&std::ffi::OsStr>
{
self.path().file_name()
}
#[cfg(all(feature="channels", not(feature="tokio_channels")))]
pub fn receiver(mut self) -> (mpsc::Receiver<u8>, std::thread::JoinHandle<()>)
{
use std::io::Read;
let (tx, rx) = mpsc::channel();
(rx,
std::thread::spawn(move ||
{
loop
{
for byte in (&mut self).bytes()
{
tx.send(byte.unwrap()).unwrap()
}
}
}))
}
#[cfg(all(feature="tokio_channels", not(feature="channels")))]
pub async fn receiver(mut self) -> (mpsc::UnboundedReceiver<u8>, tokio::task::JoinHandle<()>)
{
use std::io::Read;
let (tx, rx) = mpsc::unbounded_channel();
(rx,
tokio::task::spawn(async move
{
loop
{
for byte in (&mut self).bytes()
{
tx.send(byte.unwrap()).unwrap()
}
}
}))
}
#[cfg(all(feature="channels", not(feature="tokio_channels")))]
pub fn sender(mut self) -> (mpsc::Sender<u8>, std::thread::JoinHandle<()>)
{
use std::io::Write;
let (tx, rx) = mpsc::channel();
(tx,
std::thread::spawn(move ||
{
loop
{
(&mut self).write(&[rx.recv().unwrap()]).unwrap();
}
}))
}
#[cfg(all(feature="tokio_channels", not(feature="channels")))]
pub fn sender(mut self) -> (mpsc::UnboundedSender<u8>, tokio::task::JoinHandle<()>)
{
use std::io::Write;
let (tx, mut rx) = mpsc::unbounded_channel();
(tx,
tokio::task::spawn(async move
{
loop
{
(&mut self).write(&[rx.recv().await.unwrap()]).unwrap();
}
}))
}
}
#[derive(Debug)]
pub enum Error
{
Ipipe(&'static str),
InvalidPath,
InvalidUtf8,
Io(std::io::Error),
Native(&'static str, u32, String),
Misc(String)
}
pub type Result<T> = std::result::Result<T, Error>;
impl std::fmt::Display for Error
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result
{
match self
{
Error::Ipipe(s) => s.fmt(f),
Error::InvalidPath => write!(f, "Invalid path"),
Error::InvalidUtf8 => write!(f, "Invalid Utf8"),
Error::Io(err) => err.fmt(f),
Error::Native(text, code, oss) => write!(f, "{}: {} - {}", text, code, oss),
Error::Misc(s) => s.fmt(f),
}
}
}
impl std::error::Error for Error{}
impl From<Error> for std::io::Error
{
fn from(err: Error) -> std::io::Error
{
match err
{
Error::Io(err) => err,
e => std::io::Error::new(std::io::ErrorKind::Other, e)
}
}
}
impl From<std::io::Error> for Error
{
fn from(err: std::io::Error) -> Error
{
Error::Io(err)
}
}
impl<'a> From<std::sync::PoisonError<std::sync::MutexGuard<'a, Pipe>>> for Error
{
fn from(err: std::sync::PoisonError<std::sync::MutexGuard<Pipe>>) -> Error
{
Error::Misc(err.to_string())
}
}
impl From<std::string::FromUtf8Error> for Error
{
fn from(_: std::string::FromUtf8Error) -> Error
{
Error::InvalidUtf8
}
}
#[cfg(unix)]
impl From<nix::Error> for Error
{
fn from(error: nix::Error) -> Error
{
Error::Native("", error as u32, error.desc().to_string())
}
}
impl From<std::ffi::NulError> for Error
{
fn from(error: std::ffi::NulError) -> Error
{
Error::Native("Interior null character found", error.nul_position() as u32, format!("{}", error))
}
}