Skip to main content

oxide_framework_core/
state.rs

1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::sync::Arc;
4
5use crate::config::AppConfig;
6
7/// Clone-able, type-safe map for storing arbitrary state by type.
8#[derive(Clone, Default)]
9pub struct TypeMap {
10    map: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
11}
12
13impl TypeMap {
14    pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) {
15        self.map.insert(TypeId::of::<T>(), Arc::new(value));
16    }
17
18    pub fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
19        self.map
20            .get(&TypeId::of::<T>())
21            .and_then(|v| v.clone().downcast::<T>().ok())
22    }
23}
24
25/// Shared application state injected into every request.
26///
27/// Contains:
28/// - `config` — the loaded [`AppConfig`] (always present)
29/// - User-provided state registered via [`App::state()`](crate::App::state)
30#[derive(Clone)]
31pub struct AppState {
32    pub config: Arc<AppConfig>,
33    extensions: Arc<TypeMap>,
34}
35
36impl AppState {
37    pub(crate) fn new(config: AppConfig, extensions: TypeMap) -> Self {
38        Self {
39            config: Arc::new(config),
40            extensions: Arc::new(extensions),
41        }
42    }
43
44    /// Retrieve user-provided state by type.
45    pub fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
46        self.extensions.get::<T>()
47    }
48}
49