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