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}