use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ValidationContext {
table_name: Arc<str>,
}
impl ValidationContext {
pub fn new(table_name: impl Into<Arc<str>>) -> Self {
Self {
table_name: table_name.into(),
}
}
pub fn with_default_table() -> Self {
Self::new("data")
}
pub fn table_name(&self) -> &str {
&self.table_name
}
}
impl Default for ValidationContext {
fn default() -> Self {
Self::new("data")
}
}
tokio::task_local! {
pub static CURRENT_CONTEXT: ValidationContext;
}
pub fn current_validation_context() -> ValidationContext {
CURRENT_CONTEXT
.try_with(|ctx| ctx.clone())
.unwrap_or_else(|_| ValidationContext::with_default_table())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validation_context_creation() {
let ctx = ValidationContext::new("test_table");
assert_eq!(ctx.table_name(), "test_table");
}
#[test]
fn test_validation_context_default() {
let ctx = ValidationContext::with_default_table();
assert_eq!(ctx.table_name(), "data");
}
#[tokio::test]
async fn test_task_local_context() {
assert_eq!(current_validation_context().table_name(), "data");
let custom_ctx = ValidationContext::new("custom_table");
CURRENT_CONTEXT
.scope(custom_ctx, async {
assert_eq!(current_validation_context().table_name(), "custom_table");
})
.await;
assert_eq!(current_validation_context().table_name(), "data");
}
#[tokio::test]
async fn test_nested_contexts() {
let ctx1 = ValidationContext::new("table1");
let ctx2 = ValidationContext::new("table2");
CURRENT_CONTEXT
.scope(ctx1, async {
assert_eq!(current_validation_context().table_name(), "table1");
CURRENT_CONTEXT
.scope(ctx2, async {
assert_eq!(current_validation_context().table_name(), "table2");
})
.await;
assert_eq!(current_validation_context().table_name(), "table1");
})
.await;
assert_eq!(current_validation_context().table_name(), "data");
}
}