#![doc(html_root_url = "https://docs.rs/process_control/*")]
#![cfg_attr(process_control_docs_rs, feature(doc_cfg))]
#![warn(unused_results)]
use std::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use std::io;
use std::process;
use std::process::Child;
use std::time::Duration;
#[cfg(unix)]
#[path = "unix.rs"]
mod imp;
#[cfg(windows)]
#[path = "windows.rs"]
mod imp;
mod timeout;
#[derive(Debug)]
pub struct Terminator(imp::Handle);
impl Terminator {
#[inline]
pub unsafe fn terminate(&self) -> io::Result<()> {
self.0.terminate()
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct ExitStatus(imp::ExitStatus);
impl ExitStatus {
#[inline]
#[must_use]
pub fn success(self) -> bool {
self.0.success()
}
#[inline]
#[must_use]
pub fn code(self) -> Option<i64> {
self.0.code().map(Into::into)
}
#[cfg(any(unix, doc))]
#[cfg_attr(process_control_docs_rs, doc(cfg(unix)))]
#[inline]
#[must_use]
pub fn signal(self) -> Option<::std::os::raw::c_int> {
self.0.signal()
}
}
impl Display for ExitStatus {
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
impl From<process::ExitStatus> for ExitStatus {
#[inline]
fn from(value: process::ExitStatus) -> Self {
#[cfg_attr(windows, allow(clippy::useless_conversion))]
Self(value.into())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Output {
pub status: ExitStatus,
pub stdout: Vec<u8>,
pub stderr: Vec<u8>,
}
impl From<process::Output> for Output {
#[inline]
fn from(value: process::Output) -> Self {
Self {
status: value.status.into(),
stdout: value.stdout,
stderr: value.stderr,
}
}
}
pub trait Timeout: private::Sealed {
type Result;
#[must_use]
fn strict_errors(self) -> Self;
#[must_use]
fn terminating(self) -> Self;
fn wait(self) -> io::Result<Option<Self::Result>>;
}
pub trait ChildExt<'a>: private::Sealed {
type ExitStatusTimeout: 'a + Timeout<Result = ExitStatus>;
type OutputTimeout: Timeout<Result = Output>;
fn terminator(&self) -> io::Result<Terminator>;
#[must_use]
fn with_timeout(
&'a mut self,
time_limit: Duration,
) -> Self::ExitStatusTimeout;
#[must_use]
fn with_output_timeout(self, time_limit: Duration) -> Self::OutputTimeout;
}
impl<'a> ChildExt<'a> for Child {
type ExitStatusTimeout = timeout::ExitStatusTimeout<'a>;
type OutputTimeout = timeout::OutputTimeout;
#[inline]
fn terminator(&self) -> io::Result<Terminator> {
imp::Handle::new(self).map(Terminator)
}
#[inline]
fn with_timeout(
&'a mut self,
time_limit: Duration,
) -> Self::ExitStatusTimeout {
Self::ExitStatusTimeout::new(self, time_limit)
}
#[inline]
fn with_output_timeout(self, time_limit: Duration) -> Self::OutputTimeout {
Self::OutputTimeout::new(self, time_limit)
}
}
mod private {
use std::process::Child;
use super::timeout;
pub trait Sealed {}
impl Sealed for Child {}
impl Sealed for timeout::ExitStatusTimeout<'_> {}
impl Sealed for timeout::OutputTimeout {}
}