use std::cell::RefCell;
use std::future::Future;
use std::sync::Arc;
use crate::token::{TokenInfo, TokenValue};
thread_local! {
static TLS_CTX: RefCell<Option<SaTokenContext>> = const { RefCell::new(None) };
}
tokio::task_local! {
static TASK_CTX: SaTokenContext;
}
#[derive(Debug, Clone)]
pub struct SaTokenContext {
pub token: Option<TokenValue>,
pub token_info: Option<Arc<TokenInfo>>,
pub login_id: Option<String>,
}
impl SaTokenContext {
pub fn new() -> Self {
Self {
token: None,
token_info: None,
login_id: None,
}
}
pub async fn scope<F, R>(ctx: SaTokenContext, fut: F) -> R
where
F: Future<Output = R>,
{
TASK_CTX.scope(ctx, fut).await
}
pub fn try_current() -> Option<SaTokenContext> {
match TASK_CTX.try_with(|c| c.clone()) {
Ok(c) => Some(c),
Err(_) => TLS_CTX.with(|c| c.borrow().clone()),
}
}
pub fn set_current(ctx: SaTokenContext) {
TLS_CTX.with(|c| {
*c.borrow_mut() = Some(ctx);
});
}
pub fn get_current() -> Option<SaTokenContext> {
Self::try_current()
}
pub fn clear() {
TLS_CTX.with(|c| {
*c.borrow_mut() = None;
});
}
}
impl Default for SaTokenContext {
fn default() -> Self {
Self::new()
}
}