modo/service/state.rs
1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::sync::Arc;
4
5use super::Registry;
6
7/// Immutable, cheaply-cloneable application state produced by [`Registry::into_state`].
8///
9/// `AppState` is the value passed to [`Router::with_state`](axum::Router::with_state).
10/// axum clones it for every request, so the underlying service map is wrapped in an
11/// [`Arc`] and never copied.
12///
13/// Retrieve individual services inside handlers through the
14/// [`Service<T>`](crate::extractor::Service) extractor, which calls
15/// [`AppState::get`] internally.
16#[derive(Clone)]
17pub struct AppState {
18 services: Arc<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>,
19}
20
21impl AppState {
22 /// Returns a reference-counted handle to the service registered as type `T`,
23 /// or `None` if no such service exists.
24 pub fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
25 self.services
26 .get(&TypeId::of::<T>())
27 .and_then(|arc| arc.clone().downcast::<T>().ok())
28 }
29}
30
31impl From<Registry> for AppState {
32 /// Converts a [`Registry`] into an [`AppState`] by freezing the service map.
33 fn from(registry: Registry) -> Self {
34 Self {
35 services: Arc::new(registry.into_inner()),
36 }
37 }
38}