predawn 0.9.0

Predawn is a Rust web framework like Spring Boot.
Documentation
use std::{
    any,
    collections::{BTreeSet, HashSet},
    future::Future,
    hash::{BuildHasher, Hash},
    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
};

use bytes::Bytes;
use http::Uri;
use multer::Field;
use snafu::ResultExt;

use crate::response_error::{
    ByParseFieldSnafu, DuplicateFieldSnafu, IncorrectNumberOfFieldsSnafu, MissingFieldSnafu,
    MultipartError, ParseErrorAtNameSnafu,
};

pub trait ParseField: Sized + Send {
    type Holder: Send;

    fn default_holder(name: &'static str) -> Self::Holder;

    fn parse_field(
        holder: Self::Holder,
        field: Field<'static>,
        name: &'static str,
    ) -> impl Future<Output = Result<Self::Holder, MultipartError>> + Send;

    fn extract(holder: Self::Holder, name: &'static str) -> Result<Self, MultipartError>;
}

impl<T: ParseField> ParseField for Option<T> {
    type Holder = T::Holder;

    fn default_holder(name: &'static str) -> Self::Holder {
        T::default_holder(name)
    }

    async fn parse_field(
        holder: Self::Holder,
        field: Field<'static>,
        name: &'static str,
    ) -> Result<Self::Holder, MultipartError> {
        T::parse_field(holder, field, name).await
    }

    fn extract(holder: Self::Holder, name: &'static str) -> Result<Self, MultipartError> {
        match T::extract(holder, name) {
            Ok(o) => Ok(Some(o)),
            Err(MultipartError::MissingField { .. }) => Ok(None),
            Err(e) => Err(e),
        }
    }
}

impl<T: ParseField> ParseField for Vec<T> {
    type Holder = Result<Self, MultipartError>;

    fn default_holder(name: &'static str) -> Self::Holder {
        MissingFieldSnafu { name }.fail()
    }

    async fn parse_field(
        holder: Self::Holder,
        field: Field<'static>,
        name: &'static str,
    ) -> Result<Self::Holder, MultipartError> {
        let item_holder = T::parse_field(T::default_holder(name), field, name).await?;
        let item = T::extract(item_holder, name)?;

        let mut holder = holder.unwrap_or_default();
        holder.push(item);
        Ok(Ok(holder))
    }

    fn extract(holder: Self::Holder, _: &'static str) -> Result<Self, MultipartError> {
        holder
    }
}

impl<T: ParseField, const N: usize> ParseField for [T; N] {
    type Holder = Result<Vec<T>, MultipartError>;

    fn default_holder(name: &'static str) -> Self::Holder {
        MissingFieldSnafu { name }.fail()
    }

    async fn parse_field(
        holder: Self::Holder,
        field: Field<'static>,
        name: &'static str,
    ) -> Result<Self::Holder, MultipartError> {
        let item_holder = T::parse_field(T::default_holder(name), field, name).await?;
        let item = T::extract(item_holder, name)?;

        let mut holder = holder.unwrap_or_else(|_| Vec::with_capacity(N));
        holder.push(item);
        Ok(Ok(holder))
    }

    fn extract(holder: Self::Holder, name: &'static str) -> Result<Self, MultipartError> {
        Self::try_from(holder?).map_err(|v| {
            IncorrectNumberOfFieldsSnafu {
                name,
                expected: N,
                actual: v.len(),
            }
            .build()
        })
    }
}

impl<T, S> ParseField for HashSet<T, S>
where
    T: ParseField + Hash + Eq,
    S: Send + Default + BuildHasher,
{
    type Holder = Result<Self, MultipartError>;

    fn default_holder(name: &'static str) -> Self::Holder {
        MissingFieldSnafu { name }.fail()
    }

    async fn parse_field(
        holder: Self::Holder,
        field: Field<'static>,
        name: &'static str,
    ) -> Result<Self::Holder, MultipartError> {
        let item_holder = T::parse_field(T::default_holder(name), field, name).await?;
        let item = T::extract(item_holder, name)?;

        let mut holder = holder.unwrap_or_default();
        holder.insert(item);
        Ok(Ok(holder))
    }

    fn extract(holder: Self::Holder, _: &'static str) -> Result<Self, MultipartError> {
        holder
    }
}

impl<T: ParseField + Ord> ParseField for BTreeSet<T> {
    type Holder = Result<Self, MultipartError>;

    fn default_holder(name: &'static str) -> Self::Holder {
        MissingFieldSnafu { name }.fail()
    }

    async fn parse_field(
        holder: Self::Holder,
        field: Field<'static>,
        name: &'static str,
    ) -> Result<Self::Holder, MultipartError> {
        let item_holder = T::parse_field(T::default_holder(name), field, name).await?;
        let item = T::extract(item_holder, name)?;

        let mut holder = holder.unwrap_or_default();
        holder.insert(item);
        Ok(Ok(holder))
    }

    fn extract(holder: Self::Holder, _: &'static str) -> Result<Self, MultipartError> {
        holder
    }
}

macro_rules! some_impl {
    ($ty:ty, $ident:ident) => {
        impl ParseField for $ty {
            type Holder = Result<Self, MultipartError>;

            fn default_holder(name: &'static str) -> Self::Holder {
                MissingFieldSnafu { name }.fail()
            }

            async fn parse_field(
                holder: Self::Holder,
                field: Field<'static>,
                name: &'static str,
            ) -> Result<Self::Holder, MultipartError> {
                if holder.is_ok() {
                    return DuplicateFieldSnafu { name }.fail();
                }

                let f = field.$ident().await.context(ByParseFieldSnafu { name })?;
                Ok(Ok(f))
            }

            fn extract(holder: Self::Holder, _: &'static str) -> Result<Self, MultipartError> {
                holder
            }
        }
    };
}

some_impl!(String, text);
some_impl!(Bytes, bytes);

macro_rules! some_impl_by_parse_str {
    ($($ty:ty),+ $(,)?) => {
        $(
            impl ParseField for $ty {
                type Holder = Result<Self, MultipartError>;

                fn default_holder(name: &'static str) -> Self::Holder {
                    MissingFieldSnafu { name }.fail()
                }

                async fn parse_field(
                    holder: Self::Holder,
                    field: Field<'static>,
                    name: &'static str,
                ) -> Result<Self::Holder, MultipartError> {
                    if holder.is_ok() {
                        return DuplicateFieldSnafu { name }.fail();
                    }

                    let text = <String as ParseField>::parse_field(
                        <String as ParseField>::default_holder(name),
                        field,
                        name,
                    )
                    .await??;

                    match text.parse() {
                        Ok(o) => Ok(Ok(o)),
                        Err(_) => Err(
                            ParseErrorAtNameSnafu {
                                name,
                                value: text,
                                expected_type: any::type_name::<Self>(),
                            }
                            .build()
                        ),
                    }
                }

                fn extract(holder: Self::Holder, _: &'static str) -> Result<Self, MultipartError> {
                    holder
                }
            }
        )+
    };
}

some_impl_by_parse_str![
    bool,
    char,
    i8,
    i16,
    i32,
    i64,
    i128,
    isize,
    u8,
    u16,
    u32,
    u64,
    u128,
    usize,
    f32,
    f64,
    IpAddr,
    Ipv4Addr,
    Ipv6Addr,
    SocketAddr,
    SocketAddrV4,
    SocketAddrV6,
    Uri,
];