command_group/tokio/
erased.rs

1use std::{
2	io::Result,
3	process::{ExitStatus, Output},
4};
5
6use super::AsyncGroupChild;
7use tokio::process::Child;
8
9/// Wrapper around a process child, be it grouped or ungrouped.
10///
11/// This is a helper which erases that a [`tokio::process::Child`] is a different type than an
12/// [`AsyncGroupChild`]. It forwards to the corresponding method on the inner type.
13#[derive(Debug)]
14pub enum ErasedChild {
15	/// A grouped process child.
16	Grouped(AsyncGroupChild),
17
18	/// An ungrouped process child.
19	Ungrouped(Child),
20}
21
22impl ErasedChild {
23	/// Returns the OS-assigned process (group) identifier.
24	///
25	/// - Grouped: [`AsyncGroupChild::id`]
26	/// - Ungrouped: [`Child::id`]
27	pub fn id(&mut self) -> Option<u32> {
28		match self {
29			Self::Grouped(c) => c.id(),
30			Self::Ungrouped(c) => c.id(),
31		}
32	}
33
34	/// Forces the child to exit.
35	///
36	/// - Grouped: [`AsyncGroupChild::kill`]
37	/// - Ungrouped: [`Child::kill`]
38	pub async fn kill(&mut self) -> Result<()> {
39		match self {
40			Self::Grouped(c) => c.kill().await,
41			Self::Ungrouped(c) => c.kill().await,
42		}
43	}
44
45	/// Attempts to force the child to exit, but does not wait for the request to take effect.
46	///
47	/// - Grouped: [`AsyncGroupChild::start_kill`]
48	/// - Ungrouped: [`Child::start_kill`]
49	pub fn start_kill(&mut self) -> Result<()> {
50		match self {
51			Self::Grouped(c) => c.start_kill(),
52			Self::Ungrouped(c) => c.start_kill(),
53		}
54	}
55
56	/// Attempts to collect the exit status of the child if it has already exited.
57	///
58	/// - Grouped: [`AsyncGroupChild::try_wait`]
59	/// - Ungrouped: [`Child::try_wait`]
60	pub fn try_wait(&mut self) -> Result<Option<ExitStatus>> {
61		match self {
62			Self::Grouped(c) => c.try_wait(),
63			Self::Ungrouped(c) => c.try_wait(),
64		}
65	}
66
67	/// Waits for the process to exit, and returns its exit status.
68	///
69	/// - Grouped: [`AsyncGroupChild::wait`]
70	/// - Ungrouped: [`Child::wait`]
71	pub async fn wait(&mut self) -> Result<ExitStatus> {
72		match self {
73			Self::Grouped(c) => c.wait().await,
74			Self::Ungrouped(c) => c.wait().await,
75		}
76	}
77
78	/// Waits for the process to exit, and returns its exit status.
79	///
80	/// - Grouped: [`AsyncGroupChild::wait_with_output`]
81	/// - Ungrouped: [`Child::wait_with_output`]
82	pub async fn wait_with_output(self) -> Result<Output> {
83		match self {
84			Self::Grouped(c) => c.wait_with_output().await,
85			Self::Ungrouped(c) => c.wait_with_output().await,
86		}
87	}
88
89	/// Sends a Unix signal to the process.
90	///
91	/// - Grouped: [`AsyncGroupChild::signal`]
92	/// - Ungrouped: [`Child::signal`]
93	#[cfg(unix)]
94	pub fn signal(&self, sig: crate::Signal) -> Result<()> {
95		use crate::UnixChildExt;
96
97		match self {
98			Self::Grouped(c) => c.signal(sig),
99			Self::Ungrouped(c) => c.signal(sig),
100		}
101	}
102}