1 // Copyright 2022 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::cmp; 6 use std::ops::RangeInclusive; 7 8 use serde::Deserialize; 9 use serde::Serialize; 10 11 /// Represents a range of addresses from `start` to `end`, inclusive. 12 /// 13 /// Why not use the standard `RangeInclusive`? `RangeInclusive` is not `Copy`, because it tries to 14 /// be an iterator as well as a range (which also means it is larger than necessary). Additionally, 15 /// we would also like to implement some convenience functions for our own type. 16 #[derive(Copy, Clone, Deserialize, Serialize)] 17 #[serde(deny_unknown_fields)] 18 pub struct AddressRange { 19 pub start: u64, 20 pub end: u64, 21 } 22 23 impl AddressRange { 24 /// Creates a new `AddressRange` from `start` and `end` (inclusive) addresses. from_start_and_end(start: u64, end: u64) -> Self25 pub const fn from_start_and_end(start: u64, end: u64) -> Self { 26 AddressRange { start, end } 27 } 28 29 /// Creates a new `AddressRange` from `start` extending `size` bytes. 30 /// 31 /// Returns `None` if the generated range is not representable as an `AddressRange`. from_start_and_size(start: u64, size: u64) -> Option<Self>32 pub const fn from_start_and_size(start: u64, size: u64) -> Option<Self> { 33 if size == 0 { 34 Some(AddressRange::empty()) 35 } else if let Some(end) = start.checked_add(size - 1) { 36 Some(AddressRange { start, end }) 37 } else { 38 None 39 } 40 } 41 42 /// Returns an empty range. empty() -> Self43 pub const fn empty() -> Self { 44 AddressRange { start: 1, end: 0 } 45 } 46 47 /// Returns `true` if this range is empty (contains no addresses). is_empty(&self) -> bool48 pub fn is_empty(&self) -> bool { 49 self.end < self.start 50 } 51 52 /// Returns `true` if this range contains `address`. contains(&self, address: u64) -> bool53 pub fn contains(&self, address: u64) -> bool { 54 address >= self.start && address <= self.end 55 } 56 57 /// Returns `true` if `other` is fully contained within this range. 58 /// 59 /// Empty ranges are considered to be not contained by any range. contains_range(&self, other: AddressRange) -> bool60 pub fn contains_range(&self, other: AddressRange) -> bool { 61 !other.is_empty() && other.start >= self.start && other.end <= self.end 62 } 63 64 /// Returns `true` if the two ranges have any addresses in common. overlaps(&self, other: AddressRange) -> bool65 pub fn overlaps(&self, other: AddressRange) -> bool { 66 !self.intersect(other).is_empty() 67 } 68 69 /// Find the intersection (overlapping region) of two ranges. 70 /// 71 /// If there is no intersection, the resulting `AddressRange` will be empty. intersect(&self, other: AddressRange) -> AddressRange72 pub fn intersect(&self, other: AddressRange) -> AddressRange { 73 let start = cmp::max(self.start, other.start); 74 let end = cmp::min(self.end, other.end); 75 AddressRange { start, end } 76 } 77 78 /// Returns the ranges of addresses contained in `self` but not in `other`. 79 /// 80 /// The first returned range will contain the addresses in `self` that are less than the start 81 /// of `other`, which will be empty if the starts of the ranges coincide. 82 /// 83 /// The second returned range will contain the addresses in `self` that are greater than the end 84 /// of `other`, which will be empty if the ends of the ranges coincide. non_overlapping_ranges(&self, other: AddressRange) -> (AddressRange, AddressRange)85 pub fn non_overlapping_ranges(&self, other: AddressRange) -> (AddressRange, AddressRange) { 86 let before = if self.start >= other.start { 87 Self::empty() 88 } else { 89 let start = cmp::min(self.start, other.start); 90 91 // We know that self.start != other.start, so the maximum of the two cannot be 0, so it 92 // is safe to subtract 1. 93 let end = cmp::max(self.start, other.start) - 1; 94 95 // For non-overlapping ranges, don't allow end to extend past self.end. 96 let end = cmp::min(end, self.end); 97 98 AddressRange { start, end } 99 }; 100 101 let after = if self.end <= other.end { 102 Self::empty() 103 } else { 104 // We know that self.end != other.end, so the minimum of the two cannot be `u64::MAX`, 105 // so it is safe to add 1. 106 let start = cmp::min(self.end, other.end) + 1; 107 108 // For non-overlapping ranges, don't allow start to extend before self.start. 109 let start = cmp::max(start, self.start); 110 111 let end = cmp::max(self.end, other.end); 112 113 AddressRange { start, end } 114 }; 115 116 (before, after) 117 } 118 119 /// Returns the two subsets of this range split at the `split_start` address. 120 /// 121 /// If `split_start` is not contained in this range, returns the original range and an empty 122 /// range. split_at(&self, split_start: u64) -> (AddressRange, AddressRange)123 pub fn split_at(&self, split_start: u64) -> (AddressRange, AddressRange) { 124 // split_start == self.start is handled as a special case so we know that split_start - 1 is 125 // safe below (and so the empty range is always returned second if present). 126 if split_start <= self.start || split_start > self.end { 127 (*self, Self::empty()) 128 } else { 129 ( 130 AddressRange { 131 start: self.start, 132 end: split_start - 1, 133 }, 134 AddressRange { 135 start: split_start, 136 end: self.end, 137 }, 138 ) 139 } 140 } 141 142 /// Computes the length of an `AddressRange`. 143 /// 144 /// Returns `None` if the length cannot be represented in `u64` (if the range is 145 /// `0..=u64::MAX`). len(&self) -> Option<u64>146 pub fn len(&self) -> Option<u64> { 147 // Treat any range we consider "empty" (end < start) as having 0 length. 148 if self.is_empty() { 149 Some(0) 150 } else { 151 (self.end - self.start).checked_add(1) 152 } 153 } 154 log(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result155 fn log(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 156 if self.is_empty() { 157 f.write_str("empty") 158 } else { 159 f.write_fmt(format_args!("{:#x}..={:#x}", self.start, self.end)) 160 } 161 } 162 } 163 164 impl std::fmt::Display for AddressRange { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result165 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 166 self.log(f) 167 } 168 } 169 170 impl std::fmt::Debug for AddressRange { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result171 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 172 self.log(f) 173 } 174 } 175 176 impl From<RangeInclusive<u64>> for AddressRange { from(range: RangeInclusive<u64>) -> AddressRange177 fn from(range: RangeInclusive<u64>) -> AddressRange { 178 AddressRange { 179 start: *range.start(), 180 end: *range.end(), 181 } 182 } 183 } 184 185 impl From<AddressRange> for RangeInclusive<u64> { from(address_range: AddressRange) -> RangeInclusive<u64>186 fn from(address_range: AddressRange) -> RangeInclusive<u64> { 187 address_range.start..=address_range.end 188 } 189 } 190 191 /// Custom comparison function that provides a total order over all possible `AddressRange` values 192 /// and considers all empty ranges to be equal. 193 impl cmp::Ord for AddressRange { cmp(&self, other: &Self) -> cmp::Ordering194 fn cmp(&self, other: &Self) -> cmp::Ordering { 195 match (self.is_empty(), other.is_empty()) { 196 // Any empty range is equal to any other empty range. 197 (true, true) => cmp::Ordering::Equal, 198 // An empty range is less than any non-empty range. 199 (true, false) => cmp::Ordering::Less, 200 // Any non-empty range is greater than an empty range. 201 (false, true) => cmp::Ordering::Greater, 202 // Two non-empty ranges are ordered based on `start`, and if those are equal, `end`. 203 (false, false) => self 204 .start 205 .cmp(&other.start) 206 .then_with(|| self.end.cmp(&other.end)), 207 } 208 } 209 } 210 211 impl cmp::PartialOrd for AddressRange { partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>212 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { 213 Some(cmp::Ord::cmp(self, other)) 214 } 215 } 216 217 impl cmp::PartialEq for AddressRange { eq(&self, other: &Self) -> bool218 fn eq(&self, other: &Self) -> bool { 219 cmp::Ord::cmp(self, other) == cmp::Ordering::Equal 220 } 221 } 222 223 // The `PartialEq` implementation is reflexive, symmetric, and transitive. 224 impl cmp::Eq for AddressRange {} 225 226 #[cfg(test)] 227 mod tests { 228 use super::*; 229 230 #[test] is_empty()231 fn is_empty() { 232 assert!(AddressRange { start: 1, end: 0 }.is_empty()); 233 assert!(AddressRange { 234 start: u64::MAX, 235 end: 0 236 } 237 .is_empty()); 238 assert!(AddressRange { 239 start: u64::MAX, 240 end: u64::MAX - 1 241 } 242 .is_empty()); 243 assert!(AddressRange::empty().is_empty()); 244 245 assert!(!AddressRange { start: 0, end: 1 }.is_empty()); 246 assert!(!AddressRange { start: 1, end: 1 }.is_empty()); 247 } 248 249 #[test] contains()250 fn contains() { 251 assert!(AddressRange { start: 0, end: 5 }.contains(3)); 252 assert!(AddressRange { start: 0, end: 0 }.contains(0)); 253 assert!(AddressRange { 254 start: 0, 255 end: u64::MAX 256 } 257 .contains(u64::MAX)); 258 259 // Empty ranges do not contain any addresses 260 assert!(!AddressRange { start: 5, end: 0 }.contains(3)); 261 } 262 263 #[test] contains_range()264 fn contains_range() { 265 assert!(AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 0, end: 5 })); 266 assert!(AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 1, end: 3 })); 267 268 // Partly overlapping ranges 269 assert!( 270 !AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 3, end: 9 }) 271 ); 272 assert!( 273 !AddressRange { start: 3, end: 9 }.contains_range(AddressRange { start: 0, end: 5 }) 274 ); 275 276 // Completely discontiguous ranges 277 assert!( 278 !AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 6, end: 9 }) 279 ); 280 assert!( 281 !AddressRange { start: 6, end: 9 }.contains_range(AddressRange { start: 0, end: 5 }) 282 ); 283 284 // Empty ranges do not contain anything 285 assert!( 286 !AddressRange { start: 5, end: 0 }.contains_range(AddressRange { start: 0, end: 5 }) 287 ); 288 assert!( 289 !AddressRange { start: 5, end: 0 }.contains_range(AddressRange { start: 5, end: 0 }) 290 ); 291 assert!( 292 !AddressRange { start: 5, end: 0 }.contains_range(AddressRange { start: 1, end: 3 }) 293 ); 294 295 // An empty range is not contained by anything 296 assert!( 297 !AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 3, end: 1 }) 298 ); 299 } 300 test_intersect(a: (u64, u64), b: (u64, u64), answer: (u64, u64))301 fn test_intersect(a: (u64, u64), b: (u64, u64), answer: (u64, u64)) { 302 let a = AddressRange { 303 start: a.0, 304 end: a.1, 305 }; 306 let b = AddressRange { 307 start: b.0, 308 end: b.1, 309 }; 310 let answer = AddressRange { 311 start: answer.0, 312 end: answer.1, 313 }; 314 315 // intersect() should be commutative, so try it both ways 316 assert_eq!(a.intersect(b), answer); 317 assert_eq!(b.intersect(a), answer); 318 } 319 320 #[test] intersect()321 fn intersect() { 322 test_intersect((0, 5), (0, 5), (0, 5)); 323 test_intersect((0, 5), (0, 3), (0, 3)); 324 test_intersect((0, 5), (3, 5), (3, 5)); 325 test_intersect((0, 5), (5, 5), (5, 5)); 326 test_intersect((0, 5), (4, 9), (4, 5)); 327 test_intersect((0, u64::MAX), (3, 5), (3, 5)); 328 test_intersect((10, 20), (5, 15), (10, 15)); 329 } 330 test_intersect_empty(a: (u64, u64), b: (u64, u64))331 fn test_intersect_empty(a: (u64, u64), b: (u64, u64)) { 332 let a = AddressRange { 333 start: a.0, 334 end: a.1, 335 }; 336 let b = AddressRange { 337 start: b.0, 338 end: b.1, 339 }; 340 assert!(a.intersect(b).is_empty()); 341 assert!(b.intersect(a).is_empty()); 342 } 343 344 #[test] intersect_empty()345 fn intersect_empty() { 346 test_intersect_empty((0, 5), (10, 20)); 347 test_intersect_empty((5, 0), (3, 4)); 348 test_intersect_empty((10, 20), (20, 10)); 349 test_intersect_empty((10, 20), (30, 40)); 350 } 351 352 #[test] non_overlapping_ranges()353 fn non_overlapping_ranges() { 354 // Two identical ranges have no non-overlapping ranges. 355 assert_eq!( 356 AddressRange { start: 0, end: 100 } 357 .non_overlapping_ranges(AddressRange { start: 0, end: 100 }), 358 (AddressRange::empty(), AddressRange::empty()) 359 ); 360 361 // Non-overlapping regions on both sides. 362 assert_eq!( 363 AddressRange { start: 0, end: 100 } 364 .non_overlapping_ranges(AddressRange { start: 10, end: 20 }), 365 ( 366 AddressRange { start: 0, end: 9 }, 367 AddressRange { 368 start: 21, 369 end: 100 370 } 371 ) 372 ); 373 374 // Non-overlapping region on the left but not on the right. 375 assert_eq!( 376 AddressRange { start: 0, end: 100 }.non_overlapping_ranges(AddressRange { 377 start: 10, 378 end: 100 379 }), 380 (AddressRange { start: 0, end: 9 }, AddressRange::empty()) 381 ); 382 383 // Non-overlapping region on the right but not on the left. 384 assert_eq!( 385 AddressRange { start: 0, end: 100 } 386 .non_overlapping_ranges(AddressRange { start: 0, end: 50 }), 387 ( 388 AddressRange::empty(), 389 AddressRange { 390 start: 51, 391 end: 100 392 } 393 ) 394 ); 395 396 // Other range not contained within this range and greater than this range. 397 assert_eq!( 398 AddressRange { start: 0, end: 100 }.non_overlapping_ranges(AddressRange { 399 start: 200, 400 end: 300 401 }), 402 (AddressRange { start: 0, end: 100 }, AddressRange::empty()) 403 ); 404 405 // Other range not contained within this range and less than this range. 406 assert_eq!( 407 AddressRange { 408 start: 200, 409 end: 300 410 } 411 .non_overlapping_ranges(AddressRange { start: 0, end: 100 }), 412 ( 413 AddressRange::empty(), 414 AddressRange { 415 start: 200, 416 end: 300 417 } 418 ) 419 ); 420 421 // Partially overlapping region with non-overlapping region on the left. 422 assert_eq!( 423 AddressRange { start: 10, end: 20 } 424 .non_overlapping_ranges(AddressRange { start: 15, end: 35 }), 425 (AddressRange { start: 10, end: 14 }, AddressRange::empty()) 426 ); 427 428 // Partially overlapping region with non-overlapping region on the right. 429 assert_eq!( 430 AddressRange { start: 10, end: 20 } 431 .non_overlapping_ranges(AddressRange { start: 5, end: 15 }), 432 (AddressRange::empty(), AddressRange { start: 16, end: 20 }) 433 ); 434 } 435 436 #[test] split_at()437 fn split_at() { 438 assert_eq!( 439 AddressRange { start: 10, end: 20 }.split_at(15), 440 ( 441 AddressRange { start: 10, end: 14 }, 442 AddressRange { start: 15, end: 20 } 443 ) 444 ); 445 assert_eq!( 446 AddressRange { start: 10, end: 20 }.split_at(20), 447 ( 448 AddressRange { start: 10, end: 19 }, 449 AddressRange { start: 20, end: 20 } 450 ) 451 ); 452 assert_eq!( 453 AddressRange { start: 10, end: 20 }.split_at(10), 454 (AddressRange { start: 10, end: 20 }, AddressRange::empty()) 455 ); 456 assert_eq!( 457 AddressRange { start: 10, end: 20 }.split_at(21), 458 (AddressRange { start: 10, end: 20 }, AddressRange::empty()) 459 ); 460 assert_eq!( 461 AddressRange { start: 10, end: 20 }.split_at(9), 462 (AddressRange { start: 10, end: 20 }, AddressRange::empty()) 463 ); 464 } 465 466 #[test] from_start_and_size_valid()467 fn from_start_and_size_valid() { 468 assert_eq!( 469 AddressRange::from_start_and_size(0x100, 0x20), 470 Some(AddressRange { 471 start: 0x100, 472 end: 0x11f 473 }) 474 ); 475 476 // Max-sized range based at 0 477 assert_eq!( 478 AddressRange::from_start_and_size(0, u64::MAX), 479 Some(AddressRange { 480 start: 0, 481 end: u64::MAX - 1 482 }) 483 ); 484 485 // Max-sized range based at 1 486 assert_eq!( 487 AddressRange::from_start_and_size(1, u64::MAX), 488 Some(AddressRange { 489 start: 1, 490 end: u64::MAX 491 }) 492 ); 493 494 // One-byte range based at u64::MAX 495 assert_eq!( 496 AddressRange::from_start_and_size(u64::MAX, 1), 497 Some(AddressRange { 498 start: u64::MAX, 499 end: u64::MAX 500 }) 501 ); 502 503 // Empty range (size = 0) with arbitrary start 504 assert!(AddressRange::from_start_and_size(u64::MAX, 0) 505 .unwrap() 506 .is_empty()); 507 } 508 509 #[test] from_start_and_size_invalid()510 fn from_start_and_size_invalid() { 511 // 2 + u64::MAX - 1 overflows 512 assert_eq!(AddressRange::from_start_and_size(2, u64::MAX), None); 513 514 // 0x100 + u64::MAX - 1 overflows 515 assert_eq!(AddressRange::from_start_and_size(0x100, u64::MAX), None); 516 517 // 0x100 + (u64::MAX - 0xfe) - 1 overflows 518 assert_eq!( 519 AddressRange::from_start_and_size(0x100, u64::MAX - 0xfe), 520 None 521 ); 522 } 523 524 #[test] display()525 fn display() { 526 assert_eq!( 527 format!( 528 "{}", 529 AddressRange { 530 start: 0x1234, 531 end: 0x5678 532 } 533 ), 534 "0x1234..=0x5678" 535 ); 536 assert_eq!(format!("{}", AddressRange::empty()), "empty"); 537 } 538 539 #[test] cmp()540 fn cmp() { 541 assert!( 542 AddressRange { 543 start: 0x1000, 544 end: 0x2000 545 } < AddressRange { 546 start: 0x3000, 547 end: 0x4000 548 } 549 ); 550 assert!( 551 AddressRange { 552 start: 0x1000, 553 end: 0x2000 554 } == AddressRange { 555 start: 0x1000, 556 end: 0x2000 557 } 558 ); 559 assert!( 560 AddressRange { 561 start: 0x3000, 562 end: 0x4000 563 } > AddressRange { 564 start: 0x1000, 565 end: 0x2000 566 } 567 ); 568 assert!( 569 AddressRange { 570 start: 0x1000, 571 end: 0x2000 572 } < AddressRange { 573 start: 0x1000, 574 end: 0x3000 575 } 576 ); 577 } 578 579 #[test] cmp_empty()580 fn cmp_empty() { 581 // Empty ranges are less than any non-empty range and equal to any other empty range. 582 assert!( 583 AddressRange { 584 start: 0x1000, 585 end: 0x2000 586 } > AddressRange::empty() 587 ); 588 assert!( 589 AddressRange::empty() 590 < AddressRange { 591 start: 0x1000, 592 end: 0x2000 593 } 594 ); 595 assert!(AddressRange { start: 5, end: 3 } == AddressRange { start: 10, end: 1 }); 596 } 597 } 598