1use std::thread::sleep;
10use std::time::Duration;
11use std::time::Instant;
12
13
14pub fn wait_until<F, T, E>(deadline: Instant, interval: Duration, mut op: F) -> Result<Option<T>, E>
21where
22 F: FnMut() -> Result<Option<T>, E>,
23{
24 'l: loop {
25 match op() {
26 Ok(None) => sleep(interval),
28 v @ Ok(Some(_)) => break 'l v,
30 e @ Err(_) => break 'l e,
32 }
33
34 if Instant::now() >= deadline {
35 break 'l Ok(None);
36 }
37 }
38}
39
40pub fn wait_for<F, T, E>(timeout: Duration, interval: Duration, op: F) -> Result<Option<T>, E>
47where
48 F: FnMut() -> Result<Option<T>, E>,
49{
50 wait_until(Instant::now() + timeout, interval, op)
51}
52
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn wait_for_success() {
60 let result = wait_for::<_, _, ()>(Duration::from_secs(5), Duration::from_nanos(1), || {
61 static mut COUNTER: u64 = 1;
62 if unsafe { COUNTER } == 5 {
63 Ok(Some(5))
64 } else {
65 unsafe { COUNTER += 1 };
66 Ok(None)
67 }
68 });
69
70 assert_eq!(result, Ok(Some(5)))
71 }
72
73 #[test]
74 fn wait_for_error() {
75 let result = wait_for::<_, (), _>(Duration::from_secs(5), Duration::from_nanos(1), || {
76 static mut COUNTER: u64 = 1;
77 if unsafe { COUNTER } == 5 {
78 Err("expected")
79 } else {
80 unsafe { COUNTER += 1 };
81 Ok(None)
82 }
83 });
84
85 assert_eq!(result, Err("expected"))
86 }
87
88 #[test]
89 fn wait_for_timeout() {
90 let result = wait_for::<_, (), ()>(Duration::from_millis(10), Duration::from_nanos(1), || {
91 Ok(None)
92 });
93
94 assert_eq!(result, Ok(None))
95 }
96}