Skip to content

Commit fee153d

Browse files
committed
libkernel: region: add new utility functions
Add the following to all memory region variants: - `is_empty()`: Return true if the region has zero size. - `cap_size()`: Reduces the size if the given size < current. - `shrink_start()`: Move start address forward, while shrinking the region.
1 parent 64c8b02 commit fee153d

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

libkernel/src/memory/region.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ impl<T: MemKind> MemoryRegion<T> {
5959
}
6060
}
6161

62+
/// Returns `true` if this memory region is empty.
63+
pub fn is_empty(self) -> bool {
64+
self.size == 0
65+
}
66+
6267
/// Create a memory region from a start and end address.
6368
///
6469
/// The size is calculated as `end - start`. No alignment is enforced.
@@ -71,6 +76,27 @@ impl<T: MemKind> MemoryRegion<T> {
7176
}
7277
}
7378

79+
/// Cap the size of the region. If `max_size < self.size`, the region is
80+
/// shrunk.
81+
pub fn cap_size(self, max_size: usize) -> Self {
82+
if max_size < self.size {
83+
Self::new(self.start_address(), max_size)
84+
} else {
85+
self
86+
}
87+
}
88+
89+
/// Shrink this region by moving the start address 'forward' by `x` bytes.
90+
///
91+
/// If `x` moves the start address beyond the end of the region, it
92+
/// saturates on the boundary and becomes empty.
93+
pub fn shrink_start(self, x: usize) -> Self {
94+
Self {
95+
address: self.start_address().add_bytes(x),
96+
size: self.size.saturating_sub(x),
97+
}
98+
}
99+
74100
/// Return a new region with the same size but a different start address.
75101
pub fn with_start_address(mut self, new_start: Address<T, ()>) -> Self {
76102
self.address = new_start;
@@ -676,6 +702,83 @@ mod tests {
676702
assert_eq!(main.punch_hole(hole), (Some(main), None));
677703
}
678704

705+
#[test]
706+
fn is_empty_zero_size() {
707+
let r = region(0x1000, 0);
708+
assert!(r.is_empty());
709+
}
710+
711+
#[test]
712+
fn is_empty_nonzero_size() {
713+
let r = region(0x1000, 0x10);
714+
assert!(!r.is_empty());
715+
}
716+
717+
#[test]
718+
fn is_empty_empty_constructor() {
719+
assert!(PhysMemoryRegion::empty().is_empty());
720+
}
721+
722+
#[test]
723+
fn cap_size_below_current() {
724+
let r = region(0x1000, 0x100);
725+
let capped = r.cap_size(0x50);
726+
assert_eq!(capped.start_address().value(), 0x1000);
727+
assert_eq!(capped.size(), 0x50);
728+
}
729+
730+
#[test]
731+
fn cap_size_equal_to_current() {
732+
let r = region(0x1000, 0x100);
733+
let capped = r.cap_size(0x100);
734+
assert_eq!(capped, r);
735+
}
736+
737+
#[test]
738+
fn cap_size_above_current() {
739+
let r = region(0x1000, 0x100);
740+
let capped = r.cap_size(0x200);
741+
assert_eq!(capped, r);
742+
}
743+
744+
#[test]
745+
fn cap_size_to_zero() {
746+
let r = region(0x1000, 0x100);
747+
let capped = r.cap_size(0);
748+
assert_eq!(capped.start_address().value(), 0x1000);
749+
assert!(capped.is_empty());
750+
}
751+
752+
#[test]
753+
fn shrink_start_within_bounds() {
754+
let r = region(0x1000, 0x100);
755+
let shrunk = r.shrink_start(0x40);
756+
assert_eq!(shrunk.start_address().value(), 0x1040);
757+
assert_eq!(shrunk.size(), 0xC0);
758+
}
759+
760+
#[test]
761+
fn shrink_start_exact_size() {
762+
let r = region(0x1000, 0x100);
763+
let shrunk = r.shrink_start(0x100);
764+
assert_eq!(shrunk.start_address().value(), 0x1100);
765+
assert!(shrunk.is_empty());
766+
}
767+
768+
#[test]
769+
fn shrink_start_beyond_end_saturates() {
770+
let r = region(0x1000, 0x100);
771+
let shrunk = r.shrink_start(0x200);
772+
assert_eq!(shrunk.start_address().value(), 0x1200);
773+
assert!(shrunk.is_empty());
774+
}
775+
776+
#[test]
777+
fn shrink_start_zero() {
778+
let r = region(0x1000, 0x100);
779+
assert_eq!(r.shrink_start(0), r);
780+
}
781+
679782
#[test]
680783
fn test_punch_hole_disjoint() {
681784
// Hole is completely far away (after)

0 commit comments

Comments
 (0)