hyperlane/hook/impl.rs
1use crate::*;
2
3/// A blanket implementation for any function that takes a `Context` and returns a value.
4///
5/// This implementation makes it easy to use any compatible function as a `FnContextSendSync`,
6/// promoting a flexible and functional programming style.
7impl<F, R> FnContextSendSync<R> for F where F: Fn(Context) -> R + Send + Sync {}
8
9/// A blanket implementation for functions that return a pinned, boxed, sendable future.
10///
11/// This trait is a common pattern for asynchronous handlers in Rust, enabling type
12/// erasure and dynamic dispatch for futures. It is essential for storing different
13/// async functions in a collection.
14impl<F, T> FnContextPinBoxSendSync<T> for F where F: FnContextSendSync<SendableAsyncTask<T>> {}
15
16/// A blanket implementation for static, sendable, synchronous functions that return a future.
17///
18/// This trait is used for handlers that are known at compile time, ensuring they
19/// are safe to be sent across threads and have a static lifetime. This is crucial
20/// for handlers that are part of the application's long-lived state.
21impl<F, Fut, T> FnContextSendSyncStatic<Fut, T> for F
22where
23 F: FnContextSendSync<Fut> + 'static,
24 Fut: Future<Output = T> + Send,
25{
26}
27
28/// A blanket implementation for any future that is sendable and has a static lifetime.
29///
30/// This is a convenient trait for working with futures in an asynchronous context,
31/// ensuring that they can be safely managed by the async runtime across different
32/// threads.
33impl<T, R> FutureSendStatic<R> for T where T: Future<Output = R> + Send + 'static {}
34
35/// Blanket implementation of `FutureSend` for any type that satisfies the bounds.
36impl<T, O> FutureSend<O> for T where T: Future<Output = O> + Send {}
37
38/// Blanket implementation of `FnPinBoxFutureSend` for any type that satisfies the bounds.
39impl<T, O> FnPinBoxFutureSend<O> for T where T: Fn() -> SendableAsyncTask<O> + Send + Sync {}
40
41/// Provides a default implementation for `ServerControlHook`.
42impl Default for ServerControlHook {
43 /// Creates a new `ServerControlHook` instance with default no-op hooks.
44 ///
45 /// The default `wait_hook` and `shutdown_hook` do nothing, allowing the server
46 /// to run without specific shutdown or wait logic unless configured otherwise.
47 ///
48 /// # Returns
49 ///
50 /// - `Self` - A new `ServerControlHook` instance with default hooks.
51 #[inline(always)]
52 fn default() -> Self {
53 Self {
54 wait_hook: Arc::new(|| Box::pin(async {})),
55 shutdown_hook: Arc::new(|| Box::pin(async {})),
56 }
57 }
58}
59
60/// Manages server lifecycle hooks, including waiting and shutdown procedures.
61///
62/// This struct holds closures that are executed during specific server lifecycle events.
63impl ServerControlHook {
64 /// Waits for the server's shutdown signal or completion.
65 ///
66 /// This method asynchronously waits until the server's `wait_hook` is triggered,
67 /// typically indicating that the server has finished its operations or is ready to shut down.
68 pub async fn wait(&self) {
69 self.get_wait_hook()().await;
70 }
71
72 /// Initiates the server shutdown process.
73 ///
74 /// This method asynchronously calls the `shutdown_hook`, which is responsible for
75 /// performing any necessary cleanup or graceful shutdown procedures.
76 pub async fn shutdown(&self) {
77 self.get_shutdown_hook()().await;
78 }
79}
80
81impl PartialEq for HookHandlerSpec {
82 #[inline(always)]
83 fn eq(&self, other: &Self) -> bool {
84 match (self, other) {
85 (HookHandlerSpec::Handler(handler_a), HookHandlerSpec::Handler(handler_b)) => {
86 Arc::ptr_eq(handler_a, handler_b)
87 }
88 (HookHandlerSpec::Factory(factory_a), HookHandlerSpec::Factory(factory_b)) => {
89 std::ptr::eq(factory_a as *const _, factory_b as *const _)
90 }
91 _ => false,
92 }
93 }
94}
95
96impl Eq for HookHandlerSpec {}
97
98/// Implementation block for `HookType`.
99///
100/// This block defines utility methods associated with the `HookType` enum.
101/// These methods provide additional functionality for working with hooks,
102/// such as extracting the execution order (priority) used in duplicate checks.
103impl HookType {
104 /// Returns the optional execution priority (`order`) of a hook.
105 ///
106 /// Hooks that carry an `order` indicate their execution priority.
107 /// Hooks without an `order` are considered unordered and are ignored in duplicate checks.
108 ///
109 /// # Returns
110 ///
111 /// - `Option<isize>` - `Some(order)` if the hook defines a priority, otherwise `None`.
112 #[inline(always)]
113 pub fn try_get(&self) -> Option<isize> {
114 match *self {
115 HookType::RequestMiddleware(order)
116 | HookType::ResponseMiddleware(order)
117 | HookType::PanicHook(order) => order,
118 _ => None,
119 }
120 }
121}