Skip to main content

allframe_core/router/
handler.rs

1//! Handler trait and implementations for protocol-agnostic request handling
2
3use serde::de::DeserializeOwned;
4use serde::Serialize;
5use std::{
6    any::Any,
7    fmt,
8    future::Future,
9    ops::Deref,
10    pin::Pin,
11    sync::Arc,
12};
13
14// ─── Output conversion trait ────────────────────────────────────────────────
15
16/// Trait for converting handler return values into `Result<String, String>`.
17///
18/// This is the handler equivalent of axum's `IntoResponse`. By implementing
19/// this trait for different return types, a single set of handler structs
20/// can support `String` passthrough, `Json<T>` auto-serialization, and
21/// `Result<T, E>` error handling.
22pub trait IntoHandlerResult: Send {
23    /// Convert this value into the handler's wire result.
24    fn into_handler_result(self) -> Result<String, String>;
25}
26
27/// `String` passes through verbatim (backwards-compatible with existing handlers).
28impl IntoHandlerResult for String {
29    fn into_handler_result(self) -> Result<String, String> {
30        Ok(self)
31    }
32}
33
34/// Wrapper that auto-serializes `T: Serialize` to JSON.
35///
36/// Used internally by `register_typed*` methods — users return `T` directly,
37/// the registration method wraps it in `Json`.
38pub struct Json<T>(pub T);
39
40impl<T: Serialize + Send> IntoHandlerResult for Json<T> {
41    fn into_handler_result(self) -> Result<String, String> {
42        serde_json::to_string(&self.0)
43            .map_err(|e| format!("Failed to serialize response: {e}"))
44    }
45}
46
47/// `Result<T, E>` serializes `Ok(T)` to JSON and stringifies `Err(E)`.
48impl<T: Serialize + Send, E: fmt::Display + Send> IntoHandlerResult for Result<T, E> {
49    fn into_handler_result(self) -> Result<String, String> {
50        match self {
51            Ok(value) => serde_json::to_string(&value)
52                .map_err(|e| format!("Failed to serialize response: {e}")),
53            Err(e) => Err(e.to_string()),
54        }
55    }
56}
57
58// ─── Core handler trait ─────────────────────────────────────────────────────
59
60/// Handler trait for protocol-agnostic request handling
61///
62/// Handlers implement this trait to provide a unified interface
63/// that can be called from any protocol adapter.
64pub trait Handler: Send + Sync {
65    /// Call the handler with JSON args and return a result
66    fn call(&self, args: &str) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + '_>>;
67}
68
69// ─── State wrapper ──────────────────────────────────────────────────────────
70
71/// Newtype wrapper for injected state
72///
73/// Handlers receive `State<Arc<S>>` to access shared application state.
74#[derive(Debug, Clone)]
75pub struct State<S>(pub S);
76
77impl<S> Deref for State<S> {
78    type Target = S;
79
80    fn deref(&self) -> &Self::Target {
81        &self.0
82    }
83}
84
85// ─── Handler structs (4 total, generic over R: IntoHandlerResult) ───────────
86
87/// Wrapper for function-based handlers with no arguments
88pub struct HandlerFn<F, Fut, R>
89where
90    F: Fn() -> Fut + Send + Sync,
91    Fut: Future<Output = R> + Send,
92    R: IntoHandlerResult,
93{
94    func: F,
95    _marker: std::marker::PhantomData<fn() -> R>,
96}
97
98impl<F, Fut, R> HandlerFn<F, Fut, R>
99where
100    F: Fn() -> Fut + Send + Sync,
101    Fut: Future<Output = R> + Send,
102    R: IntoHandlerResult,
103{
104    /// Create a new handler from a function
105    pub fn new(func: F) -> Self {
106        Self {
107            func,
108            _marker: std::marker::PhantomData,
109        }
110    }
111}
112
113impl<F, Fut, R> Handler for HandlerFn<F, Fut, R>
114where
115    F: Fn() -> Fut + Send + Sync + 'static,
116    Fut: Future<Output = R> + Send + 'static,
117    R: IntoHandlerResult + 'static,
118{
119    fn call(&self, _args: &str) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + '_>> {
120        let fut = (self.func)();
121        Box::pin(async move { fut.await.into_handler_result() })
122    }
123}
124
125/// Wrapper for handlers that accept typed, deserialized arguments
126pub struct HandlerWithArgs<F, T, Fut, R>
127where
128    F: Fn(T) -> Fut + Send + Sync,
129    T: DeserializeOwned + Send,
130    Fut: Future<Output = R> + Send,
131    R: IntoHandlerResult,
132{
133    func: F,
134    // fn() -> T is covariant and auto-implements Send + Sync regardless of T,
135    // which is correct because T is only deserialized transiently, never stored.
136    _marker: std::marker::PhantomData<(fn() -> T, fn() -> R)>,
137}
138
139impl<F, T, Fut, R> HandlerWithArgs<F, T, Fut, R>
140where
141    F: Fn(T) -> Fut + Send + Sync,
142    T: DeserializeOwned + Send,
143    Fut: Future<Output = R> + Send,
144    R: IntoHandlerResult,
145{
146    /// Create a new handler that deserializes JSON args into `T`
147    pub fn new(func: F) -> Self {
148        Self {
149            func,
150            _marker: std::marker::PhantomData,
151        }
152    }
153}
154
155impl<F, T, Fut, R> Handler for HandlerWithArgs<F, T, Fut, R>
156where
157    F: Fn(T) -> Fut + Send + Sync + 'static,
158    T: DeserializeOwned + Send + 'static,
159    Fut: Future<Output = R> + Send + 'static,
160    R: IntoHandlerResult + 'static,
161{
162    fn call(&self, args: &str) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + '_>> {
163        let parsed: Result<T, _> = serde_json::from_str(args);
164        match parsed {
165            Ok(value) => {
166                let fut = (self.func)(value);
167                Box::pin(async move { fut.await.into_handler_result() })
168            }
169            Err(e) => Box::pin(async move {
170                Err(format!("Failed to deserialize args: {e}"))
171            }),
172        }
173    }
174}
175
176/// Wrapper for handlers that receive injected state and typed args
177pub struct HandlerWithState<F, S, T, Fut, R>
178where
179    F: Fn(State<Arc<S>>, T) -> Fut + Send + Sync,
180    S: Send + Sync + 'static,
181    T: DeserializeOwned + Send,
182    Fut: Future<Output = R> + Send,
183    R: IntoHandlerResult,
184{
185    func: F,
186    state: Arc<dyn Any + Send + Sync>,
187    _marker: std::marker::PhantomData<(fn() -> S, fn() -> T, fn() -> R)>,
188}
189
190impl<F, S, T, Fut, R> HandlerWithState<F, S, T, Fut, R>
191where
192    F: Fn(State<Arc<S>>, T) -> Fut + Send + Sync,
193    S: Send + Sync + 'static,
194    T: DeserializeOwned + Send,
195    Fut: Future<Output = R> + Send,
196    R: IntoHandlerResult,
197{
198    /// Create a new handler with state injection and typed args
199    pub fn new(func: F, state: Arc<dyn Any + Send + Sync>) -> Self {
200        Self {
201            func,
202            state,
203            _marker: std::marker::PhantomData,
204        }
205    }
206}
207
208impl<F, S, T, Fut, R> Handler for HandlerWithState<F, S, T, Fut, R>
209where
210    F: Fn(State<Arc<S>>, T) -> Fut + Send + Sync + 'static,
211    S: Send + Sync + 'static,
212    T: DeserializeOwned + Send + 'static,
213    Fut: Future<Output = R> + Send + 'static,
214    R: IntoHandlerResult + 'static,
215{
216    fn call(&self, args: &str) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + '_>> {
217        let state_arc = match self.state.clone().downcast::<S>() {
218            Ok(s) => s,
219            Err(_) => {
220                let msg = format!(
221                    "State type mismatch: expected {}",
222                    std::any::type_name::<S>()
223                );
224                return Box::pin(async move { Err(msg) });
225            }
226        };
227
228        let parsed: Result<T, _> = serde_json::from_str(args);
229        match parsed {
230            Ok(value) => {
231                let fut = (self.func)(State(state_arc), value);
232                Box::pin(async move { fut.await.into_handler_result() })
233            }
234            Err(e) => Box::pin(async move {
235                Err(format!("Failed to deserialize args: {e}"))
236            }),
237        }
238    }
239}
240
241/// Wrapper for handlers that receive only injected state (no args)
242pub struct HandlerWithStateOnly<F, S, Fut, R>
243where
244    F: Fn(State<Arc<S>>) -> Fut + Send + Sync,
245    S: Send + Sync + 'static,
246    Fut: Future<Output = R> + Send,
247    R: IntoHandlerResult,
248{
249    func: F,
250    state: Arc<dyn Any + Send + Sync>,
251    _marker: std::marker::PhantomData<(fn() -> S, fn() -> R)>,
252}
253
254impl<F, S, Fut, R> HandlerWithStateOnly<F, S, Fut, R>
255where
256    F: Fn(State<Arc<S>>) -> Fut + Send + Sync,
257    S: Send + Sync + 'static,
258    Fut: Future<Output = R> + Send,
259    R: IntoHandlerResult,
260{
261    /// Create a new handler with state injection only
262    pub fn new(func: F, state: Arc<dyn Any + Send + Sync>) -> Self {
263        Self {
264            func,
265            state,
266            _marker: std::marker::PhantomData,
267        }
268    }
269}
270
271impl<F, S, Fut, R> Handler for HandlerWithStateOnly<F, S, Fut, R>
272where
273    F: Fn(State<Arc<S>>) -> Fut + Send + Sync + 'static,
274    S: Send + Sync + 'static,
275    Fut: Future<Output = R> + Send + 'static,
276    R: IntoHandlerResult + 'static,
277{
278    fn call(&self, _args: &str) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + '_>> {
279        let state_arc = match self.state.clone().downcast::<S>() {
280            Ok(s) => s,
281            Err(_) => {
282                let msg = format!(
283                    "State type mismatch: expected {}",
284                    std::any::type_name::<S>()
285                );
286                return Box::pin(async move { Err(msg) });
287            }
288        };
289
290        let fut = (self.func)(State(state_arc));
291        Box::pin(async move { fut.await.into_handler_result() })
292    }
293}
294
295#[cfg(test)]
296mod tests {
297    use super::*;
298
299    // ─── String return (backwards compat) ───────────────────────────────
300
301    #[tokio::test]
302    async fn test_handler_fn() {
303        let handler = HandlerFn::new(|| async { "test".to_string() });
304        let result = handler.call("{}").await;
305        assert_eq!(result, Ok("test".to_string()));
306    }
307
308    #[tokio::test]
309    async fn test_handler_fn_ignores_args() {
310        let handler = HandlerFn::new(|| async { "no-args".to_string() });
311        let result = handler.call(r#"{"unexpected": true}"#).await;
312        assert_eq!(result, Ok("no-args".to_string()));
313    }
314
315    #[tokio::test]
316    async fn test_handler_with_args() {
317        #[derive(serde::Deserialize)]
318        struct Input {
319            name: String,
320        }
321
322        let handler = HandlerWithArgs::new(|args: Input| async move {
323            format!("hello {}", args.name)
324        });
325
326        let result = handler.call(r#"{"name":"Alice"}"#).await;
327        assert_eq!(result, Ok("hello Alice".to_string()));
328    }
329
330    #[tokio::test]
331    async fn test_handler_with_args_bad_json() {
332        #[derive(serde::Deserialize)]
333        struct Input {
334            _name: String,
335        }
336
337        let handler = HandlerWithArgs::new(|_args: Input| async move {
338            "unreachable".to_string()
339        });
340
341        let result = handler.call("not-json").await;
342        assert!(result.is_err());
343        assert!(result.unwrap_err().contains("Failed to deserialize args"));
344    }
345
346    #[tokio::test]
347    async fn test_handler_with_args_missing_field() {
348        #[derive(serde::Deserialize)]
349        struct Input {
350            _name: String,
351        }
352
353        let handler = HandlerWithArgs::new(|_args: Input| async move {
354            "unreachable".to_string()
355        });
356
357        let result = handler.call(r#"{"age": 30}"#).await;
358        assert!(result.is_err());
359        assert!(result.unwrap_err().contains("Failed to deserialize args"));
360    }
361
362    #[tokio::test]
363    async fn test_handler_with_state() {
364        struct AppState {
365            greeting: String,
366        }
367
368        #[derive(serde::Deserialize)]
369        struct Input {
370            name: String,
371        }
372
373        let state: Arc<dyn Any + Send + Sync> = Arc::new(AppState {
374            greeting: "Hi".to_string(),
375        });
376
377        let handler = HandlerWithState::new(
378            |state: State<Arc<AppState>>, args: Input| async move {
379                format!("{} {}", state.greeting, args.name)
380            },
381            state,
382        );
383
384        let result = handler.call(r#"{"name":"Bob"}"#).await;
385        assert_eq!(result, Ok("Hi Bob".to_string()));
386    }
387
388    #[tokio::test]
389    async fn test_handler_with_state_only() {
390        struct AppState {
391            value: i32,
392        }
393
394        let state: Arc<dyn Any + Send + Sync> = Arc::new(AppState { value: 42 });
395
396        let handler = HandlerWithStateOnly::new(
397            |state: State<Arc<AppState>>| async move {
398                format!("value={}", state.value)
399            },
400            state,
401        );
402
403        let result = handler.call("{}").await;
404        assert_eq!(result, Ok("value=42".to_string()));
405    }
406
407    #[tokio::test]
408    async fn test_handler_with_state_deser_error() {
409        struct AppState;
410
411        #[derive(serde::Deserialize)]
412        struct Input {
413            _x: i32,
414        }
415
416        let state: Arc<dyn Any + Send + Sync> = Arc::new(AppState);
417
418        let handler = HandlerWithState::new(
419            |_state: State<Arc<AppState>>, _args: Input| async move {
420                "unreachable".to_string()
421            },
422            state,
423        );
424
425        let result = handler.call("bad").await;
426        assert!(result.is_err());
427        assert!(result.unwrap_err().contains("Failed to deserialize args"));
428    }
429
430    // ─── Json<T> return (typed handlers via IntoHandlerResult) ──────────
431
432    #[tokio::test]
433    async fn test_json_handler_fn_struct() {
434        #[derive(serde::Serialize)]
435        struct User {
436            id: u32,
437            name: String,
438        }
439
440        let handler = HandlerFn::new(|| async {
441            Json(User {
442                id: 1,
443                name: "Alice".to_string(),
444            })
445        });
446
447        let result = handler.call("{}").await;
448        assert_eq!(result, Ok(r#"{"id":1,"name":"Alice"}"#.to_string()));
449    }
450
451    #[tokio::test]
452    async fn test_json_handler_fn_vec() {
453        let handler = HandlerFn::new(|| async { Json(vec![1, 2, 3]) });
454        let result = handler.call("{}").await;
455        assert_eq!(result, Ok("[1,2,3]".to_string()));
456    }
457
458    #[tokio::test]
459    async fn test_json_handler_with_args() {
460        #[derive(serde::Deserialize)]
461        struct Input {
462            name: String,
463        }
464
465        #[derive(serde::Serialize)]
466        struct Output {
467            greeting: String,
468        }
469
470        let handler = HandlerWithArgs::new(|args: Input| async move {
471            Json(Output {
472                greeting: format!("Hello {}", args.name),
473            })
474        });
475
476        let result = handler.call(r#"{"name":"Bob"}"#).await;
477        assert_eq!(result, Ok(r#"{"greeting":"Hello Bob"}"#.to_string()));
478    }
479
480    #[tokio::test]
481    async fn test_json_handler_with_args_bad_json() {
482        #[derive(serde::Deserialize)]
483        struct Input {
484            _x: i32,
485        }
486
487        let handler = HandlerWithArgs::new(|_: Input| async move { Json(42) });
488        let result = handler.call("bad").await;
489        assert!(result.is_err());
490        assert!(result.unwrap_err().contains("Failed to deserialize args"));
491    }
492
493    #[tokio::test]
494    async fn test_json_handler_with_state() {
495        struct AppState {
496            prefix: String,
497        }
498
499        #[derive(serde::Deserialize)]
500        struct Input {
501            name: String,
502        }
503
504        #[derive(serde::Serialize)]
505        struct Output {
506            message: String,
507        }
508
509        let state: Arc<dyn Any + Send + Sync> = Arc::new(AppState {
510            prefix: "Hi".to_string(),
511        });
512
513        let handler = HandlerWithState::new(
514            |state: State<Arc<AppState>>, args: Input| async move {
515                Json(Output {
516                    message: format!("{} {}", state.prefix, args.name),
517                })
518            },
519            state,
520        );
521
522        let result = handler.call(r#"{"name":"Charlie"}"#).await;
523        assert_eq!(result, Ok(r#"{"message":"Hi Charlie"}"#.to_string()));
524    }
525
526    #[tokio::test]
527    async fn test_json_handler_with_state_only() {
528        struct AppState {
529            version: String,
530        }
531
532        #[derive(serde::Serialize)]
533        struct Info {
534            version: String,
535        }
536
537        let state: Arc<dyn Any + Send + Sync> = Arc::new(AppState {
538            version: "1.0".to_string(),
539        });
540
541        let handler = HandlerWithStateOnly::new(
542            |state: State<Arc<AppState>>| async move {
543                Json(Info {
544                    version: state.version.clone(),
545                })
546            },
547            state,
548        );
549
550        let result = handler.call("{}").await;
551        assert_eq!(result, Ok(r#"{"version":"1.0"}"#.to_string()));
552    }
553
554    // ─── Result<T, E> return (via IntoHandlerResult) ────────────────────
555
556    #[tokio::test]
557    async fn test_result_handler_fn_ok() {
558        #[derive(serde::Serialize)]
559        struct Data {
560            value: i32,
561        }
562
563        let handler = HandlerFn::new(|| async {
564            Ok::<_, String>(Data { value: 42 })
565        });
566
567        let result = handler.call("{}").await;
568        assert_eq!(result, Ok(r#"{"value":42}"#.to_string()));
569    }
570
571    #[tokio::test]
572    async fn test_result_handler_fn_err() {
573        #[derive(serde::Serialize)]
574        struct Data {
575            value: i32,
576        }
577
578        let handler = HandlerFn::new(|| async {
579            Err::<Data, String>("something went wrong".to_string())
580        });
581
582        let result = handler.call("{}").await;
583        assert_eq!(result, Err("something went wrong".to_string()));
584    }
585
586    #[tokio::test]
587    async fn test_result_handler_with_args_ok() {
588        #[derive(serde::Deserialize)]
589        struct Input {
590            x: i32,
591        }
592
593        #[derive(serde::Serialize)]
594        struct Output {
595            doubled: i32,
596        }
597
598        let handler = HandlerWithArgs::new(|args: Input| async move {
599            Ok::<_, String>(Output { doubled: args.x * 2 })
600        });
601
602        let result = handler.call(r#"{"x":21}"#).await;
603        assert_eq!(result, Ok(r#"{"doubled":42}"#.to_string()));
604    }
605
606    #[tokio::test]
607    async fn test_result_handler_with_args_err() {
608        #[derive(serde::Deserialize)]
609        struct Input {
610            x: i32,
611        }
612
613        let handler = HandlerWithArgs::new(|args: Input| async move {
614            if args.x < 0 {
615                Err::<i32, String>("negative".to_string())
616            } else {
617                Ok(args.x)
618            }
619        });
620
621        let result = handler.call(r#"{"x":-1}"#).await;
622        assert_eq!(result, Err("negative".to_string()));
623    }
624
625    #[tokio::test]
626    async fn test_result_handler_with_state() {
627        struct AppState {
628            threshold: i32,
629        }
630
631        #[derive(serde::Deserialize)]
632        struct Input {
633            value: i32,
634        }
635
636        #[derive(serde::Serialize)]
637        struct Output {
638            accepted: bool,
639        }
640
641        let state: Arc<dyn Any + Send + Sync> = Arc::new(AppState { threshold: 10 });
642
643        let handler = HandlerWithState::new(
644            |state: State<Arc<AppState>>, args: Input| async move {
645                if args.value >= state.threshold {
646                    Ok::<_, String>(Output { accepted: true })
647                } else {
648                    Err("below threshold".to_string())
649                }
650            },
651            state,
652        );
653
654        let ok_result = handler.call(r#"{"value":15}"#).await;
655        assert_eq!(ok_result, Ok(r#"{"accepted":true}"#.to_string()));
656
657        let err_result = handler.call(r#"{"value":5}"#).await;
658        assert_eq!(err_result, Err("below threshold".to_string()));
659    }
660
661    #[tokio::test]
662    async fn test_result_handler_with_state_only() {
663        struct AppState {
664            ready: bool,
665        }
666
667        #[derive(serde::Serialize)]
668        struct Status {
669            ok: bool,
670        }
671
672        let state: Arc<dyn Any + Send + Sync> = Arc::new(AppState { ready: true });
673
674        let handler = HandlerWithStateOnly::new(
675            |state: State<Arc<AppState>>| async move {
676                if state.ready {
677                    Ok::<_, String>(Status { ok: true })
678                } else {
679                    Err("not ready".to_string())
680                }
681            },
682            state,
683        );
684
685        let result = handler.call("{}").await;
686        assert_eq!(result, Ok(r#"{"ok":true}"#.to_string()));
687    }
688}