use std::future::Future;
use std::time;
#[cfg(feature = "name")]
use crate::name::Name;
use crate::{Error, Timer};
#[async_trait::async_trait]
pub trait Context: Clone + Send + Sync {
type SubContext: Context;
fn timer(&self) -> Timer;
#[cfg(feature = "name")]
async fn name(&self) -> Name {
self.timer().name().await
}
async fn deadline(&self) -> Option<time::Instant> {
self.timer().deadline().await
}
async fn cancel(&self) {
self.timer().cancel().await
}
async fn is_cancelled(&self) -> bool {
self.timer().is_cancelled().await
}
async fn is_timeout(&self) -> bool {
self.timer().is_timeout().await
}
async fn error(&self) -> Option<Error> {
if self.is_cancelled().await {
Some(Error::ContextCancelled)
} else if self.is_timeout().await {
Some(Error::ContextTimeout)
} else {
None
}
}
async fn spawn(&self) -> Self::SubContext;
async fn spawn_with_timeout(&self, timeout: time::Duration) -> Self::SubContext;
async fn spawn_in_seconds(&self, secs: u64) -> Self::SubContext {
self.spawn_with_timeout(time::Duration::from_secs(secs)).await
}
async fn spawn_in_milliseconds(&self, millis: u64) -> Self::SubContext {
self.spawn_with_timeout(time::Duration::from_millis(millis)).await
}
async fn handle<'a, Fut, T>(&self, fut: Fut) -> crate::Result<T>
where
Fut: Future<Output = T> + Send + 'a
{
self.timer().handle(fut).await
}
async fn handle_result<'a, Fut, T, E>(&self, fut: Fut) -> Result<T, E>
where
Fut: Future<Output = Result<T, E>> + Send + 'a,
E: From<Error>,
{
self.timer().handle(fut).await?
}
}
#[async_trait::async_trait]
impl<T: Context> Context for &T {
type SubContext = T::SubContext;
fn timer(&self) -> Timer {
(*self).timer()
}
async fn spawn(&self) -> T::SubContext {
(*self).spawn().await
}
async fn spawn_with_timeout(&self, timeout: time::Duration) -> T::SubContext {
(*self).spawn_with_timeout(timeout).await
}
}