1use std::collections::HashMap;
2use std::fmt;
3use std::str::FromStr;
4
5use puzz_core::{BoxError, Request};
6use puzz_route::Params;
7
8pub fn param_raw<'a>(request: &'a Request, name: &str) -> Option<&'a str> {
9 params(request).and_then(|params| params.get(name).map(|v| v.as_str()))
10}
11
12pub fn param<T>(request: &Request, name: &str) -> Result<T, ExtractParamError>
13where
14 T: FromStr,
15 T::Err: Into<BoxError>,
16{
17 param_raw(request, name).map_or_else(
18 || Err(ExtractParamError::MissingParam { name: name.into() }),
19 |param| {
20 param
21 .parse::<T>()
22 .map_err(|e| ExtractParamError::InvalidParam {
23 name: name.into(),
24 source: e.into(),
25 })
26 },
27 )
28}
29
30pub fn params(request: &Request) -> Option<&HashMap<String, String>> {
31 crate::extract::extension(request).map(|params: &Params| params.get_ref())
32}
33
34#[derive(Debug)]
35pub enum ExtractParamError {
36 MissingParam { name: String },
37 InvalidParam { name: String, source: BoxError },
38}
39
40impl fmt::Display for ExtractParamError {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 ExtractParamError::MissingParam { name } => {
44 write!(f, "missing route param `{}`", name)
45 }
46 ExtractParamError::InvalidParam { name, source: _ } => {
47 write!(f, "invalid route param `{}`", name)
48 }
49 }
50 }
51}
52
53impl std::error::Error for ExtractParamError {}