memory_addr/
lib.rs

1#![cfg_attr(not(test), no_std)]
2#![doc = include_str!("../README.md")]
3
4mod addr;
5mod iter;
6mod range;
7
8pub use self::addr::{MemoryAddr, PhysAddr, VirtAddr};
9pub use self::iter::PageIter;
10pub use self::range::{AddrRange, PhysAddrRange, VirtAddrRange};
11
12/// The size of a 4K page (4096 bytes).
13pub const PAGE_SIZE_4K: usize = 0x1000;
14
15/// A [`PageIter`] for 4K pages.
16pub type PageIter4K<A> = PageIter<PAGE_SIZE_4K, A>;
17
18/// Align address downwards.
19///
20/// Returns the greatest `x` with alignment `align` so that `x <= addr`.
21///
22/// The alignment must be a power of two.
23#[inline]
24pub const fn align_down(addr: usize, align: usize) -> usize {
25    addr & !(align - 1)
26}
27
28/// Align address upwards.
29///
30/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
31///
32/// The alignment must be a power of two.
33#[inline]
34pub const fn align_up(addr: usize, align: usize) -> usize {
35    (addr + align - 1) & !(align - 1)
36}
37
38/// Returns the offset of the address within the alignment.
39///
40/// Equivalent to `addr % align`, but the alignment must be a power of two.
41#[inline]
42pub const fn align_offset(addr: usize, align: usize) -> usize {
43    addr & (align - 1)
44}
45
46/// Checks whether the address has the demanded alignment.
47///
48/// Equivalent to `addr % align == 0`, but the alignment must be a power of two.
49#[inline]
50pub const fn is_aligned(addr: usize, align: usize) -> bool {
51    align_offset(addr, align) == 0
52}
53
54/// Align address downwards to 4096 (bytes).
55#[inline]
56pub const fn align_down_4k(addr: usize) -> usize {
57    align_down(addr, PAGE_SIZE_4K)
58}
59
60/// Align address upwards to 4096 (bytes).
61#[inline]
62pub const fn align_up_4k(addr: usize) -> usize {
63    align_up(addr, PAGE_SIZE_4K)
64}
65
66/// Returns the offset of the address within a 4K-sized page.
67#[inline]
68pub const fn align_offset_4k(addr: usize) -> usize {
69    align_offset(addr, PAGE_SIZE_4K)
70}
71
72/// Checks whether the address is 4K-aligned.
73#[inline]
74pub const fn is_aligned_4k(addr: usize) -> bool {
75    is_aligned(addr, PAGE_SIZE_4K)
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_align() {
84        assert_eq!(align_down(0x12345678, 0x1000), 0x12345000);
85        assert_eq!(align_up(0x12345678, 0x1000), 0x12346000);
86        assert_eq!(align_offset(0x12345678, 0x1000), 0x678);
87        assert!(is_aligned(0x12345000, 0x1000));
88        assert!(!is_aligned(0x12345678, 0x1000));
89
90        assert_eq!(align_down_4k(0x12345678), 0x12345000);
91        assert_eq!(align_up_4k(0x12345678), 0x12346000);
92        assert_eq!(align_offset_4k(0x12345678), 0x678);
93        assert!(is_aligned_4k(0x12345000));
94        assert!(!is_aligned_4k(0x12345678));
95    }
96}