use std::{
cell::RefCell,
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
};
use anyhow::{anyhow, Result};
use crate::RwBuilder;
#[derive(Debug)]
pub struct Builder {
command: RefCell<Command>,
}
impl Builder {
#[must_use]
pub fn new(command: Command) -> Self {
Self { command: command.into() }
}
pub fn spawn(&self) -> Result<ChildBuilder> {
let child =
self.command.borrow_mut().stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
Ok(ChildBuilder { child: child.into() })
}
}
impl RwBuilder for Builder {
type Reader = ChildStdout;
type Writer = ChildStdin;
fn reader(&self) -> Result<Self::Reader> {
let mut child = self.command.borrow_mut().stdout(Stdio::piped()).spawn()?;
child.stdout.take().ok_or_else(|| anyhow!("no child stdout"))
}
fn writer(&self) -> Result<Self::Writer> {
let mut child = self.command.borrow_mut().stdin(Stdio::piped()).spawn()?;
child.stdin.take().ok_or_else(|| anyhow!("no child stdin"))
}
}
#[derive(Debug)]
pub struct ChildBuilder {
child: RefCell<Child>,
}
impl RwBuilder for ChildBuilder {
type Reader = ChildStdout;
type Writer = ChildStdin;
fn reader(&self) -> Result<Self::Reader> {
self.child
.borrow_mut()
.stdout
.take()
.ok_or_else(|| anyhow!("No child stdout. Did you already build a reader?"))
}
fn writer(&self) -> Result<Self::Writer> {
self.child
.borrow_mut()
.stdin
.take()
.ok_or_else(|| anyhow!("No child stdin. Did you already build a writer?"))
}
}