parlance/
impl_bytemuck.rs1#![allow(
7 unsafe_code,
8 reason = "The `bytemuck` marker traits are `unsafe` and require `unsafe impl`."
9)]
10
11use crate::{BidiLevel, GenericFamily, NormalizedCoord};
12use bytemuck::{
13 Contiguous, NoUninit, Pod, TransparentWrapper, Zeroable, checked::CheckedBitPattern,
14};
15
16unsafe impl NoUninit for GenericFamily {}
18
19unsafe impl Zeroable for GenericFamily {}
21
22unsafe impl CheckedBitPattern for GenericFamily {
24 type Bits = u8;
25
26 fn is_valid_bit_pattern(bits: &u8) -> bool {
27 *bits <= Self::MAX_VALUE
29 }
30}
31
32unsafe impl Contiguous for GenericFamily {
35 type Int = u8;
36 const MIN_VALUE: u8 = Self::Serif as u8;
37 #[allow(
38 clippy::use_self,
39 reason = "Using `Self::MAX_VALUE` here would refer to `Contiguous::MAX_VALUE` (self-reference)."
40 )]
41 const MAX_VALUE: u8 = GenericFamily::MAX_VALUE;
42}
43
44unsafe impl Pod for BidiLevel {}
48
49unsafe impl Zeroable for BidiLevel {}
51
52unsafe impl Pod for NormalizedCoord {}
54
55unsafe impl Zeroable for NormalizedCoord {}
57
58unsafe impl TransparentWrapper<i16> for NormalizedCoord {}
60
61#[cfg(test)]
62mod tests {
63 use bytemuck::{Contiguous, TransparentWrapper, Zeroable, checked::try_from_bytes};
64 use core::ptr;
65
66 use super::{BidiLevel, GenericFamily, NormalizedCoord};
67
68 #[test]
69 fn checked_bit_pattern() {
70 let valid = bytemuck::bytes_of(&2_u8);
71 let invalid = bytemuck::bytes_of(&200_u8);
72
73 assert_eq!(
74 Ok(&GenericFamily::Monospace),
75 try_from_bytes::<GenericFamily>(valid)
76 );
77
78 assert!(try_from_bytes::<GenericFamily>(invalid).is_err());
79 }
80
81 #[test]
82 fn contiguous() {
83 let hd1 = GenericFamily::SansSerif;
84 let hd2 = GenericFamily::from_integer(hd1.into_integer());
85 assert_eq!(Some(hd1), hd2);
86
87 assert_eq!(None, GenericFamily::from_integer(255));
88 }
89
90 #[test]
91 fn zeroable() {
92 let hd = GenericFamily::zeroed();
93 assert_eq!(hd, GenericFamily::Serif);
94 }
95
96 const _: () = {
98 let mut value = 0;
99 while value <= GenericFamily::MAX_VALUE {
100 let it: GenericFamily = unsafe { ptr::read((&raw const value).cast()) };
102 if it as u8 != value {
104 unreachable!();
105 }
106 value += 1;
107 }
108 };
109
110 #[test]
111 fn normalized_coord_cast_slice() {
112 let coords = [
113 NormalizedCoord::from_bits(-16384),
114 NormalizedCoord::from_bits(0),
115 NormalizedCoord::from_bits(8192),
116 ];
117 let bits: &[i16] = bytemuck::cast_slice(&coords);
118 assert_eq!(bits, [-16384, 0, 8192]);
119 let back: &[NormalizedCoord] = bytemuck::cast_slice(bits);
120 assert_eq!(back, coords);
121 }
122
123 #[test]
124 fn normalized_coord_transparent_wrapper() {
125 assert_eq!(NormalizedCoord::zeroed(), NormalizedCoord::from_bits(0));
126 let coords = [NormalizedCoord::from_bits(1), NormalizedCoord::from_bits(2)];
127 assert_eq!(NormalizedCoord::peel_slice(&coords), [1, 2]);
128 assert_eq!(
129 NormalizedCoord::wrap_slice(&[3, 4]),
130 [NormalizedCoord::from_bits(3), NormalizedCoord::from_bits(4)]
131 );
132 }
133
134 const _: () = {
139 if size_of::<NormalizedCoord>() != 2 {
140 panic!("`NormalizedCoord` is not two bytes");
141 }
142 };
143
144 const _: () = {
149 if size_of::<BidiLevel>() != 1 {
150 panic!("`BidiLevel` is not one byte");
151 }
152 };
153}
154
155#[cfg(doctest)]
156mod doctests {
158 const _GENERIC_FAMILY: () = {};
176}