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}