shellfn_core/execute/
item.rs

1use crate::error::Error;
2use crate::utils::{spawn, PANIC_MSG};
3use std::error::Error as StdError;
4use std::ffi::OsStr;
5use std::str::FromStr;
6
7/// Executes command with args and environment variables, parses output
8/// * On invalid command: return error
9/// * On error exit code: return error
10/// * On parsing failure: return error
11/// * Possible errors: ProcessNotSpawned, WaitFailed, ProcessFailed, NonUtf8Stdout, ParsingError
12///
13/// Designed for
14/// ```rust
15/// use shellfn::shell;
16/// use std::error::Error;
17///
18/// #[shell]
19/// fn command() -> Result<u32, Box<Error>> {
20///     "echo -n 42"
21/// }
22///
23/// assert_eq!(42, command().unwrap())
24/// ```
25pub fn execute_parse_result<T, TArg, TEnvKey, TEnvVal, TError>(
26    cmd: impl AsRef<OsStr>,
27    args: impl IntoIterator<Item = TArg>,
28    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
29) -> Result<T, TError>
30where
31    T: FromStr,
32    TArg: AsRef<OsStr>,
33    TEnvKey: AsRef<OsStr>,
34    TEnvVal: AsRef<OsStr>,
35    <T as FromStr>::Err: StdError,
36    TError: From<Error<<T as FromStr>::Err>>,
37{
38    let process = spawn(cmd, args, envs).map_err(Error::ProcessNotSpawned)?;
39    let result = process.wait_with_output().map_err(Error::WaitFailed)?;
40
41    if !result.status.success() {
42        return Err(Error::ProcessFailed(result).into());
43    }
44
45    String::from_utf8(result.stdout)
46        .map_err(Error::NonUtf8Stdout)
47        .map_err(Into::into)
48        .and_then(|s| s.parse().map_err(Error::ParsingError).map_err(Into::into))
49}
50
51/// Executes command with args and environment variables, parses output
52/// * On invalid command: panic
53/// * On error exit code: panic
54/// * On parsing failure: panic
55/// * Possible errors: N/A
56///
57/// Designed for
58/// ```rust
59/// use shellfn::shell;
60///
61/// #[shell]
62/// fn command() -> u32 {
63///     "echo -n 42"
64/// }
65///
66/// assert_eq!(42, command())
67/// ```
68pub fn execute_parse_panic<T, TArg, TEnvKey, TEnvVal>(
69    cmd: impl AsRef<OsStr>,
70    args: impl IntoIterator<Item = TArg>,
71    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
72) -> T
73where
74    T: FromStr,
75    TArg: AsRef<OsStr>,
76    TEnvKey: AsRef<OsStr>,
77    TEnvVal: AsRef<OsStr>,
78    <T as FromStr>::Err: StdError,
79{
80    let result = spawn(cmd, args, envs)
81        .expect(PANIC_MSG)
82        .wait_with_output()
83        .expect(PANIC_MSG);
84
85    if !result.status.success() {
86        panic!("{}", PANIC_MSG);
87    }
88
89    String::from_utf8(result.stdout)
90        .expect(PANIC_MSG)
91        .parse()
92        .expect(PANIC_MSG)
93}