mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 12:56:48 +00:00
Split ostd/util.rs
This commit is contained in:
parent
f8429b2735
commit
1a1d9bfb60
@ -9,7 +9,7 @@ use crate::{
|
||||
page_table::PageTableEntryTrait,
|
||||
Paddr, PagingConstsTrait, PagingLevel, Vaddr, PAGE_SIZE,
|
||||
},
|
||||
util::SameSizeAs,
|
||||
util::marker::SameSizeAs,
|
||||
Pod,
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
page_table::{PageTableEntryTrait, PageTableMode},
|
||||
Paddr, PageProperty, PagingConstsTrait, PagingLevel, PodOnce, Vaddr,
|
||||
},
|
||||
util::SameSizeAs,
|
||||
util::marker::SameSizeAs,
|
||||
Pod,
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,7 @@ use crate::{
|
||||
page_table::PageTableEntryTrait,
|
||||
Paddr, PagingConstsTrait, PagingLevel, PodOnce, Vaddr, PAGE_SIZE,
|
||||
},
|
||||
util::SameSizeAs,
|
||||
util::marker::SameSizeAs,
|
||||
Pod,
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
impl_frame_meta_for,
|
||||
mm::{paddr_to_vaddr, Paddr, PAGE_SIZE},
|
||||
prelude::*,
|
||||
util::range_difference,
|
||||
util::ops::range_difference,
|
||||
};
|
||||
|
||||
/// Options for allocating physical memory frames.
|
||||
|
@ -64,7 +64,7 @@ use crate::{
|
||||
Vaddr, VmReader, PAGE_SIZE,
|
||||
},
|
||||
panic::abort,
|
||||
util::range_difference,
|
||||
util::ops::range_difference,
|
||||
};
|
||||
|
||||
/// The maximum number of bytes of the metadata of a frame.
|
||||
|
@ -14,7 +14,7 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
arch::mm::{PageTableEntry, PagingConsts},
|
||||
util::SameSizeAs,
|
||||
util::marker::SameSizeAs,
|
||||
Pod,
|
||||
};
|
||||
|
||||
|
16
ostd/src/util/macros.rs
Normal file
16
ostd/src/util/macros.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// Asserts that a boolean expression is `true` at compile-time.
|
||||
///
|
||||
/// Rust provides [`const` blocks], which can be used flexibly within methods, but cannot be used
|
||||
/// directly at the top level. This macro serves as a helper to perform compile-time assertions
|
||||
/// outside of methods.
|
||||
///
|
||||
/// [`const` blocks]: https://doc.rust-lang.org/reference/expressions/block-expr.html#const-blocks
|
||||
//
|
||||
// TODO: Introduce `const_assert_eq!()` once `assert_eq!()` can be used in the `const` context.
|
||||
#[macro_export]
|
||||
macro_rules! const_assert {
|
||||
($cond:expr $(,)?) => { const _: () = assert!($cond); };
|
||||
($cond:expr, $($arg:tt)+) => { const _: () = assert!($cond, $($arg)*); };
|
||||
}
|
8
ostd/src/util/marker.rs
Normal file
8
ostd/src/util/marker.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// A marker trait that represents a type has the same size as `T`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Types that implement `SameSizeAs<T>` must have the same size as `T`.
|
||||
pub unsafe trait SameSizeAs<T> {}
|
@ -1,106 +1,6 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
mod macros;
|
||||
pub mod marker;
|
||||
pub mod ops;
|
||||
pub mod range_alloc;
|
||||
|
||||
use core::ops::Range;
|
||||
|
||||
/// Asserts that a boolean expression is `true` at compile-time.
|
||||
///
|
||||
/// Rust provides [`const` blocks], which can be used flexibly within methods, but cannot be used
|
||||
/// directly at the top level. This macro serves as a helper to perform compile-time assertions
|
||||
/// outside of methods.
|
||||
///
|
||||
/// [`const` blocks]: https://doc.rust-lang.org/reference/expressions/block-expr.html#const-blocks
|
||||
//
|
||||
// TODO: Introduce `const_assert_eq!()` once `assert_eq!()` can be used in the `const` context.
|
||||
#[macro_export]
|
||||
macro_rules! const_assert {
|
||||
($cond:expr $(,)?) => { const _: () = assert!($cond); };
|
||||
($cond:expr, $($arg:tt)+) => { const _: () = assert!($cond, $($arg)*); };
|
||||
}
|
||||
|
||||
/// A marker trait that represents a type has the same size as `T`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Types that implement `SameSizeAs<T>` must have the same size as `T`.
|
||||
pub unsafe trait SameSizeAs<T> {}
|
||||
|
||||
/// Calculates the [difference] of two [`Range`]s, i.e., `a - b`.
|
||||
///
|
||||
/// This method will return 0, 1, or 2 ranges. All returned ranges are
|
||||
/// guaranteed to be non-empty and non-overlapping. The returned ranges
|
||||
/// will be sorted in ascending order.
|
||||
///
|
||||
/// [difference]: https://en.wikipedia.org/wiki/Set_(mathematics)#Set_difference
|
||||
pub fn range_difference<T: Ord + Copy>(
|
||||
a: &Range<T>,
|
||||
b: &Range<T>,
|
||||
) -> impl Iterator<Item = Range<T>> {
|
||||
use core::cmp::{max, min};
|
||||
|
||||
let r = if b.is_empty() {
|
||||
[a.clone(), b.clone()]
|
||||
} else {
|
||||
[a.start..min(a.end, b.start), max(a.start, b.end)..a.end]
|
||||
};
|
||||
|
||||
r.into_iter().filter(|v| !v.is_empty())
|
||||
}
|
||||
|
||||
#[cfg(ktest)]
|
||||
#[expect(clippy::single_range_in_vec_init)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::prelude::ktest;
|
||||
|
||||
#[track_caller]
|
||||
fn assert_range_difference<const N: usize>(
|
||||
a: Range<usize>,
|
||||
b: Range<usize>,
|
||||
expected: [Range<usize>; N],
|
||||
) {
|
||||
let mut res = range_difference(&a, &b);
|
||||
expected
|
||||
.into_iter()
|
||||
.for_each(|val| assert_eq!(res.next(), Some(val)));
|
||||
assert!(res.next().is_none());
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn range_difference_contained() {
|
||||
assert_range_difference(0..10, 3..7, [0..3, 7..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_all_same() {
|
||||
assert_range_difference(0..10, 0..10, []);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_left_same() {
|
||||
assert_range_difference(0..10, 0..5, [5..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_right_same() {
|
||||
assert_range_difference(0..10, 5..10, [0..5]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_b_empty() {
|
||||
assert_range_difference(0..10, 0..0, [0..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_a_empty() {
|
||||
assert_range_difference(0..0, 0..10, []);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_all_empty() {
|
||||
assert_range_difference(0..0, 0..0, []);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_left_intersected() {
|
||||
assert_range_difference(5..10, 0..6, [6..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_right_intersected() {
|
||||
assert_range_difference(5..10, 6..12, [5..6]);
|
||||
}
|
||||
}
|
||||
|
82
ostd/src/util/ops.rs
Normal file
82
ostd/src/util/ops.rs
Normal file
@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::ops::Range;
|
||||
|
||||
/// Calculates the [difference] of two [`Range`]s, i.e., `a - b`.
|
||||
///
|
||||
/// This method will return 0, 1, or 2 ranges. All returned ranges are
|
||||
/// guaranteed to be non-empty and non-overlapping. The returned ranges
|
||||
/// will be sorted in ascending order.
|
||||
///
|
||||
/// [difference]: https://en.wikipedia.org/wiki/Set_(mathematics)#Set_difference
|
||||
pub fn range_difference<T: Ord + Copy>(
|
||||
a: &Range<T>,
|
||||
b: &Range<T>,
|
||||
) -> impl Iterator<Item = Range<T>> {
|
||||
use core::cmp::{max, min};
|
||||
|
||||
let r = if b.is_empty() {
|
||||
[a.clone(), b.clone()]
|
||||
} else {
|
||||
[a.start..min(a.end, b.start), max(a.start, b.end)..a.end]
|
||||
};
|
||||
|
||||
r.into_iter().filter(|v| !v.is_empty())
|
||||
}
|
||||
|
||||
#[cfg(ktest)]
|
||||
#[expect(clippy::single_range_in_vec_init)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::prelude::ktest;
|
||||
|
||||
#[track_caller]
|
||||
fn assert_range_difference<const N: usize>(
|
||||
a: Range<usize>,
|
||||
b: Range<usize>,
|
||||
expected: [Range<usize>; N],
|
||||
) {
|
||||
let mut res = range_difference(&a, &b);
|
||||
expected
|
||||
.into_iter()
|
||||
.for_each(|val| assert_eq!(res.next(), Some(val)));
|
||||
assert!(res.next().is_none());
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn range_difference_contained() {
|
||||
assert_range_difference(0..10, 3..7, [0..3, 7..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_all_same() {
|
||||
assert_range_difference(0..10, 0..10, []);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_left_same() {
|
||||
assert_range_difference(0..10, 0..5, [5..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_right_same() {
|
||||
assert_range_difference(0..10, 5..10, [0..5]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_b_empty() {
|
||||
assert_range_difference(0..10, 0..0, [0..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_a_empty() {
|
||||
assert_range_difference(0..0, 0..10, []);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_all_empty() {
|
||||
assert_range_difference(0..0, 0..0, []);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_left_intersected() {
|
||||
assert_range_difference(5..10, 0..6, [6..10]);
|
||||
}
|
||||
#[ktest]
|
||||
fn range_difference_right_intersected() {
|
||||
assert_range_difference(5..10, 6..12, [5..6]);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user