-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3c9a7fe
commit abe1670
Showing
3 changed files
with
150 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,97 +1,110 @@ | ||
use core::{fmt, ops::Range}; | ||
|
||
/// A generic range of addresses. | ||
/// | ||
/// The range is inclusive on the start and exclusive on the end. | ||
/// It is empty if `start >= end`. | ||
#[derive(Clone, Copy, Default, PartialEq, Eq)] | ||
pub struct AddrRange<A> | ||
where | ||
A: From<usize> + Into<usize> + Copy, | ||
{ | ||
/// The lower bound of the range (inclusive). | ||
pub start: A, | ||
/// The upper bound of the range (exclusive). | ||
pub end: A, | ||
} | ||
use crate::{PhysAddr, VirtAddr}; | ||
|
||
macro_rules! usize { | ||
($addr:expr) => { | ||
Into::<usize>::into($addr) | ||
($addr).as_usize() | ||
}; | ||
} | ||
|
||
impl<A> AddrRange<A> | ||
where | ||
A: From<usize> + Into<usize> + Copy, | ||
{ | ||
/// Creates a new address range. | ||
#[inline] | ||
pub const fn new(start: A, end: A) -> Self { | ||
Self { start, end } | ||
} | ||
|
||
/// Creates a new address range from the start address and the size. | ||
#[inline] | ||
pub const fn from_start_size(start: A, size: usize) -> Self { | ||
Self { | ||
start, | ||
end: A::from(usize!(start) + size), | ||
macro_rules! def_range { | ||
($name:ident, $addr_type:ty) => { | ||
/// A generic range of addresses. | ||
/// | ||
/// The range is inclusive on the start and exclusive on the end. | ||
/// It is empty if `start >= end`. | ||
#[derive(Clone, Copy, Default, PartialEq, Eq)] | ||
pub struct $name { | ||
/// The lower bound of the range (inclusive). | ||
pub start: $addr_type, | ||
/// The upper bound of the range (exclusive). | ||
pub end: $addr_type, | ||
} | ||
|
||
impl $name { | ||
/// Creates a new address range. | ||
#[inline] | ||
pub const fn new(start: $addr_type, end: $addr_type) -> Self { | ||
Self { start, end } | ||
} | ||
|
||
/// Creates a new address range from the start address and the size. | ||
#[inline] | ||
pub const fn from_start_size(start: $addr_type, size: usize) -> Self { | ||
Self { | ||
start, | ||
end: <$addr_type>::from(usize!(start) + size), | ||
} | ||
} | ||
|
||
/// Returns `true` if the range is empty (`start >= end`). | ||
#[inline] | ||
pub const fn is_empty(self) -> bool { | ||
usize!(self.start) >= usize!(self.end) | ||
} | ||
|
||
/// Returns the size of the range. | ||
#[inline] | ||
pub const fn size(self) -> usize { | ||
usize!(self.end) - usize!(self.start) | ||
} | ||
|
||
/// Checks if the range contains the given address. | ||
#[inline] | ||
pub const fn contains(self, addr: $addr_type) -> bool { | ||
usize!(self.start) <= usize!(addr) && usize!(addr) < usize!(self.end) | ||
} | ||
|
||
/// Checks if the range contains the given address range. | ||
#[inline] | ||
pub const fn contains_range(self, other: Self) -> bool { | ||
usize!(self.start) <= usize!(other.start) && usize!(other.end) <= usize!(self.end) | ||
} | ||
|
||
/// Checks if the range is contained in the given address range. | ||
#[inline] | ||
pub const fn contained_in(self, other: Self) -> bool { | ||
other.contains_range(self) | ||
} | ||
|
||
/// Checks if the range overlaps with the given address range. | ||
#[inline] | ||
pub const fn overlaps(self, other: Self) -> bool { | ||
usize!(self.start) < usize!(other.end) && usize!(other.start) < usize!(self.end) | ||
} | ||
} | ||
|
||
impl<A> From<Range<A>> for $name | ||
where | ||
A: From<usize> + Into<usize>, | ||
{ | ||
fn from(range: Range<A>) -> Self { | ||
Self::new(range.start.into().into(), range.end.into().into()) | ||
} | ||
} | ||
|
||
impl fmt::Debug for $name { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "{:#x?}..{:#x?}", usize!(self.start), usize!(self.end)) | ||
} | ||
} | ||
} | ||
|
||
/// Returns `true` if the range is empty (`start >= end`). | ||
#[inline] | ||
pub const fn is_empty(self) -> bool { | ||
usize!(self.start) >= usize!(self.end) | ||
} | ||
|
||
/// Returns the size of the range. | ||
#[inline] | ||
pub const fn size(self) -> usize { | ||
self.end.into() - self.start.into() | ||
} | ||
|
||
/// Checks if the range contains the given address. | ||
#[inline] | ||
pub const fn contains(self, addr: A) -> bool { | ||
usize!(self.start) <= usize!(addr) && usize!(addr) < usize!(self.end) | ||
} | ||
|
||
/// Checks if the range contains the given address range. | ||
#[inline] | ||
pub const fn contains_range(self, other: Self) -> bool { | ||
usize!(self.start) <= usize!(other.start) && usize!(other.end) <= usize!(self.end) | ||
} | ||
|
||
/// Checks if the range is contained in the given address range. | ||
#[inline] | ||
pub const fn contained_in(self, other: Self) -> bool { | ||
other.contains_range(self) | ||
} | ||
|
||
/// Checks if the range overlaps with the given address range. | ||
#[inline] | ||
pub const fn overlaps(self, other: Self) -> bool { | ||
usize!(self.start) < usize!(other.end) && usize!(other.start) < usize!(self.end) | ||
} | ||
}; | ||
} | ||
|
||
impl<A, B> From<Range<B>> for AddrRange<A> | ||
where | ||
A: From<usize> + Into<usize> + Copy, | ||
B: Into<A>, | ||
{ | ||
fn from(range: Range<B>) -> Self { | ||
Self::new(range.start.into(), range.end.into()) | ||
} | ||
def_range!(VirtAddrRange, VirtAddr); | ||
def_range!(PhysAddrRange, PhysAddr); | ||
|
||
#[macro_export] | ||
macro_rules! va_range { | ||
($range:expr) => { | ||
$crate::VirtAddrRange::from($range) | ||
}; | ||
} | ||
|
||
impl<A> fmt::Debug for AddrRange<A> | ||
where | ||
A: From<usize> + Into<usize> + Copy, | ||
{ | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "{:#x?}..{:#x?}", usize!(self.start), usize!(self.end)) | ||
} | ||
#[macro_export] | ||
macro_rules! pa_range { | ||
($range:expr) => { | ||
$crate::PhysAddrRange::from($range) | ||
}; | ||
} |