1use std::{
6 any::{Any, TypeId},
7 mem::{align_of, size_of},
8};
9
10macro_rules! generate_aligned_types {
11 ($($t:ident($n:expr),)*) => {
12 $(
13 #[derive(Copy, Clone, Debug)]
14 #[repr(C, align($n))]
15 pub(crate) struct $t([u8; $n]);
16
17 impl Default for $t {
18 fn default() -> Self {
19 $t([0_u8; $n])
20 }
21 }
22 )*
23 }
24}
25
26generate_aligned_types!(
27 T0(1),
28 T1(2),
29 T2(4),
30 T3(8),
31 T4(16),
32 T5(32),
33 T6(64),
34 T7(128),
35 T8(256),
36 T9(512),
37 T10(1024),
38 T11(2048),
39 T12(4096),
40 T13(8192),
41 T14(16384),
42 T15(32768),
43 T16(65536),
44 T17(131072),
45 T18(262144),
46 T19(524288),
47 T20(1048576),
48 T21(2097152),
49 T22(4194304),
50 T23(8388608),
51 T24(16777216),
52 T25(33554432),
53 T26(67108864),
54 T27(134217728),
55 T28(268435456),
56 T29(536870912),
57);
58
59#[macro_export]
60macro_rules! eval_align {
61 (limited_stack, $a:expr; $fn:ident ::<_ $(,$params:ident)*>($($args:expr),*) ) => {
66 match $a {
67 1 => $fn::<T0, $($params,)*>($($args,)*),
68 2 => $fn::<T1, $($params,)*>($($args,)*),
69 4 => $fn::<T2, $($params,)*>($($args,)*),
70 8 => $fn::<T3, $($params,)*>($($args,)*),
71 16 => $fn::<T4, $($params,)*>($($args,)*),
72 32 => $fn::<T5, $($params,)*>($($args,)*),
73 64 => $fn::<T6, $($params,)*>($($args,)*),
74 128 => $fn::<T7, $($params,)*>($($args,)*),
75 256 => $fn::<T8, $($params,)*>($($args,)*),
76 512 => $fn::<T9, $($params,)*>($($args,)*),
77 1024 => $fn::<T10, $($params,)*>($($args,)*),
78 2048 => $fn::<T11, $($params,)*>($($args,)*),
79 4096 => $fn::<T12, $($params,)*>($($args,)*),
80 8192 => $fn::<T13, $($params,)*>($($args,)*),
81 a => unreachable!("Alignment is too large ({}) for vector manipulations", a)
82 }
83 };
84
85 ($a:expr; $fn:ident ::<_ $(,$params:ident)*>($($args:expr),*) ) => {
87 match $a {
88 1 => $fn::<T0, $($params,)*>($($args,)*),
89 2 => $fn::<T1, $($params,)*>($($args,)*),
90 4 => $fn::<T2, $($params,)*>($($args,)*),
91 8 => $fn::<T3, $($params,)*>($($args,)*),
92 16 => $fn::<T4, $($params,)*>($($args,)*),
93 32 => $fn::<T5, $($params,)*>($($args,)*),
94 64 => $fn::<T6, $($params,)*>($($args,)*),
95 128 => $fn::<T7, $($params,)*>($($args,)*),
96 256 => $fn::<T8, $($params,)*>($($args,)*),
97 512 => $fn::<T9, $($params,)*>($($args,)*),
98 1024 => $fn::<T10, $($params,)*>($($args,)*),
99 2048 => $fn::<T11, $($params,)*>($($args,)*),
100 4096 => $fn::<T12, $($params,)*>($($args,)*),
101 8192 => $fn::<T13, $($params,)*>($($args,)*),
102 16384 => $fn::<T14, $($params,)*>($($args,)*),
103 32768 => $fn::<T15, $($params,)*>($($args,)*),
104 65536 => $fn::<T16, $($params,)*>($($args,)*),
105 131072 => $fn::<T17, $($params,)*>($($args,)*),
106 262144 => $fn::<T18, $($params,)*>($($args,)*),
107 524288 => $fn::<T19, $($params,)*>($($args,)*),
108 1048576 => $fn::<T20, $($params,)*>($($args,)*),
109 2097152 => $fn::<T21, $($params,)*>($($args,)*),
110 4194304 => $fn::<T22, $($params,)*>($($args,)*),
111 8388608 => $fn::<T23, $($params,)*>($($args,)*),
112 16777216 => $fn::<T24, $($params,)*>($($args,)*),
113 33554432 => $fn::<T25, $($params,)*>($($args,)*),
114 67108864 => $fn::<T26, $($params,)*>($($args,)*),
115 134217728 => $fn::<T27, $($params,)*>($($args,)*),
116 268435456 => $fn::<T28, $($params,)*>($($args,)*),
117 536870912 => $fn::<T29, $($params,)*>($($args,)*),
118 _ => unreachable!("Unsupported alignment detected")
119 }
120 }
121}
122
123pub trait CopyElem: Any + Copy {}
124impl<T> CopyElem for T where T: Any + Copy {}
125
126#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
127pub struct ElemInfo {
128 pub(crate) type_id: TypeId,
130 pub(crate) size: usize,
134 pub(crate) alignment: usize,
136}
137
138impl ElemInfo {
139 #[inline]
140 pub fn new<T: 'static>() -> ElemInfo {
141 ElemInfo {
142 type_id: TypeId::of::<T>(),
143 size: size_of::<T>() / align_of::<T>(),
144 alignment: align_of::<T>(),
145 }
146 }
147
148 #[inline]
149 pub const fn num_bytes(self) -> usize {
150 self.size * self.alignment
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn info_struct() {
160 let elem_u32 = ElemInfo::new::<u32>();
161 assert_eq!(
162 elem_u32,
163 ElemInfo {
164 type_id: TypeId::of::<u32>(),
165 size: 1,
166 alignment: 4,
167 }
168 );
169
170 assert_eq!(elem_u32.num_bytes(), 4);
171 }
172}