uri-template-core 0.1.0

RFC6570 URI Template library for Rust, with parsing, expansion, compile-time checked macros, and no_std support.
Documentation
use super::Value;
use alloc::{borrow::Cow, string::String};
use core::{hash::Hash, ops::Deref};

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Scalar<'a>(pub(crate) Cow<'a, str>);
impl<'a> Scalar<'a> {
    pub fn into_static(self) -> Scalar<'static> {
        Scalar(Cow::Owned(self.0.into_owned()))
    }
}
impl<'a> Deref for Scalar<'a> {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl<'a> From<&'a str> for Scalar<'a> {
    fn from(value: &'a str) -> Self {
        Self(Cow::Borrowed(value))
    }
}
impl<'a> From<String> for Scalar<'a> {
    fn from(value: String) -> Self {
        Self(Cow::Owned(value))
    }
}

macro_rules! impl_from_display_for_scalar {
    ($($ty:ty),+ $(,)?) => {
        $(
            impl<'a> From<$ty> for Scalar<'a> {
                fn from(value: $ty) -> Self {
                    Scalar(Cow::Owned(value.to_string()))
                }
            }
        )+
    };
}

impl_from_display_for_scalar!(i8, i16, i32, i64, i128);
impl_from_display_for_scalar!(u8, u16, u32, u64, u128);
impl_from_display_for_scalar!(bool);
#[cfg(feature = "std")]
impl_from_display_for_scalar!(std::net::IpAddr);

impl<'v, 's: 'v, T> From<T> for Value<'v, 's>
where
    T: Into<Scalar<'v>>,
{
    fn from(value: T) -> Self {
        Self::Scalar(value.into())
    }
}

impl<'v, 's: 'v, T> From<&'v [T]> for Value<'v, 's>
where
    &'v T: Into<Scalar<'s>>,
{
    fn from(value: &'v [T]) -> Self {
        let value = value.iter().map(Into::into).collect();
        Self::List(Cow::Owned(value))
    }
}

impl<'v, 's: 'v, T, const N: usize> From<[T; N]> for Value<'v, 's>
where
    [T; N]: 'v,
    T: Into<Scalar<'s>>,
{
    fn from(value: [T; N]) -> Self {
        let value = value.map(Into::into).to_vec();
        Self::List(Cow::Owned(value))
    }
}

impl<'v, 's: 'v, T> From<Vec<T>> for Value<'v, 's>
where
    T: Into<Scalar<'s>>,
{
    fn from(value: Vec<T>) -> Self {
        let value = value.into_iter().map(Into::into).collect();
        Self::List(Cow::Owned(value))
    }
}

impl<'v, 's: 'v, K, V> From<&'v [(K, V)]> for Value<'v, 's>
where
    &'v K: Into<Scalar<'s>>,
    &'v V: Into<Scalar<'s>>,
{
    fn from(value: &'v [(K, V)]) -> Self {
        let value = value
            .iter()
            .map(|(k, v)| (Into::into(k), Into::into(v)))
            .collect();
        Self::Keys(Cow::Owned(value))
    }
}

impl<'v, 's: 'v, K, V, const N: usize> From<[(K, V); N]> for Value<'v, 's>
where
    [(K, V); N]: 'v,
    K: Into<Scalar<'s>>,
    V: Into<Scalar<'s>>,
{
    fn from(value: [(K, V); N]) -> Self {
        let value = value.map(|(k, v)| (Into::into(k), Into::into(v))).to_vec();
        Self::Keys(Cow::Owned(value))
    }
}