1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3
4pub 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 pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) {
18 self.data.insert(TypeId::of::<T>(), Box::new(value));
19 }
20
21 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 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}