#[inline]
pub fn align_to_4_bytes(value: u64) -> u64 {
(value + 3) & !3
}
#[inline]
pub fn align_to(value: u64, alignment: u64) -> u64 {
debug_assert!(
alignment.is_power_of_two(),
"alignment must be a power of 2, got {alignment}"
);
(value + alignment - 1) & !(alignment - 1)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_align_to_4_bytes() {
assert_eq!(align_to_4_bytes(0), 0);
assert_eq!(align_to_4_bytes(1), 4);
assert_eq!(align_to_4_bytes(2), 4);
assert_eq!(align_to_4_bytes(3), 4);
assert_eq!(align_to_4_bytes(4), 4);
assert_eq!(align_to_4_bytes(5), 8);
assert_eq!(align_to_4_bytes(8), 8);
assert_eq!(align_to_4_bytes(9), 12);
}
#[test]
fn test_align_to() {
assert_eq!(align_to(100, 16), 112);
assert_eq!(align_to(112, 16), 112);
assert_eq!(align_to(113, 16), 128);
assert_eq!(align_to(128, 16), 128);
assert_eq!(align_to(200, 256), 256);
assert_eq!(align_to(256, 256), 256);
assert_eq!(align_to(300, 256), 512);
assert_eq!(align_to(1000, 512), 1024);
assert_eq!(align_to(1024, 512), 1024);
assert_eq!(align_to(1500, 512), 1536);
}
#[test]
fn test_alignment_properties() {
let test_alignments = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024];
for &alignment in &test_alignments {
for test_value in [1, alignment - 1, alignment, alignment + 1, alignment * 2] {
let aligned = align_to(test_value, alignment);
assert!(aligned >= test_value);
assert_eq!(
aligned % alignment,
0,
"align_to({test_value}, {alignment}) = {aligned} is not aligned"
);
assert!(
aligned < test_value + alignment,
"align_to({test_value}, {alignment}) = {aligned} over-aligned"
);
}
}
}
#[test]
fn test_4_byte_alignment_properties() {
for test_value in 0..20u64 {
let aligned = align_to_4_bytes(test_value);
assert!(aligned >= test_value);
if aligned != 0 {
assert_eq!(
aligned % 4,
0,
"Value {test_value} aligned to {aligned} is not 4-byte aligned"
);
}
assert!(aligned - test_value < 4, "Alignment added too many bytes");
}
}
#[test]
#[should_panic(expected = "alignment must be a power of 2")]
#[cfg(debug_assertions)]
fn test_align_to_non_power_of_2_panics() {
let _ = align_to(100, 3);
}
#[test]
#[cfg(debug_assertions)]
fn test_align_to_zero_alignment_panics() {
let result = std::panic::catch_unwind(|| align_to(100, 0));
assert!(result.is_err(), "align_to with 0 alignment should panic");
}
}