linearize/impls/
integers.rs
1#![allow(unexpected_cfgs)]
2
3use {crate::Linearize, cfg_if::cfg_if};
4
5macro_rules! impls {
6 ($unsigned:ty, $signed:ty, $test:ident) => {
7 unsafe impl Linearize for $unsigned {
11 type Storage<T> = [T; Self::LENGTH];
12 type CopyStorage<T>
13 = [T; Self::LENGTH]
14 where
15 T: Copy;
16 const LENGTH: usize = <$unsigned>::MAX as usize + 1;
17
18 #[inline]
19 fn linearize(&self) -> usize {
20 *self as usize
21 }
22
23 #[inline]
24 unsafe fn from_linear_unchecked(linear: usize) -> Self
25 where
26 Self: Sized,
27 {
28 linear as $unsigned
29 }
30 }
31
32 unsafe impl Linearize for $signed {
36 type Storage<T> = [T; Self::LENGTH];
37 type CopyStorage<T>
38 = [T; Self::LENGTH]
39 where
40 T: Copy;
41 const LENGTH: usize = <$unsigned>::MAX as usize + 1;
42
43 #[inline]
44 fn linearize(&self) -> usize {
45 (*self as $unsigned).wrapping_sub(<$signed>::MIN as $unsigned) as usize
46 }
47
48 #[inline]
49 unsafe fn from_linear_unchecked(linear: usize) -> Self {
50 (linear as $unsigned).wrapping_add(<$signed>::MIN as $unsigned) as $signed
51 }
52 }
53
54 impl_assert!($unsigned);
55 impl_assert!($signed);
56
57 #[cfg(test)]
58 static_assertions::const_assert_eq! {
59 <$unsigned>::LENGTH,
60 <$unsigned>::MAX as usize + 1,
61 }
62
63 #[cfg(test)]
64 static_assertions::const_assert_eq! {
65 <$signed>::LENGTH,
66 <$unsigned>::MAX as usize + 1,
67 }
68
69 #[test]
70 fn $test() {
71 let umin = <$unsigned>::MIN;
72 let umax = <$unsigned>::MAX;
73 let umid = umax / 2;
74 assert_eq!(umin.linearize(), umin as usize);
75 assert_eq!(umax.linearize(), umax as usize);
76 assert_eq!(umid.linearize(), umid as usize);
77 unsafe {
78 assert_eq!(<$unsigned>::from_linear_unchecked(umin.linearize()), umin);
79 assert_eq!(<$unsigned>::from_linear_unchecked(umax.linearize()), umax);
80 assert_eq!(<$unsigned>::from_linear_unchecked(umid.linearize()), umid);
81 }
82 let imin = <$signed>::MIN;
83 let imax = <$signed>::MAX;
84 let imid = 0 as $signed;
85 let imin_lin = imin.linearize();
86 let imax_lin = imax.linearize();
87 let imid_lin = imid.linearize();
88 assert_eq!(imax_lin, umax as usize);
89 assert_eq!(imin_lin, umin as usize);
90 assert_eq!(imid_lin, umid as usize + 1);
91 unsafe {
92 assert_eq!(<$signed>::from_linear_unchecked(imax_lin), imax);
93 assert_eq!(<$signed>::from_linear_unchecked(imin_lin), imin);
94 assert_eq!(<$signed>::from_linear_unchecked(imid_lin), imid);
95 }
96 }
97 };
98}
99
100cfg_if! {
101 if #[cfg(not(target_pointer_width = "8"))] {
102 impls!(u8, i8, test_u8);
103 cfg_if! {
104 if #[cfg(not(target_pointer_width = "16"))] {
105 impls!(u16, i16, test_u16);
106 cfg_if! {
107 if #[cfg(not(target_pointer_width = "32"))] {
108 impls!(u32, i32, test_u32);
109 cfg_if! {
110 if #[cfg(not(target_pointer_width = "64"))] {
111 impls!(u64, i64, test_u64);
112 cfg_if! {
113 if #[cfg(not(target_pointer_width = "128"))] {
114 impls!(u128, i128, test_u128);
115 }
116 }
117 }
118 }
119 }
120 }
121 }
122 }
123 }
124}