| 1 | //! A newtype with alignment of at least `A` bytes |
| 2 | //! |
| 3 | //! # Examples |
| 4 | //! |
| 5 | //! ``` |
| 6 | //! use std::mem; |
| 7 | //! |
| 8 | //! use aligned::{Aligned, A2, A4, A16}; |
| 9 | //! |
| 10 | //! // Array aligned to a 2 byte boundary |
| 11 | //! static X: Aligned<A2, [u8; 3]> = Aligned([0; 3]); |
| 12 | //! |
| 13 | //! // Array aligned to a 4 byte boundary |
| 14 | //! static Y: Aligned<A4, [u8; 3]> = Aligned([0; 3]); |
| 15 | //! |
| 16 | //! // Unaligned array |
| 17 | //! static Z: [u8; 3] = [0; 3]; |
| 18 | //! |
| 19 | //! // You can allocate the aligned arrays on the stack too |
| 20 | //! let w: Aligned<A16, _> = Aligned([0u8; 3]); |
| 21 | //! |
| 22 | //! assert_eq!(mem::align_of_val(&X), 2); |
| 23 | //! assert_eq!(mem::align_of_val(&Y), 4); |
| 24 | //! assert_eq!(mem::align_of_val(&Z), 1); |
| 25 | //! assert_eq!(mem::align_of_val(&w), 16); |
| 26 | //! ``` |
| 27 | |
| 28 | #![deny (missing_docs)] |
| 29 | #![deny (warnings)] |
| 30 | #![cfg_attr (not(test), no_std)] |
| 31 | |
| 32 | use core::{ |
| 33 | borrow::{Borrow, BorrowMut}, |
| 34 | cmp::Ordering, |
| 35 | fmt::{Debug, Display}, |
| 36 | hash::{Hash, Hasher}, |
| 37 | ops, |
| 38 | }; |
| 39 | |
| 40 | use as_slice::{AsMutSlice, AsSlice}; |
| 41 | |
| 42 | /// A marker trait for an alignment value. |
| 43 | pub trait Alignment: Copy + sealed::Sealed {} |
| 44 | |
| 45 | impl Alignment for A1 {} |
| 46 | impl Alignment for A2 {} |
| 47 | impl Alignment for A4 {} |
| 48 | impl Alignment for A8 {} |
| 49 | impl Alignment for A16 {} |
| 50 | impl Alignment for A32 {} |
| 51 | impl Alignment for A64 {} |
| 52 | |
| 53 | mod sealed { |
| 54 | pub trait Sealed {} |
| 55 | |
| 56 | impl Sealed for super::A1 {} |
| 57 | impl Sealed for super::A2 {} |
| 58 | impl Sealed for super::A4 {} |
| 59 | impl Sealed for super::A8 {} |
| 60 | impl Sealed for super::A16 {} |
| 61 | impl Sealed for super::A32 {} |
| 62 | impl Sealed for super::A64 {} |
| 63 | } |
| 64 | |
| 65 | /// 1-byte alignment |
| 66 | #[derive (Clone, Copy)] |
| 67 | #[repr (align(1))] |
| 68 | pub struct A1; |
| 69 | |
| 70 | /// 2-byte alignment |
| 71 | #[derive (Clone, Copy)] |
| 72 | #[repr (align(2))] |
| 73 | pub struct A2; |
| 74 | |
| 75 | /// 4-byte alignment |
| 76 | #[derive (Clone, Copy)] |
| 77 | #[repr (align(4))] |
| 78 | pub struct A4; |
| 79 | |
| 80 | /// 8-byte alignment |
| 81 | #[derive (Clone, Copy)] |
| 82 | #[repr (align(8))] |
| 83 | pub struct A8; |
| 84 | |
| 85 | /// 16-byte alignment |
| 86 | #[derive (Clone, Copy)] |
| 87 | #[repr (align(16))] |
| 88 | pub struct A16; |
| 89 | |
| 90 | /// 32-byte alignment |
| 91 | #[derive (Clone, Copy)] |
| 92 | #[repr (align(32))] |
| 93 | pub struct A32; |
| 94 | |
| 95 | /// 64-byte alignment |
| 96 | #[derive (Clone, Copy)] |
| 97 | #[repr (align(64))] |
| 98 | pub struct A64; |
| 99 | |
| 100 | /// A newtype with alignment of at least `A` bytes |
| 101 | #[repr (C)] |
| 102 | pub struct Aligned<A, T> |
| 103 | where |
| 104 | T: ?Sized, |
| 105 | { |
| 106 | _alignment: [A; 0], |
| 107 | value: T, |
| 108 | } |
| 109 | |
| 110 | /// Changes the alignment of `value` to be at least `A` bytes |
| 111 | #[allow (non_snake_case)] |
| 112 | pub const fn Aligned<A, T>(value: T) -> Aligned<A, T> { |
| 113 | Aligned { |
| 114 | _alignment: [], |
| 115 | value, |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | impl<A, T> ops::Deref for Aligned<A, T> |
| 120 | where |
| 121 | A: Alignment, |
| 122 | T: ?Sized, |
| 123 | { |
| 124 | type Target = T; |
| 125 | |
| 126 | fn deref(&self) -> &T { |
| 127 | &self.value |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | impl<A, T> ops::DerefMut for Aligned<A, T> |
| 132 | where |
| 133 | A: Alignment, |
| 134 | T: ?Sized, |
| 135 | { |
| 136 | fn deref_mut(&mut self) -> &mut T { |
| 137 | &mut self.value |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | impl<A, T> ops::Index<ops::RangeTo<usize>> for Aligned<A, [T]> |
| 142 | where |
| 143 | A: Alignment, |
| 144 | { |
| 145 | type Output = Aligned<A, [T]>; |
| 146 | |
| 147 | fn index(&self, range: ops::RangeTo<usize>) -> &Aligned<A, [T]> { |
| 148 | unsafe { &*(&self.value[range] as *const [T] as *const Aligned<A, [T]>) } |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | impl<A, T> AsSlice for Aligned<A, T> |
| 153 | where |
| 154 | A: Alignment, |
| 155 | T: AsSlice, |
| 156 | { |
| 157 | type Element = T::Element; |
| 158 | |
| 159 | fn as_slice(&self) -> &[T::Element] { |
| 160 | T::as_slice(&**self) |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | impl<A, T> AsMutSlice for Aligned<A, T> |
| 165 | where |
| 166 | A: Alignment, |
| 167 | T: AsMutSlice, |
| 168 | { |
| 169 | fn as_mut_slice(&mut self) -> &mut [T::Element] { |
| 170 | T::as_mut_slice(&mut **self) |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | impl<A, T> Borrow<T> for Aligned<A, T> |
| 175 | where |
| 176 | A: Alignment, |
| 177 | { |
| 178 | fn borrow(&self) -> &T { |
| 179 | &self.value |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | impl<A, T> BorrowMut<T> for Aligned<A, T> |
| 184 | where |
| 185 | A: Alignment, |
| 186 | { |
| 187 | fn borrow_mut(&mut self) -> &mut T { |
| 188 | &mut self.value |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | impl<A, T> Borrow<[<Aligned<A, T> as AsSlice>::Element]> for Aligned<A, T> |
| 193 | where |
| 194 | A: Alignment, |
| 195 | Aligned<A, T>: AsSlice, |
| 196 | { |
| 197 | fn borrow(&self) -> &[<Aligned<A, T> as AsSlice>::Element] { |
| 198 | self.as_slice() |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | impl<A, T> BorrowMut<[<Aligned<A, T> as AsSlice>::Element]> for Aligned<A, T> |
| 203 | where |
| 204 | A: Alignment, |
| 205 | Aligned<A, T>: AsMutSlice, |
| 206 | { |
| 207 | fn borrow_mut(&mut self) -> &mut [<Aligned<A, T> as AsSlice>::Element] { |
| 208 | self.as_mut_slice() |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | impl<A, T> Clone for Aligned<A, T> |
| 213 | where |
| 214 | A: Alignment, |
| 215 | T: Clone, |
| 216 | { |
| 217 | fn clone(&self) -> Self { |
| 218 | Self { |
| 219 | _alignment: [], |
| 220 | value: self.value.clone(), |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | impl<A, T> Copy for Aligned<A, T> |
| 226 | where |
| 227 | A: Alignment, |
| 228 | T: Copy, |
| 229 | { |
| 230 | } |
| 231 | |
| 232 | impl<A, T> Default for Aligned<A, T> |
| 233 | where |
| 234 | A: Alignment, |
| 235 | T: Default, |
| 236 | { |
| 237 | fn default() -> Self { |
| 238 | Self { |
| 239 | _alignment: [], |
| 240 | value: Default::default(), |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | impl<A, T> Debug for Aligned<A, T> |
| 246 | where |
| 247 | A: Alignment, |
| 248 | T: Debug, |
| 249 | { |
| 250 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| 251 | self.value.fmt(f) |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | impl<A, T> Display for Aligned<A, T> |
| 256 | where |
| 257 | A: Alignment, |
| 258 | T: Display, |
| 259 | { |
| 260 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| 261 | self.value.fmt(f) |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | impl<A, T> PartialEq for Aligned<A, T> |
| 266 | where |
| 267 | A: Alignment, |
| 268 | T: PartialEq, |
| 269 | { |
| 270 | fn eq(&self, other: &Self) -> bool { |
| 271 | self.value == other.value |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | impl<A, T> Eq for Aligned<A, T> |
| 276 | where |
| 277 | A: Alignment, |
| 278 | T: Eq, |
| 279 | { |
| 280 | } |
| 281 | |
| 282 | impl<A, T> Hash for Aligned<A, T> |
| 283 | where |
| 284 | A: Alignment, |
| 285 | T: Hash, |
| 286 | { |
| 287 | fn hash<H: Hasher>(&self, state: &mut H) { |
| 288 | self.value.hash(state); |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | impl<A, T> Ord for Aligned<A, T> |
| 293 | where |
| 294 | A: Alignment, |
| 295 | T: Ord, |
| 296 | { |
| 297 | fn cmp(&self, other: &Self) -> Ordering { |
| 298 | self.value.cmp(&other.value) |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | impl<A, T> PartialOrd for Aligned<A, T> |
| 303 | where |
| 304 | A: Alignment, |
| 305 | T: PartialOrd, |
| 306 | { |
| 307 | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { |
| 308 | self.value.partial_cmp(&other.value) |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | #[test ] |
| 313 | fn sanity() { |
| 314 | use core::mem; |
| 315 | |
| 316 | let a: Aligned<A1, _> = Aligned([0u8; 3]); |
| 317 | let x: Aligned<A2, _> = Aligned([0u8; 3]); |
| 318 | let y: Aligned<A4, _> = Aligned([0u8; 3]); |
| 319 | let z: Aligned<A8, _> = Aligned([0u8; 3]); |
| 320 | let w: Aligned<A16, _> = Aligned([0u8; 3]); |
| 321 | |
| 322 | // check alignment |
| 323 | assert_eq!(mem::align_of_val(&a), 1); |
| 324 | assert_eq!(mem::align_of_val(&x), 2); |
| 325 | assert_eq!(mem::align_of_val(&y), 4); |
| 326 | assert_eq!(mem::align_of_val(&z), 8); |
| 327 | assert_eq!(mem::align_of_val(&w), 16); |
| 328 | |
| 329 | assert!(a.as_ptr() as usize % 1 == 0); |
| 330 | assert!(x.as_ptr() as usize % 2 == 0); |
| 331 | assert!(y.as_ptr() as usize % 4 == 0); |
| 332 | assert!(z.as_ptr() as usize % 8 == 0); |
| 333 | assert!(w.as_ptr() as usize % 16 == 0); |
| 334 | |
| 335 | // test `deref` |
| 336 | assert_eq!(a.len(), 3); |
| 337 | assert_eq!(x.len(), 3); |
| 338 | assert_eq!(y.len(), 3); |
| 339 | assert_eq!(z.len(), 3); |
| 340 | assert_eq!(w.len(), 3); |
| 341 | |
| 342 | // alignment should be preserved after slicing |
| 343 | let a: &Aligned<_, [_]> = &a; |
| 344 | let x: &Aligned<_, [_]> = &x; |
| 345 | let y: &Aligned<_, [_]> = &y; |
| 346 | let z: &Aligned<_, [_]> = &z; |
| 347 | let w: &Aligned<_, [_]> = &w; |
| 348 | |
| 349 | let a: &Aligned<_, _> = &a[..2]; |
| 350 | let x: &Aligned<_, _> = &x[..2]; |
| 351 | let y: &Aligned<_, _> = &y[..2]; |
| 352 | let z: &Aligned<_, _> = &z[..2]; |
| 353 | let w: &Aligned<_, _> = &w[..2]; |
| 354 | |
| 355 | assert!(a.as_ptr() as usize % 1 == 0); |
| 356 | assert!(x.as_ptr() as usize % 2 == 0); |
| 357 | assert!(y.as_ptr() as usize % 4 == 0); |
| 358 | assert!(z.as_ptr() as usize % 8 == 0); |
| 359 | assert!(w.as_ptr() as usize % 16 == 0); |
| 360 | |
| 361 | // alignment should be preserved after boxing |
| 362 | let a: Box<Aligned<A1, [u8]>> = Box::new(Aligned([0u8; 3])); |
| 363 | let x: Box<Aligned<A2, [u8]>> = Box::new(Aligned([0u8; 3])); |
| 364 | let y: Box<Aligned<A4, [u8]>> = Box::new(Aligned([0u8; 3])); |
| 365 | let z: Box<Aligned<A8, [u8]>> = Box::new(Aligned([0u8; 3])); |
| 366 | let w: Box<Aligned<A16, [u8]>> = Box::new(Aligned([0u8; 3])); |
| 367 | |
| 368 | assert_eq!(mem::align_of_val(&*a), 1); |
| 369 | assert_eq!(mem::align_of_val(&*x), 2); |
| 370 | assert_eq!(mem::align_of_val(&*y), 4); |
| 371 | assert_eq!(mem::align_of_val(&*z), 8); |
| 372 | assert_eq!(mem::align_of_val(&*w), 16); |
| 373 | |
| 374 | // test coercions |
| 375 | let x: Aligned<A2, _> = Aligned([0u8; 3]); |
| 376 | let y: &Aligned<A2, [u8]> = &x; |
| 377 | let _: &[u8] = y; |
| 378 | } |
| 379 | |