1use derive_more::{Display, Error};
2use std::time::{Duration, SystemTime, SystemTimeError};
3
4#[derive(Debug, Display, Error)]
5pub enum Error {
6 Exec(#[error(ignore)] Box<dyn std::error::Error>),
7 SystemTime(SystemTimeError),
8 #[display(fmt = "{:?}", _0)]
9 Timeout(#[error(ignore)] Duration),
10}
11
12pub fn loop_timeout<T>(
15 timeout: Duration,
16 mut f: impl FnMut() -> Result<Option<T>, Box<dyn std::error::Error>>,
17) -> Result<T, Error> {
18 let start_time = SystemTime::now();
19 let mut result = None;
20 while SystemTime::now()
21 .duration_since(start_time)
22 .map_err(Error::SystemTime)?
23 < timeout
24 && result.is_none()
25 {
26 result = f().map_err(Error::Exec)?;
27 }
28
29 result.ok_or(Error::Timeout(timeout))
30}
31
32pub fn loop_timeout_panic<T>(
35 timeout: Duration,
36 mut f: impl FnMut() -> Option<T>,
37) -> T {
38 loop_timeout(timeout, || Ok(f())).unwrap()
39}