Skip to main content

kojin_core/
context.rs

1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3
4/// Task execution context providing type-safe access to shared data.
5pub struct TaskContext {
6    data: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
7}
8
9impl TaskContext {
10    pub fn new() -> Self {
11        Self {
12            data: HashMap::new(),
13        }
14    }
15
16    /// Insert a value into the context.
17    pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) {
18        self.data.insert(TypeId::of::<T>(), Box::new(value));
19    }
20
21    /// Get a reference to a value from the context.
22    pub fn data<T: Send + Sync + 'static>(&self) -> Option<&T> {
23        self.data
24            .get(&TypeId::of::<T>())
25            .and_then(|v| v.downcast_ref::<T>())
26    }
27
28    /// Check if the context contains a value of the given type.
29    pub fn contains<T: Send + Sync + 'static>(&self) -> bool {
30        self.data.contains_key(&TypeId::of::<T>())
31    }
32}
33
34impl Default for TaskContext {
35    fn default() -> Self {
36        Self::new()
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn context_insert_and_retrieve() {
46        let mut ctx = TaskContext::new();
47        ctx.insert(42u32);
48        ctx.insert("hello".to_string());
49
50        assert_eq!(ctx.data::<u32>(), Some(&42));
51        assert_eq!(ctx.data::<String>(), Some(&"hello".to_string()));
52        assert_eq!(ctx.data::<bool>(), None);
53    }
54
55    #[test]
56    fn context_contains() {
57        let mut ctx = TaskContext::new();
58        ctx.insert(42u32);
59        assert!(ctx.contains::<u32>());
60        assert!(!ctx.contains::<String>());
61    }
62
63    #[test]
64    fn context_overwrite() {
65        let mut ctx = TaskContext::new();
66        ctx.insert(1u32);
67        ctx.insert(2u32);
68        assert_eq!(ctx.data::<u32>(), Some(&2));
69    }
70}