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}