From 7a6a0e63c7196abe3b33d9f091a78d57e1b04439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Mon, 13 May 2024 14:28:20 +0800 Subject: [PATCH] feat(process): use TryFrom to convert to Stdio --- compio-process/src/lib.rs | 75 +++++++++++++++++---------------- compio-process/tests/process.rs | 4 +- compio-runtime/src/attacher.rs | 9 ++++ 3 files changed, 51 insertions(+), 37 deletions(-) diff --git a/compio-process/src/lib.rs b/compio-process/src/lib.rs index 0df6c955..766ac5b2 100644 --- a/compio-process/src/lib.rs +++ b/compio-process/src/lib.rs @@ -171,21 +171,21 @@ impl Command { } /// Configuration for the child process’s standard input (stdin) handle. - pub fn stdin(&mut self, cfg: impl Into) -> &mut Self { - self.0.stdin(cfg); - self + pub fn stdin>(&mut self, cfg: S) -> Result<&mut Self, S::Error> { + self.0.stdin(cfg.try_into()?); + Ok(self) } /// Configuration for the child process’s standard output (stdout) handle. - pub fn stdout(&mut self, cfg: impl Into) -> &mut Self { - self.0.stdout(cfg); - self + pub fn stdout>(&mut self, cfg: S) -> Result<&mut Self, S::Error> { + self.0.stdout(cfg.try_into()?); + Ok(self) } /// Configuration for the child process’s standard error (stderr) handle. - pub fn stderr(&mut self, cfg: impl Into) -> &mut Self { - self.0.stderr(cfg); - self + pub fn stderr>(&mut self, cfg: S) -> Result<&mut Self, S::Error> { + self.0.stderr(cfg.try_into()?); + Ok(self) } /// Returns the path to the program. @@ -409,15 +409,16 @@ impl ChildStdout { } } -impl From for process::Stdio { - fn from(value: ChildStdout) -> Self { - Self::from( - value - .0 - .into_inner() - .try_unwrap() - .expect("the handle is being used"), - ) +impl TryFrom for process::Stdio { + type Error = ChildStdout; + + fn try_from(value: ChildStdout) -> Result { + value + .0 + .into_inner() + .try_unwrap() + .map(Self::from) + .map_err(|fd| ChildStdout(unsafe { Attacher::from_shared_fd_unchecked(fd) })) } } @@ -430,15 +431,16 @@ impl ChildStderr { } } -impl From for process::Stdio { - fn from(value: ChildStderr) -> Self { - Self::from( - value - .0 - .into_inner() - .try_unwrap() - .expect("the handle is being used"), - ) +impl TryFrom for process::Stdio { + type Error = ChildStderr; + + fn try_from(value: ChildStderr) -> Result { + value + .0 + .into_inner() + .try_unwrap() + .map(Self::from) + .map_err(|fd| ChildStderr(unsafe { Attacher::from_shared_fd_unchecked(fd) })) } } @@ -452,14 +454,15 @@ impl ChildStdin { } } -impl From for process::Stdio { - fn from(value: ChildStdin) -> Self { - Self::from( - value - .0 - .into_inner() - .try_unwrap() - .expect("the handle is being used"), - ) +impl TryFrom for process::Stdio { + type Error = ChildStdin; + + fn try_from(value: ChildStdin) -> Result { + value + .0 + .into_inner() + .try_unwrap() + .map(Self::from) + .map_err(|fd| ChildStdin(unsafe { Attacher::from_shared_fd_unchecked(fd) })) } } diff --git a/compio-process/tests/process.rs b/compio-process/tests/process.rs index 97b35d40..7d1b2c3f 100644 --- a/compio-process/tests/process.rs +++ b/compio-process/tests/process.rs @@ -38,6 +38,7 @@ async fn echo() { let child = cmd .arg("echo hello world") .stdout(Stdio::piped()) + .unwrap() .spawn() .unwrap(); @@ -58,7 +59,8 @@ async fn arg0() { cmd.arg0("test_string") .arg("-c") .arg("echo $0") - .stdout(Stdio::piped()); + .stdout(Stdio::piped()) + .unwrap(); let output = cmd.output().await.unwrap(); assert_eq!(output.stdout, b"test_string\n"); diff --git a/compio-runtime/src/attacher.rs b/compio-runtime/src/attacher.rs index 60746244..b1f58e1a 100644 --- a/compio-runtime/src/attacher.rs +++ b/compio-runtime/src/attacher.rs @@ -30,6 +30,15 @@ impl Attacher { source: SharedFd::new(source), } } + + /// Create [`Attacher`] without trying to attach the source. + /// + /// # Safety + /// + /// See [`Attacher::new_unchecked`]. + pub unsafe fn from_shared_fd_unchecked(source: SharedFd) -> Self { + Self { source } + } } impl Attacher {