use crate::env::SubEnvironment;
use crate::io::{FileDesc, Pipe as OsPipe};
use std::fs::OpenOptions;
use std::io;
use std::path::Path;
use std::sync::Arc;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Pipe<T> {
pub reader: T,
pub writer: T,
}
pub trait FileDescOpener {
type OpenedFileHandle;
fn open_path(&mut self, path: &Path, opts: &OpenOptions) -> io::Result<Self::OpenedFileHandle>;
fn open_pipe(&mut self) -> io::Result<Pipe<Self::OpenedFileHandle>>;
}
impl<'a, T: ?Sized + FileDescOpener> FileDescOpener for &'a mut T {
type OpenedFileHandle = T::OpenedFileHandle;
fn open_path(&mut self, path: &Path, opts: &OpenOptions) -> io::Result<Self::OpenedFileHandle> {
(**self).open_path(path, opts)
}
fn open_pipe(&mut self) -> io::Result<Pipe<Self::OpenedFileHandle>> {
(**self).open_pipe()
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct FileDescOpenerEnv;
impl FileDescOpenerEnv {
pub fn new() -> Self {
Self {}
}
}
impl SubEnvironment for FileDescOpenerEnv {
fn sub_env(&self) -> Self {
*self
}
}
impl FileDescOpener for FileDescOpenerEnv {
type OpenedFileHandle = FileDesc;
fn open_path(&mut self, path: &Path, opts: &OpenOptions) -> io::Result<Self::OpenedFileHandle> {
opts.open(path).map(FileDesc::from)
}
fn open_pipe(&mut self) -> io::Result<Pipe<Self::OpenedFileHandle>> {
OsPipe::new().map(|pipe| Pipe {
reader: pipe.reader,
writer: pipe.writer,
})
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct ArcFileDescOpenerEnv<O> {
opener: O,
}
impl<O> ArcFileDescOpenerEnv<O> {
pub fn new(opener: O) -> Self {
Self { opener }
}
}
impl<O: SubEnvironment> SubEnvironment for ArcFileDescOpenerEnv<O> {
fn sub_env(&self) -> Self {
Self {
opener: self.opener.sub_env(),
}
}
}
impl<O: FileDescOpener> FileDescOpener for ArcFileDescOpenerEnv<O> {
type OpenedFileHandle = Arc<O::OpenedFileHandle>;
fn open_path(&mut self, path: &Path, opts: &OpenOptions) -> io::Result<Self::OpenedFileHandle> {
self.opener.open_path(path, opts).map(Arc::new)
}
fn open_pipe(&mut self) -> io::Result<Pipe<Self::OpenedFileHandle>> {
self.opener.open_pipe().map(|pipe| Pipe {
reader: Arc::new(pipe.reader),
writer: Arc::new(pipe.writer),
})
}
}