use std::sync::Arc;
use percent_encoding::percent_decode_str;
use topcoat_core::context::{Cx, request_context};
pub trait PathParam {
type Output<'cx>;
#[doc(hidden)]
fn path_param(cx: &Cx, _: PathParamSealed) -> Self::Output<'_>;
}
#[inline]
#[must_use]
pub fn path_param<T: PathParam + ?Sized>(cx: &Cx) -> T::Output<'_> {
T::path_param(cx, PathParamSealed::new())
}
#[inline]
#[must_use]
#[doc(hidden)]
pub fn raw_path_params(cx: &Cx) -> &RawPathParams {
request_context::<RawPathParams>(cx)
}
#[derive(Debug, Clone, Default)]
pub struct RawPathParams(Vec<(Arc<str>, Box<str>)>);
impl RawPathParams {
pub(crate) fn from_pairs<'pairs>(
pairs: impl IntoIterator<Item = (Arc<str>, &'pairs str)>,
) -> Self {
Self(
pairs
.into_iter()
.map(|(key, value)| {
let value = percent_decode_str(value)
.decode_utf8_lossy()
.into_owned()
.into_boxed_str();
(key, value)
})
.collect(),
)
}
pub fn iter(&self) -> RawPathParamsIter<'_> {
<&Self as IntoIterator>::into_iter(self)
}
}
pub type RawPathParamsIter<'params> = std::iter::Map<
std::slice::Iter<'params, (Arc<str>, Box<str>)>,
fn(&'params (Arc<str>, Box<str>)) -> (&'params str, &'params str),
>;
impl<'params> IntoIterator for &'params RawPathParams {
type Item = (&'params str, &'params str);
type IntoIter = RawPathParamsIter<'params>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter().map(|(key, value)| (&**key, &**value))
}
}
#[doc(hidden)]
#[derive(Debug)]
pub struct PathParamSealed(());
impl PathParamSealed {
pub(crate) fn new() -> Self {
Self(())
}
}