19
19
//! object and defines methods to access and manipulate it.
20
20
21
21
use std:: cmp:: { Eq , Ord , PartialEq , PartialOrd } ;
22
- use std:: ops:: { Add , BitAnd , BitOr , Sub } ;
22
+ use std:: fmt:: Debug ;
23
+ use std:: ops:: { Add , BitAnd , BitOr , Not , Sub } ;
23
24
24
25
/// Simple helper trait used to store a raw address value.
25
26
pub trait AddressValue {
@@ -29,10 +30,23 @@ pub trait AddressValue {
29
30
+ Eq
30
31
+ PartialOrd
31
32
+ Ord
33
+ + Not < Output = Self :: V >
32
34
+ Add < Output = Self :: V >
33
35
+ Sub < Output = Self :: V >
34
36
+ BitAnd < Output = Self :: V >
35
- + BitOr < Output = Self :: V > ;
37
+ + BitOr < Output = Self :: V >
38
+ + Debug
39
+ + From < u8 > ;
40
+
41
+ /// Return the value zero, coerced into the value type `Self::V`
42
+ fn zero ( ) -> Self :: V {
43
+ 0u8 . into ( )
44
+ }
45
+
46
+ /// Return the value zero, coerced into the value type `Self::V`
47
+ fn one ( ) -> Self :: V {
48
+ 1u8 . into ( )
49
+ }
36
50
}
37
51
38
52
/// Trait to represent an address within an address space.
@@ -89,6 +103,21 @@ pub trait Address:
89
103
self . raw_value ( ) - base. raw_value ( )
90
104
}
91
105
106
+ /// Returns self, aligned to the given power of two.
107
+ fn checked_align_up ( & self , power_of_two : Self :: V ) -> Option < Self > {
108
+ let mask = power_of_two - Self :: one ( ) ;
109
+ assert_ne ! ( power_of_two, Self :: zero( ) ) ;
110
+ assert_eq ! ( power_of_two & mask, Self :: zero( ) ) ;
111
+ self . checked_add ( mask) . map ( |x| x & !mask)
112
+ }
113
+
114
+ /// Returns self, aligned to the given power of two.
115
+ /// Only use this when the result is guaranteed not to overflow.
116
+ fn unchecked_align_up ( & self , power_of_two : Self :: V ) -> Self {
117
+ let mask = power_of_two - Self :: one ( ) ;
118
+ self . unchecked_add ( mask) & !mask
119
+ }
120
+
92
121
/// Computes `self + other`, returning `None` if overflow occurred.
93
122
fn checked_add ( & self , other : Self :: V ) -> Option < Self > ;
94
123
@@ -232,6 +261,40 @@ mod tests {
232
261
assert ! ( a < b) ;
233
262
}
234
263
264
+ #[ test]
265
+ fn test_checked_align_up ( ) {
266
+ assert_eq ! (
267
+ MockAddress :: new( 0x128 ) . checked_align_up( 8 ) ,
268
+ Some ( MockAddress ( 0x128 ) )
269
+ ) ;
270
+ assert_eq ! (
271
+ MockAddress :: new( 0x128 ) . checked_align_up( 16 ) ,
272
+ Some ( MockAddress ( 0x130 ) )
273
+ ) ;
274
+ assert_eq ! (
275
+ MockAddress :: new( std:: u64 :: MAX - 0x3fff ) . checked_align_up( 0x10000 ) ,
276
+ None
277
+ ) ;
278
+ }
279
+
280
+ #[ test]
281
+ #[ should_panic]
282
+ fn test_checked_align_up_invalid ( ) {
283
+ let _ = MockAddress :: new ( 0x128 ) . checked_align_up ( 12 ) ;
284
+ }
285
+
286
+ #[ test]
287
+ fn test_unchecked_align_up ( ) {
288
+ assert_eq ! (
289
+ MockAddress :: new( 0x128 ) . unchecked_align_up( 8 ) ,
290
+ MockAddress ( 0x128 )
291
+ ) ;
292
+ assert_eq ! (
293
+ MockAddress :: new( 0x128 ) . unchecked_align_up( 16 ) ,
294
+ MockAddress ( 0x130 )
295
+ ) ;
296
+ }
297
+
235
298
#[ test]
236
299
fn test_mask ( ) {
237
300
let a = MockAddress ( 0x5050 ) ;
0 commit comments