1use std::{future::Future, time::Duration};
2
3use thiserror::Error;
4
5#[derive(Debug, Error, PartialEq, Eq)]
7#[error("operation timed out after {duration:?}")]
8pub struct TimeoutError {
9 pub duration: Duration,
11}
12
13pub async fn run_with_timeout<F, T>(duration: Duration, future: F) -> Result<T, TimeoutError>
15where
16 F: Future<Output = T>,
17{
18 tokio::time::timeout(duration, future)
19 .await
20 .map_err(|_| TimeoutError { duration })
21}
22
23#[cfg(test)]
24mod tests {
25 use super::run_with_timeout;
26 use std::time::Duration;
27
28 #[tokio::test]
29 async fn returns_value_before_timeout() {
30 let value = run_with_timeout(Duration::from_millis(50), async { 7 })
31 .await
32 .expect("value");
33
34 assert_eq!(value, 7);
35 }
36
37 #[tokio::test]
38 async fn returns_timeout_error() {
39 let result = run_with_timeout(Duration::from_millis(5), async {
40 tokio::time::sleep(Duration::from_millis(50)).await;
41 })
42 .await;
43
44 assert!(result.is_err());
45 }
46}