puzz/extract/
param.rs

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 {}