use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf};
use crate::uri::fmt::UriDisplay;
use crate::uri::fmt::{self, Part};
pub trait FromUriParam<P: Part, T> {
type Target: UriDisplay<P>;
fn from_uri_param(param: T) -> Self::Target;
}
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! impl_conversion_ref {
($(($($l:tt)+) $A:ty => $B:ty),* $(,)?) => (
impl_conversion_ref!(@_ $(($($l)+,) $A => $B),*);
);
($($A:ty => $B:ty),* $(,)?) => (
impl_conversion_ref!(@_ $(() $A => $B),*);
);
(@_ $(($($l:tt)*) $A:ty => $B:ty),* $(,)?) => ($(
impl_conversion_ref!([P] ($($l)* P: $crate::uri::fmt::Part) $A => $B);
)*);
($([$P:ty] ($($l:tt)*) $A:ty => $B:ty),* $(,)?) => ($(
impl_conversion_ref!(@_ [$P] ($($l)*) $A => $B);
impl_conversion_ref!(@_ [$P] ('x, $($l)*) &'x $A => $B);
impl_conversion_ref!(@_ [$P] ('x, $($l)*) &'x mut $A => $B);
)*);
($([$P:ty] $A:ty => $B:ty),* $(,)?) => ( impl_conversion_ref!($([$P] () $A => $B),*););
(@_ [$P:ty] ($($l:tt)*) $A:ty => $B:ty) => (
impl<$($l)*> $crate::uri::fmt::FromUriParam<$P, $A> for $B {
type Target = $A;
#[inline(always)] fn from_uri_param(param: $A) -> $A { param }
}
);
}
#[macro_export(local_inner_macros)]
macro_rules! impl_from_uri_param_identity {
($(($($l:tt)*) $T:ty),* $(,)?) => ($( impl_conversion_ref!(($($l)*) $T => $T); )*);
($([$P:ty] ($($l:tt)*) $T:ty),* $(,)?) => ($( impl_conversion_ref!([$P] ($($l)*) $T => $T); )*);
($([$P:ty] $T:ty),* $(,)?) => ($( impl_conversion_ref!([$P] $T => $T); )*);
($($T:ty),* $(,)?) => ($( impl_conversion_ref!($T => $T); )*);
}
use std::borrow::Cow;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::num::{
NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,
NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
};
impl_from_uri_param_identity! {
String,
i8, i16, i32, i64, i128, isize,
u8, u16, u32, u64, u128, usize,
f32, f64, bool,
IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6,
NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,
NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
time::Date, time::Time, time::PrimitiveDateTime,
}
impl_from_uri_param_identity! {
('a) &'a str,
('a) Cow<'a, str>
}
impl_conversion_ref! {
('a) &'a str => String,
('a) String => &'a str
}
impl_from_uri_param_identity!([fmt::Path] ('a) &'a Path);
impl_from_uri_param_identity!([fmt::Path] PathBuf);
impl_conversion_ref! {
[fmt::Path] ('a) &'a Path => PathBuf,
[fmt::Path] ('a) PathBuf => &'a Path,
}
impl_from_uri_param_identity!([fmt::Query] ('a) &'a [u8]);
impl_conversion_ref! {
[fmt::Query] (T, A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>) Vec<A> => Vec<T>,
[fmt::Query] (
T,
A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,
const N: usize
) Vec<A> => [T; N],
[fmt::Query] (
T,
A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,
const N: usize
) [A; N] => Vec<T>,
[fmt::Query] (
T,
A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,
const N: usize
) [A; N] => [T; N],
}
impl<'a> FromUriParam<fmt::Path, &'a str> for PathBuf {
type Target = &'a Path;
#[inline(always)]
fn from_uri_param(param: &'a str) -> &'a Path {
Path::new(param)
}
}
impl<'a, 'b> FromUriParam<fmt::Path, &'a &'b str> for PathBuf {
type Target = &'b Path;
#[inline(always)]
fn from_uri_param(param: &'a &'b str) -> &'b Path {
Path::new(*param)
}
}
impl<A, T: FromUriParam<fmt::Path, A>> FromUriParam<fmt::Path, A> for Option<T> {
type Target = T::Target;
#[inline(always)]
fn from_uri_param(param: A) -> Self::Target {
T::from_uri_param(param)
}
}
impl<A, E, T: FromUriParam<fmt::Path, A>> FromUriParam<fmt::Path, A> for Result<T, E> {
type Target = T::Target;
#[inline(always)]
fn from_uri_param(param: A) -> Self::Target {
T::from_uri_param(param)
}
}
impl<A, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Option<A>> for Option<T> {
type Target = Option<T::Target>;
#[inline(always)]
fn from_uri_param(param: Option<A>) -> Self::Target {
param.map(T::from_uri_param)
}
}
impl<A, E, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Option<A>> for Result<T, E> {
type Target = Option<T::Target>;
#[inline(always)]
fn from_uri_param(param: Option<A>) -> Self::Target {
param.map(T::from_uri_param)
}
}
impl<A, E, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Result<A, E>> for Result<T, E> {
type Target = Result<T::Target, E>;
#[inline(always)]
fn from_uri_param(param: Result<A, E>) -> Self::Target {
param.map(T::from_uri_param)
}
}
impl<A, E, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Result<A, E>> for Option<T> {
type Target = Result<T::Target, E>;
#[inline(always)]
fn from_uri_param(param: Result<A, E>) -> Self::Target {
param.map(T::from_uri_param)
}
}
macro_rules! impl_map_conversion {
($From:ident => $To:ident) => (
impl<K, V, A, B> FromUriParam<fmt::Query, $From<A, B>> for $To<K, V>
where A: UriDisplay<fmt::Query>, K: FromUriParam<fmt::Query, A>,
B: UriDisplay<fmt::Query>, V: FromUriParam<fmt::Query, B>
{
type Target = $From<A, B>;
#[inline(always)]
fn from_uri_param(param: $From<A, B>) -> Self::Target {
param
}
}
);
(& $([$mut:tt])? $From:ident => $To:ident) => (
impl<'a, K, V, A, B> FromUriParam<fmt::Query, &'a $($mut)? $From<A, B>> for $To<K, V>
where A: UriDisplay<fmt::Query>, K: FromUriParam<fmt::Query, A>,
B: UriDisplay<fmt::Query>, V: FromUriParam<fmt::Query, B>
{
type Target = &'a $From<A, B>;
#[inline(always)]
fn from_uri_param(param: &'a $($mut)? $From<A, B>) -> Self::Target {
param
}
}
);
}
impl_map_conversion!(HashMap => HashMap);
impl_map_conversion!(HashMap => BTreeMap);
impl_map_conversion!(BTreeMap => BTreeMap);
impl_map_conversion!(BTreeMap => HashMap);
impl_map_conversion!(&HashMap => HashMap);
impl_map_conversion!(&HashMap => BTreeMap);
impl_map_conversion!(&BTreeMap => BTreeMap);
impl_map_conversion!(&BTreeMap => HashMap);
impl_map_conversion!(&[mut] HashMap => HashMap);
impl_map_conversion!(&[mut] HashMap => BTreeMap);
impl_map_conversion!(&[mut] BTreeMap => BTreeMap);
impl_map_conversion!(&[mut] BTreeMap => HashMap);