Skip to main content

rav1e/util/
align.rs

1// Copyright (c) 2017-2022, The rav1e contributors. All rights reserved
2//
3// This source code is subject to the terms of the BSD 2 Clause License and
4// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
5// was not distributed with this source code in the LICENSE file, you can
6// obtain it at www.aomedia.org/license/software. If the Alliance for Open
7// Media Patent License 1.0 was not distributed with this source code in the
8// PATENTS file, you can obtain it at www.aomedia.org/license/patent.
9
10use std::mem::MaybeUninit;
11
12#[repr(align(64))]
13pub struct Align64;
14
15// A 64 byte aligned piece of data.
16// # Examples
17// ```
18// let mut x: Aligned<[i16; 64 * 64]> = Aligned::new([0; 64 * 64]);
19// assert!(x.data.as_ptr() as usize % 16 == 0);
20//
21// let mut x: Aligned<[i16; 64 * 64]> = Aligned::uninitialized();
22// assert!(x.data.as_ptr() as usize % 16 == 0);
23// ```
24pub struct Aligned<T> {
25  _alignment: [Align64; 0],
26  pub data: T,
27}
28
29#[cfg(any(test, feature = "bench"))]
30impl<const N: usize, T> Aligned<[T; N]> {
31  #[inline(always)]
32  pub fn from_fn<F>(cb: F) -> Self
33  where
34    F: FnMut(usize) -> T,
35  {
36    Aligned { _alignment: [], data: std::array::from_fn(cb) }
37  }
38}
39
40impl<const N: usize, T> Aligned<[MaybeUninit<T>; N]> {
41  #[inline(always)]
42  pub const fn uninit_array() -> Self {
43    Aligned {
44      _alignment: [],
45      // SAFETY: Uninitialized [MaybeUninit<T>; N] is valid.
46      data: unsafe { MaybeUninit::uninit().assume_init() },
47    }
48  }
49}
50
51impl<T> Aligned<T> {
52  pub const fn new(data: T) -> Self {
53    Aligned { _alignment: [], data }
54  }
55  #[allow(clippy::uninit_assumed_init)]
56  /// # Safety
57  ///
58  /// The resulting `Aligned<T>` *must* be written to before it is read from.
59  pub const unsafe fn uninitialized() -> Self {
60    Self::new(MaybeUninit::uninit().assume_init())
61  }
62}
63
64#[cfg(test)]
65mod test {
66  use super::*;
67
68  fn is_aligned<T>(ptr: *const T, n: usize) -> bool {
69    ((ptr as usize) & ((1 << n) - 1)) == 0
70  }
71
72  #[test]
73  fn sanity_stack() {
74    let a: Aligned<_> = Aligned::new([0u8; 3]);
75    assert!(is_aligned(a.data.as_ptr(), 4));
76  }
77}