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)]
29#[cfg_attr(coverage_nightly, coverage(off))]
30mod tests {
31 use futures::executor::block_on;
32
33 use crate::time::{Duration, Error, Instant, Interval, TimeAbstraction};
34
35 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
37 struct TimeMock<const NOW: u64>;
38
39 impl<const NOW: u64> TimeAbstraction for TimeMock<NOW> {
40 fn now() -> Instant {
41 Instant::MIN + Duration::from_secs(NOW)
42 }
43
44 async fn sleep_until(deadline: Instant) -> Result<(), Error> {
45 if Self::now() < deadline {
46 core::future::pending::<()>().await;
48 }
49 Ok(())
50 }
51
52 fn interval(_: Duration) -> impl Interval {
53 struct IntervalInternal;
54 impl Interval for IntervalInternal {
55 async fn tick(&mut self) -> Result<(), Error> {
56 unimplemented!()
57 }
58 }
59 unimplemented!();
60 #[allow(unreachable_code)] IntervalInternal
62 }
63 }
64
65 #[test]
66 fn timeout_with_future_that_completes_in_time_should_not_fail() {
67 async fn should_complete_on_time() {}
68
69 let result = block_on(TimeMock::<0>::timeout_at(
70 Instant::MIN + Duration::from_secs(123),
71 should_complete_on_time(),
72 ));
73 assert!(result.is_ok(), "the future did complete out of time");
74 }
75
76 #[test]
77 fn timeout_with_future_that_completes_out_of_time_should_fail() {
78 async fn should_complete_out_of_time() {}
79
80 let result = block_on(TimeMock::<123>::timeout_at(
81 Instant::MIN + Duration::from_secs(0),
82 should_complete_out_of_time(),
83 ));
84 assert!(result.is_err(), "the future did complete in time");
85 }
86}