veecle_osal_api/time/
timeout.rs1use core::future::Future;
2use core::pin::pin;
3
4use futures::future::{Either, select};
5
6use super::{Error, Instant, TimeAbstraction};
7
8#[derive(Debug)]
10pub struct Exceeded;
11
12pub async fn timeout_at<T, F>(
14 deadline: Instant,
15 future: F,
16) -> Result<F::Output, Either<Exceeded, Error>>
17where
18 T: TimeAbstraction,
19 F: Future,
20{
21 match select(pin!(T::sleep_until(deadline)), pin!(future)).await {
22 Either::Left((Ok(_), _)) => Err(Either::Left(Exceeded)),
23 Either::Left((Err(error), _)) => Err(Either::Right(error)),
24 Either::Right((output, _)) => Ok(output),
25 }
26}
27
28#[cfg(test)]
29mod tests {
30 use futures::executor::block_on;
31
32 use crate::time::{Duration, Error, Instant, Interval, TimeAbstraction};
33
34 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
36 struct TimeMock<const NOW: u64>;
37
38 impl<const NOW: u64> TimeAbstraction for TimeMock<NOW> {
39 fn now() -> Instant {
40 Instant::MIN + Duration::from_secs(NOW)
41 }
42
43 async fn sleep_until(deadline: Instant) -> Result<(), Error> {
44 if Self::now() < deadline {
45 core::future::pending::<()>().await;
47 }
48 Ok(())
49 }
50
51 fn interval(_: Duration) -> impl Interval {
52 struct IntervalInternal;
53 impl Interval for IntervalInternal {
54 async fn tick(&mut self) -> Result<(), Error> {
55 unimplemented!()
56 }
57 }
58 unimplemented!();
59 #[allow(unreachable_code)] IntervalInternal
61 }
62 }
63
64 #[test]
65 fn timeout_with_future_that_completes_in_time_should_not_fail() {
66 async fn should_complete_on_time() {}
67
68 let result = block_on(TimeMock::<0>::timeout_at(
69 Instant::MIN + Duration::from_secs(123),
70 should_complete_on_time(),
71 ));
72 assert!(result.is_ok(), "the future did complete out of time");
73 }
74
75 #[test]
76 fn timeout_with_future_that_completes_out_of_time_should_fail() {
77 async fn should_complete_out_of_time() {}
78
79 let result = block_on(TimeMock::<123>::timeout_at(
80 Instant::MIN + Duration::from_secs(0),
81 should_complete_out_of_time(),
82 ));
83 assert!(result.is_err(), "the future did complete in time");
84 }
85}