awmpde_structs 0.7.1

awmpde used for deriving multipart request for actix web 3
Documentation
use super::*;

use image::io::Reader as ImgReader;
use image::{Bgr, Bgra, ImageFormat};

#[derive(Deref, DerefMut, Debug)]
pub struct ImageBuffer<P: image::Pixel, Cont>(pub image::ImageBuffer<P, Cont>);

#[derive(Deref, DerefMut)]
pub struct DynamicImage(pub image::DynamicImage);

impl FromField for DynamicImage {
    type Error = Error;
    type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;

    fn from_field(field: actix_multipart::Field) -> Self::Future {
        async move {
            let ct = field.content_type().clone();
            let vec = Vec::<u8>::from_field(field).await.unwrap();
            let tp = match ct.subtype() {
                mime::JPEG => Some(ImageFormat::Jpeg),
                mime::PNG => Some(ImageFormat::Png),
                mime::GIF => Some(ImageFormat::Gif),
                mime::BMP => Some(ImageFormat::Bmp),
                _ => None,
            };
            let cur = Cursor::new(&*vec);
            let rdr = match tp {
                Some(fmt) => ImgReader::with_format(cur, fmt),
                None => ImgReader::new(cur)
                    .with_guessed_format()
                    .expect("Cursor io never fails"),
            };

            Ok(Self(rdr.decode()?))
        }
        .boxed_local()
    }
}

macro_rules! ff_img(
	{ $ty:ident, $img:ty, $into:ident } => {
		#[derive(Deref, DerefMut, Debug)]
		pub struct $ty(pub $img);

		impl FromField for $ty {
			type Error = Error;
			type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;

			fn from_field(field: actix_multipart::Field) -> Self::Future {
				async move {
					let img = DynamicImage::from_field(field).await?;
					let img = img.0.$into();
					Ok(Self(img))
				}
				.boxed_local()
			}
		}
	};
);

#[cfg(feature = "mozjpeg")]
macro_rules! ff_img_mozjpeg(
	{ $ty:ident, $img:ty, $subp:ty, $into:ident, $into_img:ident } => {
		#[derive(Deref, DerefMut, Debug, Clone)]
		pub struct $ty(pub $img);

		impl FromField for $ty {
			type Error = Error;
			type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;

			fn from_field(field: actix_multipart::Field) -> Self::Future {
				use mozjpeg::{decompress::DctMethod, Decompress, ALL_MARKERS};

				if *field.content_type() == mime::IMAGE_JPEG {
					async move {
						let buf = Vec::<u8>::from_field(field).await.unwrap();
						let mut decomp = Decompress::with_markers(ALL_MARKERS)
							.from_mem(&buf[..])
							.map_err(|_| Error::MozjpgDecodeError)?;
						decomp.dct_method(DctMethod::IntegerFast);

						let (w, h) = decomp.size();
						let mut decomp = decomp.$into()
							.map_err(|_| Error::MozjpgDecodeError)?;
						let out = decomp
							.read_scanlines::<$subp>()
							.ok_or(Error::MozjpgDecodeError)?;

						let out: &[$subp] = &*out;
						let sz = out.len() * std::mem::size_of::<$subp>();
						let out: &[u8] = unsafe {
							std::slice::from_raw_parts(
                                out.as_ptr() as *const u8,
                                sz,
                            )
						};

						Ok(Self(<$img>::from_raw(w as u32, h as u32, out.to_vec())
										 .ok_or(Error::MozjpgDecodeError)?))
					}
					.boxed_local()
				} else {
					async move {
						let img = DynamicImage::from_field(field).await?;
						let img = img.0.$into_img();
						Ok(Self(img))
					}
					.boxed_local()
				}
			}
		}
	};
);

#[cfg(feature = "mozjpeg")]
ff_img_mozjpeg!(RgbImage, image::RgbImage, [u8; 3], rgb, into_rgb8);
#[cfg(not(feature = "mozjpeg"))]
ff_img!(RgbImage, image::RgbImage, into_rgb8);

#[cfg(feature = "mozjpeg")]
ff_img_mozjpeg!(RgbaImage, image::RgbaImage, [u8; 4], rgba, into_rgba8);
#[cfg(not(feature = "mozjpeg"))]
ff_img!(RgbaImage, image::RgbaImage, into_rgba8);

#[cfg(feature = "mozjpeg")]
ff_img_mozjpeg!(GrayImage, image::GrayImage, [u8; 1], grayscale, into_luma8);
#[cfg(not(feature = "mozjpeg"))]
ff_img!(GrayImage, image::GrayImage, into_luma8);

ff_img!(GrayAlphaImage, image::GrayAlphaImage, into_luma_alpha8);
ff_img!(BgrImage, image::ImageBuffer<Bgr<u8>, Vec<u8>>, into_bgr8);
ff_img!(BgraImage, image::ImageBuffer<Bgra<u8>, Vec<u8>>, into_bgra8);