#![allow(unsafe_code, reason = "unsafe is required for bytemuck unsafe impls")]
use crate::{Compose, Extend, Fill, ImageAlphaType, ImageFormat, ImageQuality, Mix};
unsafe impl bytemuck::NoUninit for Compose {}
unsafe impl bytemuck::Zeroable for Compose {}
unsafe impl bytemuck::checked::CheckedBitPattern for Compose {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
use bytemuck::Contiguous;
*bits <= Self::MAX_VALUE
}
}
unsafe impl bytemuck::Contiguous for Compose {
type Int = u8;
const MIN_VALUE: u8 = Self::Clear as u8;
const MAX_VALUE: u8 = Self::PlusLighter as u8;
}
unsafe impl bytemuck::NoUninit for Extend {}
unsafe impl bytemuck::Zeroable for Extend {}
unsafe impl bytemuck::checked::CheckedBitPattern for Extend {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
use bytemuck::Contiguous;
*bits <= Self::MAX_VALUE
}
}
unsafe impl bytemuck::Contiguous for Extend {
type Int = u8;
const MIN_VALUE: u8 = Self::Pad as u8;
const MAX_VALUE: u8 = Self::Reflect as u8;
}
unsafe impl bytemuck::NoUninit for Fill {}
unsafe impl bytemuck::Zeroable for Fill {}
unsafe impl bytemuck::checked::CheckedBitPattern for Fill {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
use bytemuck::Contiguous;
*bits <= Self::MAX_VALUE
}
}
unsafe impl bytemuck::Contiguous for Fill {
type Int = u8;
const MIN_VALUE: u8 = Self::NonZero as u8;
const MAX_VALUE: u8 = Self::EvenOdd as u8;
}
unsafe impl bytemuck::NoUninit for ImageAlphaType {}
unsafe impl bytemuck::Zeroable for ImageAlphaType {}
unsafe impl bytemuck::checked::CheckedBitPattern for ImageAlphaType {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
use bytemuck::Contiguous;
*bits <= Self::MAX_VALUE
}
}
unsafe impl bytemuck::Contiguous for ImageAlphaType {
type Int = u8;
const MIN_VALUE: u8 = Self::Alpha as u8;
const MAX_VALUE: u8 = Self::AlphaPremultiplied as u8;
}
unsafe impl bytemuck::NoUninit for ImageFormat {}
unsafe impl bytemuck::Zeroable for ImageFormat {}
unsafe impl bytemuck::checked::CheckedBitPattern for ImageFormat {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
use bytemuck::Contiguous;
*bits <= Self::MAX_VALUE
}
}
unsafe impl bytemuck::Contiguous for ImageFormat {
type Int = u8;
const MIN_VALUE: u8 = Self::Rgba8 as u8;
const MAX_VALUE: u8 = Self::Bgra8 as u8;
}
unsafe impl bytemuck::NoUninit for ImageQuality {}
unsafe impl bytemuck::Zeroable for ImageQuality {}
unsafe impl bytemuck::checked::CheckedBitPattern for ImageQuality {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
use bytemuck::Contiguous;
*bits <= Self::MAX_VALUE
}
}
unsafe impl bytemuck::Contiguous for ImageQuality {
type Int = u8;
const MIN_VALUE: u8 = Self::Low as u8;
const MAX_VALUE: u8 = Self::High as u8;
}
unsafe impl bytemuck::NoUninit for Mix {}
unsafe impl bytemuck::Zeroable for Mix {}
unsafe impl bytemuck::checked::CheckedBitPattern for Mix {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
use bytemuck::Contiguous;
*bits <= Self::MAX_VALUE
}
}
unsafe impl bytemuck::Contiguous for Mix {
type Int = u8;
const MIN_VALUE: u8 = Self::Normal as u8;
const MAX_VALUE: u8 = Self::Luminosity as u8;
}
#[cfg(test)]
mod tests {
use crate::{Compose, Extend, Fill, ImageAlphaType, ImageFormat, ImageQuality, Mix};
use bytemuck::{Contiguous, Zeroable, checked::try_from_bytes};
use core::ptr;
#[test]
fn checked_bit_pattern() {
let valid_zero = bytemuck::bytes_of(&0_u8);
let valid_one = bytemuck::bytes_of(&1_u8);
let invalid = bytemuck::bytes_of(&200_u8);
assert_eq!(Ok(&Compose::Copy), try_from_bytes::<Compose>(valid_one));
assert!(try_from_bytes::<Compose>(invalid).is_err());
assert_eq!(Ok(&Extend::Repeat), try_from_bytes::<Extend>(valid_one));
assert!(try_from_bytes::<Extend>(invalid).is_err());
assert_eq!(Ok(&Fill::EvenOdd), try_from_bytes::<Fill>(valid_one));
assert!(try_from_bytes::<Fill>(invalid).is_err());
assert_eq!(
Ok(&ImageAlphaType::Alpha),
try_from_bytes::<ImageAlphaType>(valid_zero)
);
assert_eq!(
Ok(&ImageAlphaType::AlphaPremultiplied),
try_from_bytes::<ImageAlphaType>(valid_one)
);
assert!(try_from_bytes::<ImageAlphaType>(invalid).is_err());
assert_eq!(
Ok(&ImageFormat::Rgba8),
try_from_bytes::<ImageFormat>(valid_zero)
);
assert_eq!(
Ok(&ImageFormat::Bgra8),
try_from_bytes::<ImageFormat>(valid_one)
);
assert!(try_from_bytes::<ImageFormat>(invalid).is_err());
assert_eq!(
Ok(&ImageQuality::Medium),
try_from_bytes::<ImageQuality>(valid_one)
);
assert!(try_from_bytes::<ImageQuality>(invalid).is_err());
assert_eq!(Ok(&Mix::Multiply), try_from_bytes::<Mix>(valid_one));
assert!(try_from_bytes::<Mix>(invalid).is_err());
}
#[test]
fn contiguous() {
let compose1 = Compose::PlusLighter;
let compose2 = Compose::from_integer(compose1.into_integer());
assert_eq!(Some(compose1), compose2);
assert_eq!(None, Compose::from_integer(255));
let extend1 = Extend::Repeat;
let extend2 = Extend::from_integer(extend1.into_integer());
assert_eq!(Some(extend1), extend2);
assert_eq!(None, Extend::from_integer(255));
let fill1 = Fill::EvenOdd;
let fill2 = Fill::from_integer(fill1.into_integer());
assert_eq!(Some(fill1), fill2);
assert_eq!(None, Fill::from_integer(255));
let image_alpha_type_1 = ImageAlphaType::Alpha;
let image_alpha_type_2 = ImageAlphaType::from_integer(image_alpha_type_1.into_integer());
assert_eq!(Some(image_alpha_type_1), image_alpha_type_2);
assert_eq!(None, ImageAlphaType::from_integer(255));
let image_format_1 = ImageFormat::Rgba8;
let image_format_2 = ImageFormat::from_integer(image_format_1.into_integer());
assert_eq!(Some(image_format_1), image_format_2);
assert_eq!(None, ImageFormat::from_integer(255));
let image_quality_1 = ImageQuality::Low;
let image_quality_2 = ImageQuality::from_integer(image_quality_1.into_integer());
assert_eq!(Some(image_quality_1), image_quality_2);
assert_eq!(None, ImageQuality::from_integer(255));
let mix_1 = Mix::Multiply;
let mix_2 = Mix::from_integer(mix_1.into_integer());
assert_eq!(Some(mix_1), mix_2);
assert_eq!(None, Mix::from_integer(255));
}
#[test]
fn zeroable() {
let compose = Compose::zeroed();
assert_eq!(compose, Compose::Clear);
let extend = Extend::zeroed();
assert_eq!(extend, Extend::Pad);
let fill = Fill::zeroed();
assert_eq!(fill, Fill::NonZero);
let image_alpha_type = ImageAlphaType::zeroed();
assert_eq!(image_alpha_type, ImageAlphaType::Alpha);
let image_format = ImageFormat::zeroed();
assert_eq!(image_format, ImageFormat::Rgba8);
let image_quality = ImageQuality::zeroed();
assert_eq!(image_quality, ImageQuality::Low);
let mix = Mix::zeroed();
assert_eq!(mix, Mix::Normal);
}
const _: () = {
let mut value = 0;
while value <= Compose::MAX_VALUE {
let it: Compose = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
const _: () = {
let mut value = 0;
while value <= Extend::MAX_VALUE {
let it: Extend = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
const _: () = {
let mut value = 0;
while value <= Fill::MAX_VALUE {
let it: Fill = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
const _: () = {
let mut value = 0;
while value <= ImageAlphaType::MAX_VALUE {
let it: ImageAlphaType = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
const _: () = {
let mut value = 0;
while value <= ImageFormat::MAX_VALUE {
let it: ImageFormat = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
const _: () = {
let mut value = 0;
while value <= ImageQuality::MAX_VALUE {
let it: ImageQuality = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
const _: () = {
let mut value = 0;
while value <= ImageQuality::MAX_VALUE {
let it: ImageQuality = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
}
#[cfg(doctest)]
mod doctests {
const _COMPOSE: () = {};
const _EXTEND: () = {};
const _FILL: () = {};
const _IMAGE_ALPHA_TYPE: () = {};
const _IMAGE_FORMAT: () = {};
const _IMAGE_QUALITY: () = {};
const _MIX: () = {};
}