Split ostd/util.rs

This commit is contained in:
Ruihan Li 2025-03-18 00:43:28 +08:00 committed by Tate, Hongliang Tian
parent f8429b2735
commit 1a1d9bfb60
10 changed files with 115 additions and 109 deletions

View File

@ -9,7 +9,7 @@ use crate::{
page_table::PageTableEntryTrait,
Paddr, PagingConstsTrait, PagingLevel, Vaddr, PAGE_SIZE,
},
util::SameSizeAs,
util::marker::SameSizeAs,
Pod,
};

View File

@ -10,7 +10,7 @@ use crate::{
page_table::{PageTableEntryTrait, PageTableMode},
Paddr, PageProperty, PagingConstsTrait, PagingLevel, PodOnce, Vaddr,
},
util::SameSizeAs,
util::marker::SameSizeAs,
Pod,
};

View File

@ -15,7 +15,7 @@ use crate::{
page_table::PageTableEntryTrait,
Paddr, PagingConstsTrait, PagingLevel, PodOnce, Vaddr, PAGE_SIZE,
},
util::SameSizeAs,
util::marker::SameSizeAs,
Pod,
};

View File

@ -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.

View File

@ -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.

View File

@ -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
View 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
View 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> {}

View File

@ -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
View 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]);
}
}