use std::ptr::{Alignment, Thin};
use crate::VerifyError;
#[must_use]
pub const fn max_alignment<const N: usize>(alignments: [Alignment; N]) -> Alignment {
let mut max = Alignment::MIN;
let mut i = 0;
while i < N {
if max.as_usize() < alignments[i].as_usize() {
max = alignments[i];
}
i += 1;
}
max
}
#[must_use]
pub fn align_offset<T>(ptr: usize) -> usize {
(!ptr + 1) & (align_of::<T>() - 1)
}
pub fn check_alignment(address: *const impl Thin, align: Alignment) -> Result<(), VerifyError> {
let address = address as usize;
if address & (align.as_usize() - 1) == 0 {
Ok(())
} else {
Err(VerifyError::UnalignedPointer { address, align })
}
}
pub fn offset_archived(
base: *const u8,
offset: usize,
size: usize,
buffer_end: *const u8,
align: Alignment,
) -> Result<*const u8, VerifyError> {
let data = base.wrapping_add(offset);
check_alignment(data, align)?;
let data_end = data.wrapping_add(size);
if data <= base || data_end < data || buffer_end < data_end {
Err(VerifyError::InvalidPointer {
address: data,
size,
range: base..buffer_end,
})
} else {
Ok(data)
}
}