shellfn_core/execute/
vec.rs

1use crate::error::Error;
2use crate::execute::execute_iter_nopanic_nopanic;
3use crate::utils::*;
4use std::error::Error as StdError;
5use std::ffi::OsStr;
6use std::io::{BufRead, BufReader};
7use std::str::FromStr;
8
9/// Executes command with args and environment variables, parses output line by line, returns after reading whole output
10/// * On invalid command: return error
11/// * On error exit code: return error
12/// * On parsing failure: collect error item
13/// * Possible errors: ProcessNotSpawned, WaitFailed, ProcessFailed, StdoutUnreadable (item error), ParsingError (item error)
14///
15/// Designed for
16/// ```rust
17/// use shellfn::shell;
18/// use std::error::Error;
19///
20/// #[shell]
21/// fn command() -> Result<Vec<Result<u32, Box<Error + 'static>>>, Box<Error>> {
22///     "echo 1; echo 2; echo 3"
23/// }
24///
25/// assert_eq!(vec![1, 2, 3], command().unwrap().map(Result::unwrap).collect::<Vec<_>>())
26/// ```
27pub fn execute_vec_result_result<T, TArg, TEnvKey, TEnvVal, TOuterError, TInnerError>(
28    cmd: impl AsRef<OsStr>,
29    args: impl IntoIterator<Item = TArg>,
30    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
31) -> Result<Vec<Result<T, TInnerError>>, TOuterError>
32where
33    T: FromStr,
34    TArg: AsRef<OsStr>,
35    TEnvKey: AsRef<OsStr>,
36    TEnvVal: AsRef<OsStr>,
37    <T as FromStr>::Err: StdError,
38    TOuterError: From<Error<<T as FromStr>::Err>>,
39    TInnerError: From<Error<<T as FromStr>::Err>>,
40{
41    let mut process = spawn(cmd, args, envs).map_err(Error::ProcessNotSpawned)?;
42    let stdout = process.stdout.take().unwrap();
43    let result = BufReader::new(stdout)
44        .lines()
45        .map(|lres| lres
46            .map_err(Error::StdoutUnreadable)
47            .map_err(Into::into)
48            .and_then(|line|
49                line.parse()
50                    .map_err(Error::ParsingError)
51                    .map_err(Into::into)
52            )
53        )
54        .collect::<Vec<_>>();
55
56    check_exit_code(process)?;
57    Ok(result)
58}
59
60/// Executes command with args and environment variables, parses output line by line, returns after reading whole output
61/// * On invalid command: panic
62/// * On error exit code: panic
63/// * On parsing failure: panic
64/// * Possible errors: N/A
65///
66/// Designed for
67/// ```rust
68/// use shellfn::shell;
69/// use std::error::Error;
70///
71/// #[shell]
72/// fn command() -> Vec<u32> {
73///     "echo 1; echo 2; echo 3"
74/// }
75///
76/// assert_eq!(vec![1, 2, 3], command().collect::<Vec<_>>())
77/// ```
78pub fn execute_vec_panic_panic<T, TArg, TEnvKey, TEnvVal>(
79    cmd: impl AsRef<OsStr>,
80    args: impl IntoIterator<Item = TArg>,
81    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
82) -> Vec<T>
83where
84    T: FromStr,
85    TArg: AsRef<OsStr>,
86    TEnvKey: AsRef<OsStr>,
87    TEnvVal: AsRef<OsStr>,
88    <T as FromStr>::Err: StdError,
89{
90    let mut process = spawn(cmd, args, envs).expect(PANIC_MSG);
91    let stdout = process.stdout.take().unwrap();
92    let result = BufReader::new(stdout)
93        .lines()
94        .map(|lres| lres
95            .expect(PANIC_MSG)
96            .parse()
97            .expect(PANIC_MSG)
98        )
99        .collect::<Vec<_>>();
100
101    check_exit_code_panic(process);
102    result
103}
104
105/// Executes command with args and environment variables, parses output line by line, returns after reading whole output
106/// * On invalid command: panic
107/// * On error exit code: panic
108/// * On parsing failure: collect error item
109/// * Possible errors: StdoutUnreadable (item error), ParsingError (item error)
110///
111/// Designed for
112/// ```rust
113/// use shellfn::shell;
114/// use std::error::Error;
115///
116/// #[shell]
117/// fn command() -> Vec<Result<u32, Box<Error + 'static>>> {
118///     "echo 1; echo 2; echo 3"
119/// }
120///
121/// assert_eq!(vec![1, 2, 3], command().map(Result::unwrap).collect::<Vec<_>>())
122/// ```
123pub fn execute_vec_panic_result<T, TArg, TEnvKey, TEnvVal, TError>(
124    cmd: impl AsRef<OsStr>,
125    args: impl IntoIterator<Item = TArg>,
126    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
127) -> Vec<Result<T, TError>>
128where
129    T: FromStr,
130    TArg: AsRef<OsStr>,
131    TEnvKey: AsRef<OsStr>,
132    TEnvVal: AsRef<OsStr>,
133    <T as FromStr>::Err: StdError,
134    TError: From<Error<<T as FromStr>::Err>>,
135{
136    let mut process = spawn(cmd, args, envs).expect(PANIC_MSG);
137    let stdout = process.stdout.take().unwrap();
138    let result = BufReader::new(stdout)
139        .lines()
140        .map(|lres| lres
141            .map_err(Error::StdoutUnreadable)
142            .map_err(Into::into)
143            .and_then(|line|
144                line.parse()
145                    .map_err(Error::ParsingError)
146                    .map_err(Into::into)
147            )
148        )
149        .collect::<Vec<_>>();
150
151    check_exit_code_panic(process);
152    result
153}
154
155/// Executes command with args and environment variables, parses output line by line, returns after reading whole output
156/// * On invalid command: return empty vec
157/// * On error exit code: return already collected items
158/// * On parsing failure: collect error item
159/// * Possible errors: StdoutUnreadable (item error), ParsingError (item error)
160///
161/// Designed for
162/// ```rust
163/// use shellfn::shell;
164/// use std::error::Error;
165///
166/// #[shell(no_panic)]
167/// fn command() -> Vec<Result<u32, Box<Error + 'static>>> {
168///     "echo 1; echo 2; echo 3"
169/// }
170///
171/// assert_eq!(vec![1, 2, 3], command().map(Result::unwrap).collect::<Vec<_>>())
172/// ```
173pub fn execute_vec_nopanic_result<T, TArg, TEnvKey, TEnvVal, TError>(
174    cmd:  impl AsRef<OsStr>,
175    args: impl IntoIterator<Item = TArg>,
176    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
177) -> Vec<Result<T, TError>>
178where
179    T: FromStr,
180    TArg: AsRef<OsStr>,
181    TEnvKey: AsRef<OsStr>,
182    TEnvVal: AsRef<OsStr>,
183    <T as FromStr>::Err: StdError,
184    TError: From<Error<<T as FromStr>::Err>>,
185{
186    spawn(cmd, args, envs)
187        .map(|mut process|
188            BufReader::new(process.stdout.take().unwrap())
189                .lines()
190                .map(|lres|
191                    lres.map_err(Error::StdoutUnreadable)
192                        .map_err(Into::into)
193                        .and_then(|line|
194                            line.parse()
195                                .map_err(Error::ParsingError)
196                                .map_err(Into::into)
197                        )
198                )
199                .collect::<Vec<_>>()
200        )
201        .unwrap_or(Vec::default())
202}
203
204/// Executes command with args and environment variables, parses output line by line, returns after reading whole output
205/// * On invalid command: return empty vec
206/// * On error exit code: return already collected items
207/// * On parsing failure: skip item
208/// * Possible errors: N/A
209///
210/// Designed for
211/// ```rust
212/// use shellfn::shell;
213/// use std::error::Error;
214///
215/// #[shell(no_panic)]
216/// fn command() -> Vec<u32> {
217///     "echo 1; echo 2; echo 3"
218/// }
219///
220/// assert_eq!(vec![1, 2, 3], command().collect::<Vec<_>>())
221/// ```
222pub fn execute_vec_nopanic_nopanic<T, TArg, TEnvKey, TEnvVal>(
223    cmd: impl AsRef<OsStr>,
224    args: impl IntoIterator<Item = TArg>,
225    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
226) -> Vec<T>
227where
228    T: FromStr,
229    TArg: AsRef<OsStr>,
230    TEnvKey: AsRef<OsStr>,
231    TEnvVal: AsRef<OsStr>,
232    <T as FromStr>::Err: StdError,
233{
234    execute_iter_nopanic_nopanic(cmd, args, envs).collect()
235}
236
237/// Executes command with args and environment variables, parses output line by line, returns after reading whole output
238/// * On invalid command: return error
239/// * On error exit code: return error
240/// * On parsing failure: panic
241/// * Possible errors: ProcessNotSpawned, WaitFailed, ProcessFailed
242///
243/// Designed for
244/// ```rust
245/// use shellfn::shell;
246/// use std::error::Error;
247///
248/// #[shell]
249/// fn command() -> Result<Vec<u32>, Box<Error>> {
250///     "echo 1; echo 2; echo 3"
251/// }
252///
253/// assert_eq!(vec![1, 2, 3], command().unwrap().collect::<Vec<_>>())
254/// ```
255pub fn execute_vec_result_panic<T, TArg, TEnvKey, TEnvVal, TError>(
256    cmd: impl AsRef<OsStr>,
257    args: impl IntoIterator<Item = TArg>,
258    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
259) -> Result<Vec<T>, TError>
260where
261    T: FromStr,
262    TArg: AsRef<OsStr>,
263    TEnvKey: AsRef<OsStr>,
264    TEnvVal: AsRef<OsStr>,
265    <T as FromStr>::Err: StdError,
266    TError: From<Error<<T as FromStr>::Err>>,
267{
268    let mut process = spawn(cmd, args, envs).map_err(Error::ProcessNotSpawned)?;
269    let stdout = process.stdout.take().unwrap();
270    let mut result = Vec::new();
271
272    for lres in BufReader::new(stdout).lines() {
273        result.push(lres.expect(PANIC_MSG).parse().expect(PANIC_MSG));
274    }
275
276    check_exit_code(process)?;
277    Ok(result)
278}
279
280/// Executes command with args and environment variables, parses output line by line, returns after reading whole output
281/// * On invalid command: return error
282/// * On error exit code: return error
283/// * On parsing failure: skip item
284/// * Possible errors: ProcessNotSpawned, WaitFailed, ProcessFailed
285///
286/// Designed for
287/// ```rust
288/// use shellfn::shell;
289/// use std::error::Error;
290///
291/// #[shell(no_panic)]
292/// fn command() -> Result<Vec<u32>, Box<Error>> {
293///     "echo 1; echo 2; echo 3"
294/// }
295///
296/// assert_eq!(vec![1, 2, 3], command().unwrap().collect::<Vec<_>>())
297/// ```
298pub fn execute_vec_result_nopanic<T, TArg, TEnvKey, TEnvVal, TError>(
299    cmd: impl AsRef<OsStr>,
300    args: impl IntoIterator<Item = TArg>,
301    envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
302) -> Result<Vec<T>, TError>
303where
304    T: FromStr,
305    TArg: AsRef<OsStr>,
306    TEnvKey: AsRef<OsStr>,
307    TEnvVal: AsRef<OsStr>,
308    <T as FromStr>::Err: StdError,
309    TError: From<Error<<T as FromStr>::Err>>,
310{
311    let mut process = spawn(cmd, args, envs).map_err(Error::ProcessNotSpawned)?;
312    let stdout = process.stdout.take().unwrap();
313    let result = BufReader::new(stdout)
314        .lines()
315        .filter_map(|lres| lres.ok().and_then(|line| line.parse().ok()))
316        .collect::<Vec<_>>();
317
318    check_exit_code(process)?;
319    Ok(result)
320}