command_error/
output_context.rs

1use std::borrow::Borrow;
2use std::fmt::Debug;
3use std::fmt::Display;
4use std::process::ExitStatus;
5
6#[cfg(doc)]
7use std::process::Command;
8#[cfg(doc)]
9use std::process::Output;
10
11#[cfg(doc)]
12use crate::CommandExt;
13
14use crate::CommandDisplay;
15use crate::Error;
16use crate::OutputError;
17use crate::OutputLike;
18
19/// [`Output`] combined with context about the [`Command`] that produced it.
20///
21/// This contains additional information about the command that was run (via a [`CommandDisplay`]
22/// object) and can be used to construct error messages (for use in methods like
23/// [`CommandExt::output_checked_as`]).
24///
25/// Note that because [`ExitStatus`] has a trivial implementation for [`OutputLike`] (where
26/// [`stdout`][OutputLike::stdout] and [`stderr`][OutputLike::stderr] return empty strings), this
27/// is also used as context for [`status`][`CommandExt::status_checked`] calls.
28pub struct OutputContext<O> {
29    pub(crate) output: O,
30    pub(crate) command: Box<dyn CommandDisplay + Send + Sync>,
31}
32
33impl<O> OutputContext<O>
34where
35    O: OutputLike + Send + Sync + 'static,
36{
37    /// Get the [`OutputLike`] data contained in this context object.
38    pub fn into_output(self) -> O {
39        self.output
40    }
41
42    /// Get a reference to the [`OutputLike`] data contained in this context object.
43    pub fn output(&self) -> &O {
44        &self.output
45    }
46
47    /// Get the command's [`ExitStatus`].
48    pub fn status(&self) -> ExitStatus {
49        self.output.status()
50    }
51
52    /// Get a reference to the command contained in this context object, for use in error messages
53    /// or diagnostics.
54    pub fn command(&self) -> &(dyn CommandDisplay + Send + Sync) {
55        self.command.borrow()
56    }
57
58    /// Get the command contained in this context object, for use in error messages
59    /// or diagnostics.
60    pub fn into_command(self) -> Box<dyn CommandDisplay> {
61        self.command
62    }
63
64    /// Construct an error that indicates this command failed, containing information about the
65    /// command and its output.
66    ///
67    /// See [`CommandExt`] for examples of the error format.
68    pub fn error(self) -> Error {
69        Error::from(OutputError::new(self.command, Box::new(self.output)))
70    }
71
72    /// Construct an error that indicates this command failed, containing information about the
73    /// command, its output, and the provided error message.
74    ///
75    /// See [`CommandExt::output_checked_as`] for examples of the error format.
76    pub fn error_msg<E>(self, message: E) -> Error
77    where
78        E: Debug + Display + Send + Sync + 'static,
79    {
80        Error::from(
81            OutputError::new(self.command, Box::new(self.output)).with_message(Box::new(message)),
82        )
83    }
84
85    pub(crate) fn maybe_error_msg<E>(self, message: Option<E>) -> Error
86    where
87        E: Debug + Display + Send + Sync + 'static,
88    {
89        let ret = OutputError::new(self.command, Box::new(self.output));
90        Error::from(match message {
91            Some(message) => ret.with_message(Box::new(message)),
92            None => ret,
93        })
94    }
95}