1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use core::cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use core::marker::PhantomData;
use core::{fmt, mem};
use zerocopy::{AsBytes, FromBytes};
pub struct Pixel<P: ?Sized>(PhantomData<P>);
pub trait AsPixel {
fn pixel() -> Pixel<Self>;
}
pub(crate) const MAX_ALIGN: usize = 16;
#[derive(Clone, Copy, AsBytes, FromBytes)]
#[repr(align(16))]
#[repr(C)]
pub struct MaxAligned(pub(crate) [u8; 16]);
pub(crate) mod constants {
use super::{AsPixel, MaxAligned, Pixel};
macro_rules! constant_pixels {
($(($name:ident, $type:ty)),*) => {
$(pub const $name: Pixel<$type> = Pixel(core::marker::PhantomData) ;
impl AsPixel for $type {
fn pixel() -> Pixel<Self> {
$name
}
}
)*
}
}
constant_pixels!(
(I8, i8),
(U8, u8),
(I16, i16),
(U16, u16),
(I32, i32),
(U32, u32),
(RGB, [u8; 3]),
(RGBA, [u8; 4]),
(MAX, MaxAligned)
);
}
impl<P: AsBytes + FromBytes> Pixel<P> {
pub fn for_type() -> Option<Self> {
if mem::align_of::<P>() <= MAX_ALIGN && !mem::needs_drop::<P>() {
Some(Pixel(PhantomData))
} else {
None
}
}
}
impl<P> Pixel<P> {
pub fn align(self) -> usize {
mem::align_of::<P>()
}
pub fn size(self) -> usize {
mem::size_of::<P>()
}
}
impl<P> Clone for Pixel<P> {
fn clone(&self) -> Self {
Pixel(PhantomData)
}
}
impl<P> PartialEq for Pixel<P> {
fn eq(&self, _: &Self) -> bool {
true
}
}
impl<P> Eq for Pixel<P> { }
impl<P> PartialOrd for Pixel<P> {
fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
Some(Ordering::Equal)
}
}
impl<P> Ord for Pixel<P> {
fn cmp(&self, _: &Self) -> Ordering {
Ordering::Equal
}
}
impl<P> Copy for Pixel<P> { }
impl<P> fmt::Debug for Pixel<P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Pixel")
.field("size", &self.size())
.field("align", &self.align())
.finish()
}
}