1mod de;
4
5use std::{
6 fmt::Display,
7 ops::{Deref, DerefMut},
8 str::FromStr,
9};
10
11use serde::de::DeserializeOwned;
12
13use crate::{
14 Error, FromRequest, IntoResponse, Request, RequestExt, Response, StatusCode, ThisError,
15};
16
17#[allow(clippy::redundant_pub_crate)]
18pub(crate) use de::PathDeserializer;
19
20#[derive(Debug, Clone)]
22pub struct Params<T = Vec<(String, String)>>(pub T);
23
24impl<T> AsRef<T> for Params<T> {
25 fn as_ref(&self) -> &T {
26 &self.0
27 }
28}
29
30impl<T> Deref for Params<T> {
31 type Target = T;
32
33 fn deref(&self) -> &T {
34 &self.0
35 }
36}
37
38impl<T> DerefMut for Params<T> {
39 fn deref_mut(&mut self) -> &mut T {
40 &mut self.0
41 }
42}
43
44impl From<Vec<(&str, &str)>> for Params {
45 fn from(v: Vec<(&str, &str)>) -> Self {
46 Self(
47 v.into_iter()
48 .map(|(k, v)| (k.to_string(), v.to_string()))
49 .collect(),
50 )
51 }
52}
53
54impl Params {
55 pub fn find<T>(&self, name: &str) -> Result<T, ParamsError>
61 where
62 T: FromStr,
63 T::Err: Display,
64 {
65 self.iter()
66 .find(|p| p.0 == name)
67 .ok_or_else(|| {
68 let mut s = String::new();
69 s.push_str("missing ");
70 s.push_str(name);
71 s.push_str(" param");
72 ParamsError::SingleParse(s)
73 })?
74 .1
75 .parse()
76 .map_err(|e: T::Err| ParamsError::SingleParse(e.to_string()))
77 }
78}
79
80impl<T> FromRequest for Params<T>
81where
82 T: DeserializeOwned,
83{
84 type Error = ParamsError;
85
86 async fn extract(req: &mut Request) -> Result<Self, Self::Error> {
87 req.params().map(Params)
88 }
89}
90
91#[derive(ThisError, Debug)]
93pub enum ParamsError {
94 #[error("{}", .0)]
96 SingleParse(String),
97 #[error(transparent)]
99 Parse(#[from] serde::de::value::Error),
100 #[error("params is empty")]
102 Empty,
103}
104
105impl IntoResponse for ParamsError {
106 fn into_response(self) -> Response {
107 (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response()
108 }
109}
110
111impl From<ParamsError> for Error {
112 fn from(e: ParamsError) -> Self {
113 e.into_error()
114 }
115}