use std::sync::Arc;
use std::time::Duration;
use crate::builtins::{Context, ExecutionDeadline, ExecutionExtensions};
use crate::{ExecutionBudget, ExecutionCapability};
#[derive(Clone, Default)]
pub struct RuntimeCallContext {
extensions: Option<Arc<ExecutionExtensions>>,
}
impl RuntimeCallContext {
pub(crate) fn from_context(ctx: &Context<'_>) -> Self {
Self {
extensions: ctx.execution_extensions(),
}
}
pub fn current() -> Self {
RUNTIME_CALL_CONTEXT
.try_with(Clone::clone)
.unwrap_or_default()
}
pub fn execution_extension<T>(&self) -> Option<ExecutionCapability<T>>
where
T: Send + Sync + 'static,
{
self.extensions.as_ref()?.get::<T>()
}
pub fn execution_capability<T>(&self, value: T) -> Option<ExecutionCapability<T>>
where
T: Send + Sync + 'static,
{
self.extensions.as_ref()?.capability(value)
}
pub fn execution_budget(&self) -> Option<ExecutionCapability<ExecutionBudget>> {
self.execution_extension::<ExecutionBudget>()
}
pub fn remaining_deadline(&self) -> Option<Duration> {
self.execution_extension::<ExecutionDeadline>()?
.try_with(ExecutionDeadline::remaining)
.ok()
}
}
tokio::task_local! {
static RUNTIME_CALL_CONTEXT: RuntimeCallContext;
}
pub(crate) async fn scope<F: std::future::Future>(ctx: &Context<'_>, future: F) -> F::Output {
RUNTIME_CALL_CONTEXT
.scope(RuntimeCallContext::from_context(ctx), future)
.await
}