1use std::convert::Infallible;
2use std::error::Error as StdError;
3use std::fmt;
4use std::pin::Pin;
5use std::str::FromStr;
6use std::{future::Future, ops::Deref};
7
8use types::header::RequestHeader;
9
10use crate::error::{ClientErrorKind, ErrorKind, ServerErrorKind};
11use crate::state::StateValidation;
12use crate::{
13 routes::{ParamsNames, PathParams},
14 state::State,
15 Request, Resources,
16};
17
18#[non_exhaustive]
19pub struct Validate<'a> {
20 pub name: &'a str,
21 pub params: &'a ParamsNames<'a>,
22 pub state: &'a mut StateValidation,
23 pub resources: &'a Resources,
24}
25
26#[non_exhaustive]
27pub struct Prepare<'a> {
28 pub name: &'a str,
29 pub header: &'a RequestHeader,
30 pub params: &'a PathParams,
31 pub state: &'a mut State,
32 pub resources: &'a Resources,
33}
34
35#[non_exhaustive]
36pub struct Extract<'a, 'b, P, R> {
37 pub prepared: P,
38 pub name: &'b str,
39 pub request: &'b mut Option<R>,
40 pub params: &'a PathParams,
41 pub state: &'a State,
42 pub resources: &'a Resources,
43}
44
45pub trait Extractor<'a, R> {
46 type Error: ExtractorError;
47 type Prepared;
48
49 fn validate(validate: Validate<'_>);
50
51 fn prepare(
52 prepare: Prepare<'_>,
53 ) -> Pin<
54 Box<
55 dyn Future<Output = Result<Self::Prepared, Self::Error>>
56 + Send
57 + '_,
58 >,
59 >;
60
61 fn extract(
62 extract: Extract<'a, '_, Self::Prepared, R>,
63 ) -> Result<Self, Self::Error>
64 where
65 Self: Sized;
66}
67
68pub trait ExtractorError: StdError + Send + Sync {
69 fn error_kind(&self) -> ErrorKind;
70
71 fn into_std(self) -> Box<dyn StdError + Send + Sync>;
72}
73
74impl ExtractorError for Infallible {
75 fn error_kind(&self) -> ErrorKind {
76 unreachable!()
77 }
78
79 fn into_std(self) -> Box<dyn StdError + Send + Sync> {
80 unreachable!()
81 }
82}
83
84#[derive(Debug)]
85pub struct InternalError<E>(pub E);
86
87impl<E> ExtractorError for InternalError<E>
88where
89 E: Into<Box<dyn StdError + Send + Sync>> + StdError + Send + Sync,
90{
91 fn error_kind(&self) -> ErrorKind {
92 ServerErrorKind::InternalServerError.into()
93 }
94
95 fn into_std(self) -> Box<dyn StdError + Send + Sync> {
96 self.0.into()
97 }
98}
99
100impl<E> StdError for InternalError<E> where E: StdError {}
101
102impl<E> fmt::Display for InternalError<E>
103where
104 E: fmt::Display,
105{
106 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107 self.0.fmt(f)
108 }
109}
110
111impl<E> From<E> for InternalError<E> {
112 fn from(e: E) -> Self {
113 Self(e)
114 }
115}
116
117impl<'a> Validate<'a> {
118 pub fn new(
119 name: &'a str,
120 params: &'a ParamsNames<'a>,
121 state: &'a mut StateValidation,
122 resources: &'a Resources,
123 ) -> Self {
124 Self {
125 name,
126 params,
127 state,
128 resources,
129 }
130 }
131}
132
133impl<'a> Prepare<'a> {
134 pub fn new(
135 name: &'a str,
136 header: &'a RequestHeader,
137 params: &'a PathParams,
138 state: &'a mut State,
139 resources: &'a Resources,
140 ) -> Self {
141 Self {
142 name,
143 header,
144 params,
145 state,
146 resources,
147 }
148 }
149}
150
151impl<'a, 'b, P, R> Extract<'a, 'b, P, R> {
152 pub fn new(
153 prepared: P,
154 name: &'b str,
155 request: &'b mut Option<R>,
156 params: &'a PathParams,
157 state: &'a State,
158 resources: &'a Resources,
159 ) -> Self {
160 Self {
161 prepared,
162 name,
163 request,
164 params,
165 state,
166 resources,
167 }
168 }
169}
170
171pub struct Res<'a, T: ?Sized>(&'a T);
172
173impl<'a, T, R> Extractor<'a, R> for Res<'a, T>
174where
175 T: Send + Sync + 'static,
176{
177 type Error = Infallible;
178 type Prepared = ();
179
180 extractor_validate!(|validate| {
181 validate.resources.get::<T>().unwrap();
182 });
183
184 extractor_prepare!();
185
186 extractor_extract!(|extract| {
187 Ok(Res(extract.resources.get::<T>().unwrap()))
188 });
189}
190
191impl<T> Deref for Res<'_, T> {
192 type Target = T;
193
194 fn deref(&self) -> &Self::Target {
195 self.0
196 }
197}
198
199impl<'a> Extractor<'a, &'a mut Request> for &'a mut Request {
200 type Error = Infallible;
201 type Prepared = ();
202
203 extractor_validate!();
204
205 extractor_prepare!();
206
207 fn extract(
208 extract: Extract<'a, '_, Self::Prepared, &'a mut Request>,
209 ) -> Result<Self, Self::Error>
210 where
211 Self: Sized,
212 {
213 Ok(extract.request.take().unwrap())
214 }
215}
216
217impl<'a, R> Extractor<'a, R> for &'a RequestHeader {
218 type Error = Infallible;
219 type Prepared = ();
220
221 extractor_validate!();
222
223 extractor_prepare!(|prepare| {
224 if !prepare.state.contains::<RequestHeader>() {
225 prepare
226 .state
227 .insert::<RequestHeader>(prepare.header.clone());
228 }
229
230 Ok(())
231 });
232
233 extractor_extract!(|extract| { Ok(extract.state.get().unwrap()) });
234}
235
236pub type PathStr = PathParam<str>;
237
238#[derive(Debug, Clone, PartialEq, Eq)]
239#[repr(transparent)]
240pub struct PathParam<T: ?Sized>(T);
241
242impl<'a, T, R> Extractor<'a, R> for PathParam<T>
243where
244 T: Send + Sync + FromStr + 'a,
245 T::Err: StdError + Send + Sync + 'static,
246{
247 type Error = PathError<T::Err>;
248 type Prepared = ();
249
250 extractor_validate!(|validate| {
251 assert!(
252 validate.params.exists(validate.name),
253 "Path parameter `{}` does not exist",
254 validate.name
255 );
256 });
257
258 extractor_prepare!();
259
260 extractor_extract!(|extract| {
261 extract
262 .params
263 .parse(extract.name)
264 .map(PathParam)
265 .map_err(PathError)
266 });
267}
268
269impl<'a, R> Extractor<'a, R> for &'a PathParam<str> {
270 type Error = Infallible;
271 type Prepared = ();
272
273 extractor_validate!(|validate| {
274 assert!(
275 validate.params.exists(validate.name),
276 "Path parameter `{}` does not exist",
277 validate.name
278 );
279 });
280
281 extractor_prepare!();
282
283 extractor_extract!(|extract| {
284 let s = extract.params.get(extract.name).unwrap();
285
286 let s: &'a PathParam<str> =
288 unsafe { &*(s as *const str as *const PathParam<str>) };
289
290 Ok(s)
291 });
292}
293
294impl<T> Deref for PathParam<T>
295where
296 T: ?Sized,
297{
298 type Target = T;
299
300 fn deref(&self) -> &Self::Target {
301 &self.0
302 }
303}
304
305impl<T> fmt::Display for PathParam<T>
306where
307 T: fmt::Display + ?Sized,
308{
309 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
310 self.0.fmt(f)
311 }
312}
313
314#[derive(Debug)]
315pub struct PathError<T>(pub T);
316
317impl<T> fmt::Display for PathError<T>
318where
319 T: fmt::Display,
320{
321 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
322 write!(f, "Failed to parse path parameter: {}", self.0)
323 }
324}
325
326impl<T> StdError for PathError<T>
327where
328 T: StdError + 'static,
329{
330 fn source(&self) -> Option<&(dyn StdError + 'static)> {
331 Some(&self.0)
332 }
333}
334
335impl<T> ExtractorError for PathError<T>
336where
337 T: StdError + Send + Sync + 'static,
338{
339 fn error_kind(&self) -> ErrorKind {
340 ErrorKind::Client(ClientErrorKind::BadRequest)
341 }
342
343 fn into_std(self) -> Box<dyn StdError + Send + Sync> {
344 Box::new(self.0)
345 }
346}
347
348impl<'a, R: 'a> Extractor<'a, R> for &'a Resources {
349 type Error = Infallible;
350 type Prepared = ();
351
352 extractor_validate!();
353
354 extractor_prepare!();
355
356 extractor_extract!(|extract| { Ok(extract.resources) });
357}