|
| 1 | +use crate::convert::TryFrom; |
| 2 | +use crate::num::NonZeroUsize; |
| 3 | +use crate::{cmp, fmt, mem, num}; |
| 4 | + |
| 5 | +/// A type storing a `usize` which is a power of two, and thus |
| 6 | +/// represents a possible alignment in the rust abstract machine. |
| 7 | +/// |
| 8 | +/// Note that particularly large alignments, while representable in this type, |
| 9 | +/// are likely not to be supported by actual allocators and linkers. |
| 10 | +#[derive(Copy, Clone)] |
| 11 | +#[repr(transparent)] |
| 12 | +pub(crate) struct ValidAlign(ValidAlignEnum); |
| 13 | + |
| 14 | +// ValidAlign is `repr(usize)`, but via extra steps. |
| 15 | +const _: () = assert!(mem::size_of::<ValidAlign>() == mem::size_of::<usize>()); |
| 16 | +const _: () = assert!(mem::align_of::<ValidAlign>() == mem::align_of::<usize>()); |
| 17 | + |
| 18 | +impl ValidAlign { |
| 19 | + /// Creates a `ValidAlign` from a power-of-two `usize`. |
| 20 | + /// |
| 21 | + /// # Safety |
| 22 | + /// |
| 23 | + /// `align` must be a power of two. |
| 24 | + /// |
| 25 | + /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`. |
| 26 | + /// It must *not* be zero. |
| 27 | + #[inline] |
| 28 | + pub(crate) const unsafe fn new_unchecked(align: usize) -> Self { |
| 29 | + debug_assert!(align.is_power_of_two()); |
| 30 | + |
| 31 | + // SAFETY: By precondition, this must be a power of two, and |
| 32 | + // our variants encompass all possible powers of two. |
| 33 | + unsafe { mem::transmute::<usize, ValidAlign>(align) } |
| 34 | + } |
| 35 | + |
| 36 | + #[inline] |
| 37 | + pub(crate) const fn as_nonzero(self) -> NonZeroUsize { |
| 38 | + // SAFETY: All the discriminants are non-zero. |
| 39 | + unsafe { NonZeroUsize::new_unchecked(self.0 as usize) } |
| 40 | + } |
| 41 | + |
| 42 | + /// Returns the base 2 logarithm of the alignment. |
| 43 | + /// |
| 44 | + /// This is always exact, as `self` represents a power of two. |
| 45 | + #[inline] |
| 46 | + pub(crate) fn log2(self) -> u32 { |
| 47 | + self.as_nonzero().trailing_zeros() |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +impl fmt::Debug for ValidAlign { |
| 52 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 53 | + write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2()) |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +impl TryFrom<NonZeroUsize> for ValidAlign { |
| 58 | + type Error = num::TryFromIntError; |
| 59 | + |
| 60 | + #[inline] |
| 61 | + fn try_from(align: NonZeroUsize) -> Result<ValidAlign, Self::Error> { |
| 62 | + if align.is_power_of_two() { |
| 63 | + // SAFETY: Just checked for power-of-two |
| 64 | + unsafe { Ok(ValidAlign::new_unchecked(align.get())) } |
| 65 | + } else { |
| 66 | + Err(num::TryFromIntError(())) |
| 67 | + } |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +impl TryFrom<usize> for ValidAlign { |
| 72 | + type Error = num::TryFromIntError; |
| 73 | + |
| 74 | + #[inline] |
| 75 | + fn try_from(align: usize) -> Result<ValidAlign, Self::Error> { |
| 76 | + if align.is_power_of_two() { |
| 77 | + // SAFETY: Just checked for power-of-two |
| 78 | + unsafe { Ok(ValidAlign::new_unchecked(align)) } |
| 79 | + } else { |
| 80 | + Err(num::TryFromIntError(())) |
| 81 | + } |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +impl cmp::Eq for ValidAlign {} |
| 86 | + |
| 87 | +impl cmp::PartialEq for ValidAlign { |
| 88 | + #[inline] |
| 89 | + fn eq(&self, other: &Self) -> bool { |
| 90 | + self.as_nonzero() == other.as_nonzero() |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +impl cmp::Ord for ValidAlign { |
| 95 | + #[inline] |
| 96 | + fn cmp(&self, other: &Self) -> cmp::Ordering { |
| 97 | + self.as_nonzero().cmp(&other.as_nonzero()) |
| 98 | + } |
| 99 | +} |
| 100 | + |
| 101 | +impl cmp::PartialOrd for ValidAlign { |
| 102 | + #[inline] |
| 103 | + fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { |
| 104 | + Some(self.cmp(other)) |
| 105 | + } |
| 106 | +} |
| 107 | + |
| 108 | +#[cfg(target_pointer_width = "16")] |
| 109 | +type ValidAlignEnum = ValidAlignEnum16; |
| 110 | +#[cfg(target_pointer_width = "32")] |
| 111 | +type ValidAlignEnum = ValidAlignEnum32; |
| 112 | +#[cfg(target_pointer_width = "64")] |
| 113 | +type ValidAlignEnum = ValidAlignEnum64; |
| 114 | + |
| 115 | +#[derive(Copy, Clone)] |
| 116 | +#[repr(u16)] |
| 117 | +enum ValidAlignEnum16 { |
| 118 | + _Align1Shl0 = 1 << 0, |
| 119 | + _Align1Shl1 = 1 << 1, |
| 120 | + _Align1Shl2 = 1 << 2, |
| 121 | + _Align1Shl3 = 1 << 3, |
| 122 | + _Align1Shl4 = 1 << 4, |
| 123 | + _Align1Shl5 = 1 << 5, |
| 124 | + _Align1Shl6 = 1 << 6, |
| 125 | + _Align1Shl7 = 1 << 7, |
| 126 | + _Align1Shl8 = 1 << 8, |
| 127 | + _Align1Shl9 = 1 << 9, |
| 128 | + _Align1Shl10 = 1 << 10, |
| 129 | + _Align1Shl11 = 1 << 11, |
| 130 | + _Align1Shl12 = 1 << 12, |
| 131 | + _Align1Shl13 = 1 << 13, |
| 132 | + _Align1Shl14 = 1 << 14, |
| 133 | + _Align1Shl15 = 1 << 15, |
| 134 | +} |
| 135 | + |
| 136 | +#[derive(Copy, Clone)] |
| 137 | +#[repr(u32)] |
| 138 | +enum ValidAlignEnum32 { |
| 139 | + _Align1Shl0 = 1 << 0, |
| 140 | + _Align1Shl1 = 1 << 1, |
| 141 | + _Align1Shl2 = 1 << 2, |
| 142 | + _Align1Shl3 = 1 << 3, |
| 143 | + _Align1Shl4 = 1 << 4, |
| 144 | + _Align1Shl5 = 1 << 5, |
| 145 | + _Align1Shl6 = 1 << 6, |
| 146 | + _Align1Shl7 = 1 << 7, |
| 147 | + _Align1Shl8 = 1 << 8, |
| 148 | + _Align1Shl9 = 1 << 9, |
| 149 | + _Align1Shl10 = 1 << 10, |
| 150 | + _Align1Shl11 = 1 << 11, |
| 151 | + _Align1Shl12 = 1 << 12, |
| 152 | + _Align1Shl13 = 1 << 13, |
| 153 | + _Align1Shl14 = 1 << 14, |
| 154 | + _Align1Shl15 = 1 << 15, |
| 155 | + _Align1Shl16 = 1 << 16, |
| 156 | + _Align1Shl17 = 1 << 17, |
| 157 | + _Align1Shl18 = 1 << 18, |
| 158 | + _Align1Shl19 = 1 << 19, |
| 159 | + _Align1Shl20 = 1 << 20, |
| 160 | + _Align1Shl21 = 1 << 21, |
| 161 | + _Align1Shl22 = 1 << 22, |
| 162 | + _Align1Shl23 = 1 << 23, |
| 163 | + _Align1Shl24 = 1 << 24, |
| 164 | + _Align1Shl25 = 1 << 25, |
| 165 | + _Align1Shl26 = 1 << 26, |
| 166 | + _Align1Shl27 = 1 << 27, |
| 167 | + _Align1Shl28 = 1 << 28, |
| 168 | + _Align1Shl29 = 1 << 29, |
| 169 | + _Align1Shl30 = 1 << 30, |
| 170 | + _Align1Shl31 = 1 << 31, |
| 171 | +} |
| 172 | + |
| 173 | +#[derive(Copy, Clone)] |
| 174 | +#[repr(u64)] |
| 175 | +enum ValidAlignEnum64 { |
| 176 | + _Align1Shl0 = 1 << 0, |
| 177 | + _Align1Shl1 = 1 << 1, |
| 178 | + _Align1Shl2 = 1 << 2, |
| 179 | + _Align1Shl3 = 1 << 3, |
| 180 | + _Align1Shl4 = 1 << 4, |
| 181 | + _Align1Shl5 = 1 << 5, |
| 182 | + _Align1Shl6 = 1 << 6, |
| 183 | + _Align1Shl7 = 1 << 7, |
| 184 | + _Align1Shl8 = 1 << 8, |
| 185 | + _Align1Shl9 = 1 << 9, |
| 186 | + _Align1Shl10 = 1 << 10, |
| 187 | + _Align1Shl11 = 1 << 11, |
| 188 | + _Align1Shl12 = 1 << 12, |
| 189 | + _Align1Shl13 = 1 << 13, |
| 190 | + _Align1Shl14 = 1 << 14, |
| 191 | + _Align1Shl15 = 1 << 15, |
| 192 | + _Align1Shl16 = 1 << 16, |
| 193 | + _Align1Shl17 = 1 << 17, |
| 194 | + _Align1Shl18 = 1 << 18, |
| 195 | + _Align1Shl19 = 1 << 19, |
| 196 | + _Align1Shl20 = 1 << 20, |
| 197 | + _Align1Shl21 = 1 << 21, |
| 198 | + _Align1Shl22 = 1 << 22, |
| 199 | + _Align1Shl23 = 1 << 23, |
| 200 | + _Align1Shl24 = 1 << 24, |
| 201 | + _Align1Shl25 = 1 << 25, |
| 202 | + _Align1Shl26 = 1 << 26, |
| 203 | + _Align1Shl27 = 1 << 27, |
| 204 | + _Align1Shl28 = 1 << 28, |
| 205 | + _Align1Shl29 = 1 << 29, |
| 206 | + _Align1Shl30 = 1 << 30, |
| 207 | + _Align1Shl31 = 1 << 31, |
| 208 | + _Align1Shl32 = 1 << 32, |
| 209 | + _Align1Shl33 = 1 << 33, |
| 210 | + _Align1Shl34 = 1 << 34, |
| 211 | + _Align1Shl35 = 1 << 35, |
| 212 | + _Align1Shl36 = 1 << 36, |
| 213 | + _Align1Shl37 = 1 << 37, |
| 214 | + _Align1Shl38 = 1 << 38, |
| 215 | + _Align1Shl39 = 1 << 39, |
| 216 | + _Align1Shl40 = 1 << 40, |
| 217 | + _Align1Shl41 = 1 << 41, |
| 218 | + _Align1Shl42 = 1 << 42, |
| 219 | + _Align1Shl43 = 1 << 43, |
| 220 | + _Align1Shl44 = 1 << 44, |
| 221 | + _Align1Shl45 = 1 << 45, |
| 222 | + _Align1Shl46 = 1 << 46, |
| 223 | + _Align1Shl47 = 1 << 47, |
| 224 | + _Align1Shl48 = 1 << 48, |
| 225 | + _Align1Shl49 = 1 << 49, |
| 226 | + _Align1Shl50 = 1 << 50, |
| 227 | + _Align1Shl51 = 1 << 51, |
| 228 | + _Align1Shl52 = 1 << 52, |
| 229 | + _Align1Shl53 = 1 << 53, |
| 230 | + _Align1Shl54 = 1 << 54, |
| 231 | + _Align1Shl55 = 1 << 55, |
| 232 | + _Align1Shl56 = 1 << 56, |
| 233 | + _Align1Shl57 = 1 << 57, |
| 234 | + _Align1Shl58 = 1 << 58, |
| 235 | + _Align1Shl59 = 1 << 59, |
| 236 | + _Align1Shl60 = 1 << 60, |
| 237 | + _Align1Shl61 = 1 << 61, |
| 238 | + _Align1Shl62 = 1 << 62, |
| 239 | + _Align1Shl63 = 1 << 63, |
| 240 | +} |
0 commit comments