1use crate::error::Error;
2use crate::utils::{spawn, PANIC_MSG};
3use itertools::Either;
4use std::error::Error as StdError;
5use std::ffi::OsStr;
6use std::io::{BufRead, BufReader};
7use std::str::FromStr;
8
9pub fn execute_iter_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<impl Iterator<Item = 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
44 Ok(BufReader::new(stdout).lines().map(|lres| {
45 lres.map_err(Error::StdoutUnreadable)
46 .map_err(Into::into)
47 .and_then(|line| {
48 line.parse()
49 .map_err(Error::ParsingError)
50 .map_err(Into::into)
51 })
52 }))
53}
54
55pub fn execute_iter_panic_panic<T, TArg, TEnvKey, TEnvVal>(
74 cmd: impl AsRef<OsStr>,
75 args: impl IntoIterator<Item = TArg>,
76 envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
77) -> impl Iterator<Item = T>
78where
79 T: FromStr,
80 TArg: AsRef<OsStr>,
81 TEnvKey: AsRef<OsStr>,
82 TEnvVal: AsRef<OsStr>,
83 <T as FromStr>::Err: StdError,
84{
85 let mut process = spawn(cmd, args, envs).expect(PANIC_MSG);
86 let stdout = process.stdout.take().unwrap();
87
88 BufReader::new(stdout)
89 .lines()
90 .map(|lres| lres.expect(PANIC_MSG).parse().expect(PANIC_MSG))
91 .chain([()].iter().flat_map(move |_| {
92 if !process.wait().unwrap().success() {
93 panic!("{}", PANIC_MSG)
94 }
95 std::iter::empty()
96 }))
97}
98
99pub fn execute_iter_panic_result<T, TArg, TEnvKey, TEnvVal, TError>(
118 cmd: impl AsRef<OsStr>,
119 args: impl IntoIterator<Item = TArg>,
120 envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
121) -> impl Iterator<Item = Result<T, TError>>
122where
123 T: FromStr,
124 TArg: AsRef<OsStr>,
125 TEnvKey: AsRef<OsStr>,
126 TEnvVal: AsRef<OsStr>,
127 <T as FromStr>::Err: StdError,
128 TError: From<Error<<T as FromStr>::Err>>,
129{
130 let mut process = spawn(cmd, args, envs).expect(PANIC_MSG);
131 let stdout = process.stdout.take().unwrap();
132
133 BufReader::new(stdout)
134 .lines()
135 .map(|lres| {
136 lres.map_err(Error::StdoutUnreadable)
137 .map_err(Into::into)
138 .and_then(|line| {
139 line.parse()
140 .map_err(Error::ParsingError)
141 .map_err(Into::into)
142 })
143 })
144 .chain([()].iter().flat_map(move |_| {
145 if !process.wait().unwrap().success() {
146 panic!("{}", PANIC_MSG)
147 }
148 std::iter::empty()
149 }))
150}
151
152pub fn execute_iter_nopanic_result<T, TArg, TEnvKey, TEnvVal, TError>(
171 cmd: impl AsRef<OsStr>,
172 args: impl IntoIterator<Item = TArg>,
173 envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
174) -> impl Iterator<Item = Result<T, TError>>
175where
176 T: FromStr,
177 TArg: AsRef<OsStr>,
178 TEnvKey: AsRef<OsStr>,
179 TEnvVal: AsRef<OsStr>,
180 <T as FromStr>::Err: StdError,
181 TError: From<Error<<T as FromStr>::Err>>,
182{
183 spawn(cmd, args, envs)
184 .ok()
185 .map(|mut process| {
186 BufReader::new(process.stdout.take().unwrap())
187 .lines()
188 .map(|lres| {
189 lres.map_err(Error::StdoutUnreadable)
190 .map_err(Into::into)
191 .and_then(|line| {
192 line.parse()
193 .map_err(Error::ParsingError)
194 .map_err(Into::into)
195 })
196 })
197 })
198 .map_or_else(|| Either::Right(std::iter::empty()), Either::Left)
199}
200
201pub fn execute_iter_nopanic_nopanic<T, TArg, TEnvKey, TEnvVal>(
220 cmd: impl AsRef<OsStr>,
221 args: impl IntoIterator<Item = TArg>,
222 envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
223) -> impl Iterator<Item = T>
224where
225 T: FromStr,
226 TArg: AsRef<OsStr>,
227 TEnvKey: AsRef<OsStr>,
228 TEnvVal: AsRef<OsStr>,
229 <T as FromStr>::Err: StdError,
230{
231 spawn(cmd, args, envs)
232 .ok()
233 .map(|mut process| {
234 BufReader::new(process.stdout.take().unwrap())
235 .lines()
236 .filter_map(|lres| lres.ok().and_then(|line| line.parse().ok()))
237 })
238 .map_or_else(|| Either::Right(std::iter::empty()), Either::Left)
239}
240
241pub fn execute_iter_result_panic<T, TArg, TEnvKey, TEnvVal, TError>(
260 cmd: impl AsRef<OsStr>,
261 args: impl IntoIterator<Item = TArg>,
262 envs: impl IntoIterator<Item = (TEnvKey, TEnvVal)>,
263) -> Result<impl Iterator<Item = T>, TError>
264where
265 T: FromStr,
266 TArg: AsRef<OsStr>,
267 TEnvKey: AsRef<OsStr>,
268 TEnvVal: AsRef<OsStr>,
269 <T as FromStr>::Err: StdError,
270 TError: From<Error<<T as FromStr>::Err>>,
271{
272 let mut process = spawn(cmd, args, envs).map_err(Error::ProcessNotSpawned)?;
273 let stdout = process.stdout.take().unwrap();
274
275 Ok(BufReader::new(stdout)
276 .lines()
277 .map(|lres| lres.expect(PANIC_MSG).parse().expect(PANIC_MSG)))
278}
279
280pub fn execute_iter_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<impl Iterator<Item = 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
314 Ok(BufReader::new(stdout)
315 .lines()
316 .filter_map(|lres| lres.ok().and_then(|item| item.parse().ok())))
317}