Skip to main content

lutum_protocol/
extensions.rs

1use std::{
2    any::{Any, TypeId},
3    collections::HashMap,
4};
5
6/// A neutral type-map for per-request execution metadata.
7///
8/// The library treats this as an opaque slot. It passes extensions to
9/// `BudgetManager` methods so implementors can extract identity, routing keys,
10/// or any other metadata they need. It also passes extensions to `EventHandler`
11/// so handlers can inspect them during streaming.
12///
13/// The library treats entries in `RequestExtensions` as opaque. All entries are
14/// user-defined.
15#[derive(Default)]
16pub struct RequestExtensions {
17    map: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
18}
19
20impl RequestExtensions {
21    pub fn new() -> Self {
22        Self::default()
23    }
24
25    pub fn insert<T: Any + Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
26        self.map
27            .insert(TypeId::of::<T>(), Box::new(val))
28            .and_then(|old| old.downcast::<T>().ok().map(|b| *b))
29    }
30
31    pub fn get<T: Any + Send + Sync + 'static>(&self) -> Option<&T> {
32        self.map
33            .get(&TypeId::of::<T>())
34            .and_then(|b| b.downcast_ref::<T>())
35    }
36
37    pub fn get_mut<T: Any + Send + Sync + 'static>(&mut self) -> Option<&mut T> {
38        self.map
39            .get_mut(&TypeId::of::<T>())
40            .and_then(|b| b.downcast_mut::<T>())
41    }
42
43    pub fn remove<T: Any + Send + Sync + 'static>(&mut self) -> Option<T> {
44        self.map
45            .remove(&TypeId::of::<T>())
46            .and_then(|b| b.downcast::<T>().ok().map(|b| *b))
47    }
48
49    pub fn contains<T: Any + Send + Sync + 'static>(&self) -> bool {
50        self.map.contains_key(&TypeId::of::<T>())
51    }
52}