puzz 0.2.0

A simple and powerful web framework.
Documentation
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;

use puzz_core::{BoxError, Request};
use puzz_route::Params;

pub fn param_raw<'a>(request: &'a Request, name: &str) -> Option<&'a str> {
    params(request).and_then(|params| params.get(name).map(|v| v.as_str()))
}

pub fn param<T>(request: &Request, name: &str) -> Result<T, ExtractParamError>
where
    T: FromStr,
    T::Err: Into<BoxError>,
{
    param_raw(request, name).map_or_else(
        || Err(ExtractParamError::MissingParam { name: name.into() }),
        |param| {
            param
                .parse::<T>()
                .map_err(|e| ExtractParamError::InvalidParam {
                    name: name.into(),
                    source: e.into(),
                })
        },
    )
}

pub fn params(request: &Request) -> Option<&HashMap<String, String>> {
    crate::extract::extension(request).map(|params: &Params| params.get_ref())
}

#[derive(Debug)]
pub enum ExtractParamError {
    MissingParam { name: String },
    InvalidParam { name: String, source: BoxError },
}

impl fmt::Display for ExtractParamError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ExtractParamError::MissingParam { name } => {
                write!(f, "missing route param `{}`", name)
            }
            ExtractParamError::InvalidParam { name, source: _ } => {
                write!(f, "invalid route param `{}`", name)
            }
        }
    }
}

impl std::error::Error for ExtractParamError {}