//! Small memory utilities useful in kernels.
//!
//! These helpers are `no_std` and avoid panics, focusing on correctness and clarity.

/// Returns `true` if `addr` is aligned to `align` (which must be a power of two).
#[inline]
pub const fn is_aligned(addr: usize, align: usize) -> bool {
    addr & (align - 1) == 0
}

/// Rounds `addr` down to the nearest multiple of `align` (power of two).
#[inline]
pub const fn align_down(addr: usize, align: usize) -> usize {
    addr & !(align - 1)
}

/// Rounds `addr` up to the nearest multiple of `align` (power of two).
#[inline]
pub const fn align_up(addr: usize, align: usize) -> usize {
    (addr + align - 1) & !(align - 1)
}

/// Checks whether the range `[ptr, ptr + len)` is valid when `limit` is the maximum addressable value.
///
/// Returns `false` on overflow or out-of-bounds.
#[inline]
pub const fn range_fits(ptr: usize, len: usize, limit: usize) -> bool {
    match ptr.checked_add(len) {
        Some(end) => end <= limit,
        None => false,
    }
}

/// Common page sizes (not architecture-specific, purely conventional).
pub mod page {
    /// 4 KiB page size.
    pub const SIZE_4K: usize = 4096;
    /// 2 MiB page size.
    pub const SIZE_2M: usize = 2 * 1024 * 1024;
    /// 1 GiB page size.
    pub const SIZE_1G: usize = 1024 * 1024 * 1024;
}

