Documentation

use std::{intrinsics::unreachable, sync::Arc};

use tokio::task::futures::TaskLocalFuture;

use crate::{
	error::ServiceNotFoundError,
	scope::{Scope, ScopeProvider},
};

tokio::task_local! {
	static TASK_SCOPE: Arc<Scope>;
}

pub struct TaskScopeProvider;

impl super::ScopeDefault for TaskScopeProvider {
	fn initialize(_scope: Arc<Scope>) {
		unreachable!()
	}

	fn update(_scope: Arc<Scope>) {
		unreachable!()
	}
}

impl TaskScopeProvider {
	pub fn initialize_async<F>(scope: Scope, fut: F) -> TaskLocalFuture<Arc<Scope>, F>
	where
		F: Future,
	{
		TASK_SCOPE.scope(Arc::new(scope), fut)
	}

	pub fn initialize_sync<F, R>(scope: Scope, fun: F) -> R
	where
		F: FnOnce() -> R,
	{
		TASK_SCOPE.sync_scope(Arc::new(scope), fun)
	}

	pub fn update_async<F>(scope: Scope, fut: F) -> TaskLocalFuture<Arc<Scope>, F>
	where
		F: Future,
	{
		TASK_SCOPE.scope(Arc::new(scope), fut)
	}

	pub fn update_sync<F, R>(scope: Scope, fun: F) -> R
	where
		F: FnOnce() -> R,
	{
		TASK_SCOPE.sync_scope(Arc::new(scope), fun)
	}
}

impl ScopeProvider for TaskScopeProvider {
	fn provide_scope(&self) -> Result<Arc<Scope>, ServiceNotFoundError> {
		Ok(TASK_SCOPE.get())
	}
}