predawn 0.9.0

Predawn is a Rust web framework like Spring Boot.
Documentation
use http_body_util::BodyExt;
use mime::{FORM_DATA, MULTIPART};
use multer::Field;
use predawn_core::{
    body::RequestBody,
    from_request::FromRequest,
    media_type::{has_media_type, MediaType, RequestMediaType},
    request::Head,
};
use snafu::ResultExt;

use crate::response_error::{
    ByParseMultipartSnafu, InvalidMultipartContentTypeSnafu, MultipartError,
};

#[doc(hidden)]
#[derive(Debug)]
pub struct Multipart(multer::Multipart<'static>);

impl<'a> FromRequest<'a> for Multipart {
    type Error = MultipartError;

    async fn from_request(head: &'a mut Head, body: RequestBody) -> Result<Self, Self::Error> {
        let content_type = head.content_type().unwrap_or_default();

        if <Multipart as RequestMediaType>::check_content_type(content_type) {
            let boundary = multer::parse_boundary(content_type).context(ByParseMultipartSnafu)?;
            let multipart = multer::Multipart::new(body.into_data_stream(), boundary);
            Ok(Multipart(multipart))
        } else {
            InvalidMultipartContentTypeSnafu.fail()
        }
    }
}

impl Multipart {
    pub async fn next_field(&mut self) -> Result<Option<Field<'static>>, MultipartError> {
        self.0.next_field().await.context(ByParseMultipartSnafu)
    }
}

impl MediaType for Multipart {
    const MEDIA_TYPE: &'static str = "multipart/form-data";
}

impl RequestMediaType for Multipart {
    fn check_content_type(content_type: &str) -> bool {
        has_media_type(
            content_type,
            MULTIPART.as_str(),
            FORM_DATA.as_str(),
            FORM_DATA.as_str(),
            None,
        )
    }
}