From 1a1d9bfb60ec2a203ad2fbf39417cc353b0447d0 Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Tue, 18 Mar 2025 00:43:28 +0800 Subject: [PATCH] Split `ostd/util.rs` --- ostd/src/arch/riscv/mm/mod.rs | 2 +- .../x86/iommu/dma_remapping/second_stage.rs | 2 +- ostd/src/arch/x86/mm/mod.rs | 2 +- ostd/src/mm/frame/allocator.rs | 2 +- ostd/src/mm/frame/meta.rs | 2 +- ostd/src/mm/page_table/mod.rs | 2 +- ostd/src/util/macros.rs | 16 +++ ostd/src/util/marker.rs | 8 ++ ostd/src/util/mod.rs | 106 +----------------- ostd/src/util/ops.rs | 82 ++++++++++++++ 10 files changed, 115 insertions(+), 109 deletions(-) create mode 100644 ostd/src/util/macros.rs create mode 100644 ostd/src/util/marker.rs create mode 100644 ostd/src/util/ops.rs diff --git a/ostd/src/arch/riscv/mm/mod.rs b/ostd/src/arch/riscv/mm/mod.rs index f9abb7f69..3bdf9dda1 100644 --- a/ostd/src/arch/riscv/mm/mod.rs +++ b/ostd/src/arch/riscv/mm/mod.rs @@ -9,7 +9,7 @@ use crate::{ page_table::PageTableEntryTrait, Paddr, PagingConstsTrait, PagingLevel, Vaddr, PAGE_SIZE, }, - util::SameSizeAs, + util::marker::SameSizeAs, Pod, }; diff --git a/ostd/src/arch/x86/iommu/dma_remapping/second_stage.rs b/ostd/src/arch/x86/iommu/dma_remapping/second_stage.rs index 3b9e8449c..35176b5ad 100644 --- a/ostd/src/arch/x86/iommu/dma_remapping/second_stage.rs +++ b/ostd/src/arch/x86/iommu/dma_remapping/second_stage.rs @@ -10,7 +10,7 @@ use crate::{ page_table::{PageTableEntryTrait, PageTableMode}, Paddr, PageProperty, PagingConstsTrait, PagingLevel, PodOnce, Vaddr, }, - util::SameSizeAs, + util::marker::SameSizeAs, Pod, }; diff --git a/ostd/src/arch/x86/mm/mod.rs b/ostd/src/arch/x86/mm/mod.rs index 548760996..bee800fc3 100644 --- a/ostd/src/arch/x86/mm/mod.rs +++ b/ostd/src/arch/x86/mm/mod.rs @@ -15,7 +15,7 @@ use crate::{ page_table::PageTableEntryTrait, Paddr, PagingConstsTrait, PagingLevel, PodOnce, Vaddr, PAGE_SIZE, }, - util::SameSizeAs, + util::marker::SameSizeAs, Pod, }; diff --git a/ostd/src/mm/frame/allocator.rs b/ostd/src/mm/frame/allocator.rs index ee6f4d06e..9e423743c 100644 --- a/ostd/src/mm/frame/allocator.rs +++ b/ostd/src/mm/frame/allocator.rs @@ -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. diff --git a/ostd/src/mm/frame/meta.rs b/ostd/src/mm/frame/meta.rs index 5b4e47b0f..53f782792 100644 --- a/ostd/src/mm/frame/meta.rs +++ b/ostd/src/mm/frame/meta.rs @@ -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. diff --git a/ostd/src/mm/page_table/mod.rs b/ostd/src/mm/page_table/mod.rs index 9a1b6f6a2..af942edbd 100644 --- a/ostd/src/mm/page_table/mod.rs +++ b/ostd/src/mm/page_table/mod.rs @@ -14,7 +14,7 @@ use super::{ }; use crate::{ arch::mm::{PageTableEntry, PagingConsts}, - util::SameSizeAs, + util::marker::SameSizeAs, Pod, }; diff --git a/ostd/src/util/macros.rs b/ostd/src/util/macros.rs new file mode 100644 index 000000000..ae6aa687c --- /dev/null +++ b/ostd/src/util/macros.rs @@ -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)*); }; +} diff --git a/ostd/src/util/marker.rs b/ostd/src/util/marker.rs new file mode 100644 index 000000000..379dd4b5d --- /dev/null +++ b/ostd/src/util/marker.rs @@ -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` must have the same size as `T`. +pub unsafe trait SameSizeAs {} diff --git a/ostd/src/util/mod.rs b/ostd/src/util/mod.rs index a372b041a..bbda50051 100644 --- a/ostd/src/util/mod.rs +++ b/ostd/src/util/mod.rs @@ -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` must have the same size as `T`. -pub unsafe trait SameSizeAs {} - -/// 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( - a: &Range, - b: &Range, -) -> impl Iterator> { - 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( - a: Range, - b: Range, - expected: [Range; 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]); - } -} diff --git a/ostd/src/util/ops.rs b/ostd/src/util/ops.rs new file mode 100644 index 000000000..bfdb9139b --- /dev/null +++ b/ostd/src/util/ops.rs @@ -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( + a: &Range, + b: &Range, +) -> impl Iterator> { + 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( + a: Range, + b: Range, + expected: [Range; 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]); + } +}