intrepid_core/extract/
path.rs1use serde::de::DeserializeOwned;
2
3use crate::{ActionContext, Context, Extractor, Frame, MessageFrame, PathError};
4
5#[derive(Clone, Debug, PartialEq, Eq)]
40pub struct Path<T>(pub T)
41where
42 T: DeserializeOwned;
43
44impl<State, T> Extractor<State> for Path<T>
45where
46 T: DeserializeOwned,
47 State: std::fmt::Debug + Clone + Send + Sync + 'static,
48{
49 type Error = PathError;
50
51 fn extract(frame: Frame, context: &Context<State>) -> Result<Self, Self::Error> {
52 match (frame, &context.action) {
53 (Frame::Message(MessageFrame { uri, .. }), ActionContext::System(system_context)) => {
54 let capture = system_context.router.capture::<T>(uri)?;
55
56 Ok(Self(capture))
57 }
58 (_, ActionContext::System(_)) => Err(PathError::FrameIsNotAMessage),
59 _ => Err(PathError::IncorrectActionContext),
60 }
61 }
62}
63
64#[tokio::test]
65async fn attempts_to_extract_given_types() -> Result<(), tower::BoxError> {
66 use crate::SystemContext;
67
68 let id = uuid::Uuid::new_v4();
69 let frame = Frame::message(format!("/uri/{id}"), (), ());
70 let mut router = crate::Router::<()>::new();
71
72 router.insert("/uri/:id", || async {})?;
73
74 let context = Context::from_action(SystemContext::from(router).into());
75
76 let Path((extracted,)): Path<(uuid::Uuid,)> = Path::extract(frame, &context)?;
77
78 assert_eq!(extracted, id);
79
80 Ok(())
81}
82
83#[tokio::test]
84async fn non_frame_messages_error() -> Result<(), tower::BoxError> {
85 use crate::{Router, SystemContext};
86
87 let frame = Frame::default();
88 let context = Context::from_action(SystemContext::<()>::from(Router::default()).into());
89
90 let attempt = Path::<()>::extract(frame, &context);
91
92 assert!(
93 matches!(attempt.unwrap_err(), PathError::FrameIsNotAMessage),
94 "expected a frame is not a message error"
95 );
96
97 Ok(())
98}
99
100#[tokio::test]
101async fn non_system_contexts_error() -> Result<(), tower::BoxError> {
102 let frame = Frame::default();
103 let context = Context::<()>::default();
104 let attempt = Path::<()>::extract(frame, &context);
105
106 assert!(
107 matches!(attempt.unwrap_err(), PathError::IncorrectActionContext),
108 "expected an incorrect action context error"
109 );
110
111 Ok(())
112}