use crate::{Command, OsStr, Process};
#[cfg(feature = "shell")]
use crate::{ShellLex, ShellWordError, Str};
use std::process::{abort, exit, id};
trait Sealed {}
impl Sealed for Process {}
#[doc = crate::_tags!(platform concurrency namespace)]
#[doc = crate::_doc_meta!{location("work/process")}]
#[rustfmt::skip]
#[cfg_attr(nightly_doc, doc(notable_trait))]
#[expect(private_bounds, reason = "Sealed")]
pub trait ProcessExt: Sealed {
fn command<S: AsRef<OsStr>>(program: S) -> Command {
Command::new(program)
}
#[cfg(feature = "shell")]
fn command_shell(line: &str) -> Result<Command, ShellWordError> {
let mut lex = ShellLex::new(line);
let mut buf = crate::vec_![0u8; line.len()];
let Some(len) = lex.next_word_to(&mut buf)? else {
return Err(ShellWordError::EmptyCommand);
};
let prog = Str::from_utf8(&buf[..len]).map_err(|_| ShellWordError::InvalidUtf8)?;
let mut cmd = Command::new(prog);
while let Some(len) = lex.next_word_to(&mut buf)? {
let arg = Str::from_utf8(&buf[..len]).map_err(|_| ShellWordError::InvalidUtf8)?;
cmd.arg(arg);
}
Ok(cmd)
}
#[rustfmt::skip]
fn abort() -> ! { abort() }
#[rustfmt::skip]
fn exit(code: i32) -> ! { exit(code) }
#[must_use] #[rustfmt::skip]
fn self_pid() -> u32 { id() }
}
impl ProcessExt for Process {}
#[cfg(test)]
mod tests {
#[cfg(feature = "shell")]
use super::*;
#[test]
#[cfg(feature = "shell")]
fn command_ext_command_shell() {
let cmd = Process::command_shell(r#"echo "hello world""#).unwrap();
let dbg = format!("{cmd:?}");
assert!(dbg.contains("echo"));
assert!(dbg.contains("hello world"));
}
}