#![allow(
unsafe_code,
reason = "The `bytemuck` marker traits are `unsafe` and require `unsafe impl`."
)]
use crate::{BidiLevel, GenericFamily, NormalizedCoord};
use bytemuck::{
Contiguous, NoUninit, Pod, TransparentWrapper, Zeroable, checked::CheckedBitPattern,
};
unsafe impl NoUninit for GenericFamily {}
unsafe impl Zeroable for GenericFamily {}
unsafe impl CheckedBitPattern for GenericFamily {
type Bits = u8;
fn is_valid_bit_pattern(bits: &u8) -> bool {
*bits <= Self::MAX_VALUE
}
}
unsafe impl Contiguous for GenericFamily {
type Int = u8;
const MIN_VALUE: u8 = Self::Serif as u8;
#[allow(
clippy::use_self,
reason = "Using `Self::MAX_VALUE` here would refer to `Contiguous::MAX_VALUE` (self-reference)."
)]
const MAX_VALUE: u8 = GenericFamily::MAX_VALUE;
}
unsafe impl Pod for BidiLevel {}
unsafe impl Zeroable for BidiLevel {}
unsafe impl Pod for NormalizedCoord {}
unsafe impl Zeroable for NormalizedCoord {}
unsafe impl TransparentWrapper<i16> for NormalizedCoord {}
#[cfg(test)]
mod tests {
use bytemuck::{Contiguous, TransparentWrapper, Zeroable, checked::try_from_bytes};
use core::ptr;
use super::{BidiLevel, GenericFamily, NormalizedCoord};
#[test]
fn checked_bit_pattern() {
let valid = bytemuck::bytes_of(&2_u8);
let invalid = bytemuck::bytes_of(&200_u8);
assert_eq!(
Ok(&GenericFamily::Monospace),
try_from_bytes::<GenericFamily>(valid)
);
assert!(try_from_bytes::<GenericFamily>(invalid).is_err());
}
#[test]
fn contiguous() {
let hd1 = GenericFamily::SansSerif;
let hd2 = GenericFamily::from_integer(hd1.into_integer());
assert_eq!(Some(hd1), hd2);
assert_eq!(None, GenericFamily::from_integer(255));
}
#[test]
fn zeroable() {
let hd = GenericFamily::zeroed();
assert_eq!(hd, GenericFamily::Serif);
}
const _: () = {
let mut value = 0;
while value <= GenericFamily::MAX_VALUE {
let it: GenericFamily = unsafe { ptr::read((&raw const value).cast()) };
if it as u8 != value {
unreachable!();
}
value += 1;
}
};
#[test]
fn normalized_coord_cast_slice() {
let coords = [
NormalizedCoord::from_bits(-16384),
NormalizedCoord::from_bits(0),
NormalizedCoord::from_bits(8192),
];
let bits: &[i16] = bytemuck::cast_slice(&coords);
assert_eq!(bits, [-16384, 0, 8192]);
let back: &[NormalizedCoord] = bytemuck::cast_slice(bits);
assert_eq!(back, coords);
}
#[test]
fn normalized_coord_transparent_wrapper() {
assert_eq!(NormalizedCoord::zeroed(), NormalizedCoord::from_bits(0));
let coords = [NormalizedCoord::from_bits(1), NormalizedCoord::from_bits(2)];
assert_eq!(NormalizedCoord::peel_slice(&coords), [1, 2]);
assert_eq!(
NormalizedCoord::wrap_slice(&[3, 4]),
[NormalizedCoord::from_bits(3), NormalizedCoord::from_bits(4)]
);
}
const _: () = {
if size_of::<NormalizedCoord>() != 2 {
panic!("`NormalizedCoord` is not two bytes");
}
};
const _: () = {
if size_of::<BidiLevel>() != 1 {
panic!("`BidiLevel` is not one byte");
}
};
}
#[cfg(doctest)]
mod doctests {
const _GENERIC_FAMILY: () = {};
}