aligned/
lib.rs

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
32use core::{
33    borrow::{Borrow, BorrowMut},
34    cmp::Ordering,
35    fmt::{Debug, Display},
36    hash::{Hash, Hasher},
37    ops,
38};
39
40use as_slice::{AsMutSlice, AsSlice};
41
42/// A marker trait for an alignment value.
43pub trait Alignment: Copy + sealed::Sealed {}
44
45impl Alignment for A1 {}
46impl Alignment for A2 {}
47impl Alignment for A4 {}
48impl Alignment for A8 {}
49impl Alignment for A16 {}
50impl Alignment for A32 {}
51impl Alignment for A64 {}
52
53mod 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))]
68pub struct A1;
69
70/// 2-byte alignment
71#[derive(Clone, Copy)]
72#[repr(align(2))]
73pub struct A2;
74
75/// 4-byte alignment
76#[derive(Clone, Copy)]
77#[repr(align(4))]
78pub struct A4;
79
80/// 8-byte alignment
81#[derive(Clone, Copy)]
82#[repr(align(8))]
83pub struct A8;
84
85/// 16-byte alignment
86#[derive(Clone, Copy)]
87#[repr(align(16))]
88pub struct A16;
89
90/// 32-byte alignment
91#[derive(Clone, Copy)]
92#[repr(align(32))]
93pub struct A32;
94
95/// 64-byte alignment
96#[derive(Clone, Copy)]
97#[repr(align(64))]
98pub struct A64;
99
100/// A newtype with alignment of at least `A` bytes
101#[repr(C)]
102pub struct Aligned<A, T>
103where
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)]
112pub const fn Aligned<A, T>(value: T) -> Aligned<A, T> {
113    Aligned {
114        _alignment: [],
115        value,
116    }
117}
118
119impl<A, T> ops::Deref for Aligned<A, T>
120where
121    A: Alignment,
122    T: ?Sized,
123{
124    type Target = T;
125
126    fn deref(&self) -> &T {
127        &self.value
128    }
129}
130
131impl<A, T> ops::DerefMut for Aligned<A, T>
132where
133    A: Alignment,
134    T: ?Sized,
135{
136    fn deref_mut(&mut self) -> &mut T {
137        &mut self.value
138    }
139}
140
141impl<A, T> ops::Index<ops::RangeTo<usize>> for Aligned<A, [T]>
142where
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
152impl<A, T> AsSlice for Aligned<A, T>
153where
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
164impl<A, T> AsMutSlice for Aligned<A, T>
165where
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
174impl<A, T> Borrow<T> for Aligned<A, T>
175where
176    A: Alignment,
177{
178    fn borrow(&self) -> &T {
179        &self.value
180    }
181}
182
183impl<A, T> BorrowMut<T> for Aligned<A, T>
184where
185    A: Alignment,
186{
187    fn borrow_mut(&mut self) -> &mut T {
188        &mut self.value
189    }
190}
191
192impl<A, T> Borrow<[<Aligned<A, T> as AsSlice>::Element]> for Aligned<A, T>
193where
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
202impl<A, T> BorrowMut<[<Aligned<A, T> as AsSlice>::Element]> for Aligned<A, T>
203where
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
212impl<A, T> Clone for Aligned<A, T>
213where
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
225impl<A, T> Copy for Aligned<A, T>
226where
227    A: Alignment,
228    T: Copy,
229{
230}
231
232impl<A, T> Default for Aligned<A, T>
233where
234    A: Alignment,
235    T: Default,
236{
237    fn default() -> Self {
238        Self {
239            _alignment: [],
240            value: Default::default(),
241        }
242    }
243}
244
245impl<A, T> Debug for Aligned<A, T>
246where
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
255impl<A, T> Display for Aligned<A, T>
256where
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
265impl<A, T> PartialEq for Aligned<A, T>
266where
267    A: Alignment,
268    T: PartialEq,
269{
270    fn eq(&self, other: &Self) -> bool {
271        self.value == other.value
272    }
273}
274
275impl<A, T> Eq for Aligned<A, T>
276where
277    A: Alignment,
278    T: Eq,
279{
280}
281
282impl<A, T> Hash for Aligned<A, T>
283where
284    A: Alignment,
285    T: Hash,
286{
287    fn hash<H: Hasher>(&self, state: &mut H) {
288        self.value.hash(state);
289    }
290}
291
292impl<A, T> Ord for Aligned<A, T>
293where
294    A: Alignment,
295    T: Ord,
296{
297    fn cmp(&self, other: &Self) -> Ordering {
298        self.value.cmp(&other.value)
299    }
300}
301
302impl<A, T> PartialOrd for Aligned<A, T>
303where
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]
313fn 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}