| 1 | use core::num::NonZeroUsize; |
| 2 | |
| 3 | /// Returns the amount of padding we must insert after `len` bytes to ensure |
| 4 | /// that the following address will satisfy `align` (measured in bytes). |
| 5 | /// |
| 6 | /// e.g., if `len` is 9, then `padding_needed_for(len, 4)` returns 3, because |
| 7 | /// that is the minimum number of bytes of padding required to get a 4-aligned |
| 8 | /// address (assuming that the corresponding memory block starts at a 4-aligned |
| 9 | /// address). |
| 10 | /// |
| 11 | /// The return value of this function has no meaning if `align` is not a |
| 12 | /// power-of-two. |
| 13 | /// |
| 14 | /// # Panics |
| 15 | /// |
| 16 | /// May panic if `align` is not a power of two. |
| 17 | // |
| 18 | // TODO(#419): Replace `len` with a witness type for region size. |
| 19 | #[allow (unused)] |
| 20 | #[inline (always)] |
| 21 | pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize { |
| 22 | // Rounded up value is: |
| 23 | // len_rounded_up = (len + align - 1) & !(align - 1); |
| 24 | // and then we return the padding difference: `len_rounded_up - len`. |
| 25 | // |
| 26 | // We use modular arithmetic throughout: |
| 27 | // |
| 28 | // 1. align is guaranteed to be > 0, so align - 1 is always |
| 29 | // valid. |
| 30 | // |
| 31 | // 2. `len + align - 1` can overflow by at most `align - 1`, |
| 32 | // so the &-mask with `!(align - 1)` will ensure that in the |
| 33 | // case of overflow, `len_rounded_up` will itself be 0. |
| 34 | // Thus the returned padding, when added to `len`, yields 0, |
| 35 | // which trivially satisfies the alignment `align`. |
| 36 | // |
| 37 | // (Of course, attempts to allocate blocks of memory whose |
| 38 | // size and padding overflow in the above manner should cause |
| 39 | // the allocator to yield an error anyway.) |
| 40 | |
| 41 | let align = align.get(); |
| 42 | debug_assert!(align.is_power_of_two()); |
| 43 | let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); |
| 44 | len_rounded_up.wrapping_sub(len) |
| 45 | } |
| 46 | |