Skip to main content

sword_core/
controllers.rs

1use parking_lot::{RawRwLock, RwLock, lock_api::RwLockReadGuard};
2use std::{
3    any::TypeId,
4    collections::{HashMap, HashSet},
5};
6
7pub type ControllerMap = HashMap<Controller, HashSet<TypeId>>;
8pub type ControllerIds = HashSet<TypeId>;
9
10/// Controller enum used by `#[controller(...)]` attributes and runtime internals.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum Controller {
13    Web,
14    SocketIo,
15    Grpc,
16    EventHandler,
17}
18
19/// Event source enum used by `#[controller(kind = Controller::EventHandler, ...)]`
20/// attributes and runtime internals to select which event backend a handler consumes from.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum EventSource {
23    Memory,
24}
25
26/// A trait for defining controllers in the application.
27///
28/// Controllers represent different entry points into your application.
29/// automatically implement this trait, allowing them to be registered as HTTP controllers
30/// within modules.
31///
32/// # Example
33///
34/// ```rust,ignore
35/// use sword::prelude::*;
36///
37/// #[controller(kind = Controller::Web, path = "/api/items")]
38/// struct ItemsController { /* ... */ }
39///
40/// // The macro automatically implements ControllerSpec for ItemsController
41/// // In your module:
42/// fn register_controllers(controllers: &ControllerRegistry) {
43///     controllers.register::<ItemsController>();
44/// }
45/// ```
46pub trait ControllerSpec {
47    fn kind() -> Controller;
48}
49
50/// Registry for managing and storing different controller kinds.
51///
52/// `ControllerRegistry` is used within modules to register controllers that define how requests
53/// enter the application.
54///
55/// # Example
56///
57/// ```rust,ignore
58/// use sword::prelude::*;
59///
60/// struct MyModule;
61///
62/// impl Module for MyModule {
63///     fn register_controllers(controllers: &ControllerRegistry) {
64///         controllers.register::<UserController>();
65///         controllers.register::<ProductController>();
66///     }
67/// }
68/// ```
69pub struct ControllerRegistry {
70    controllers: RwLock<HashMap<Controller, HashSet<TypeId>>>,
71}
72
73impl ControllerRegistry {
74    #[doc(hidden)]
75    pub fn new() -> Self {
76        Self {
77            controllers: RwLock::new(HashMap::new()),
78        }
79    }
80
81    /// Registers a controller of type `C` by calling its `kind()` method
82    /// and storing the resulting `Controller` in the registry.
83    ///
84    /// # Example
85    ///
86    /// ```rust,ignore
87    /// controllers.register::<MyController>();
88    /// ```
89    pub fn register<C: ControllerSpec + 'static>(&self) {
90        self.controllers
91            .write()
92            .entry(C::kind())
93            .or_default()
94            .insert(TypeId::of::<C>());
95    }
96
97    #[doc(hidden)]
98    pub fn read(&self) -> RwLockReadGuard<'_, RawRwLock, HashMap<Controller, HashSet<TypeId>>> {
99        self.controllers.read()
100    }
101
102    #[doc(hidden)]
103    pub fn snapshot(&self) -> ControllerMap {
104        self.controllers.read().clone()
105    }
106
107    #[doc(hidden)]
108    pub fn get_by_kind(&self, kind: Controller) -> ControllerIds {
109        self.controllers
110            .read()
111            .get(&kind)
112            .cloned()
113            .unwrap_or(HashSet::new())
114    }
115}
116
117impl Default for ControllerRegistry {
118    fn default() -> Self {
119        Self::new()
120    }
121}