1use std::cmp;
6use std::ops::RangeInclusive;
7
8use serde::Deserialize;
9use serde::Serialize;
10
11#[derive(Copy, Clone, Deserialize, Serialize)]
17#[serde(deny_unknown_fields)]
18pub struct AddressRange {
19 pub start: u64,
20 pub end: u64,
21}
22
23impl AddressRange {
24 pub const fn from_start_and_end(start: u64, end: u64) -> Self {
26 AddressRange { start, end }
27 }
28
29 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 pub const fn empty() -> Self {
44 AddressRange { start: 1, end: 0 }
45 }
46
47 pub fn is_empty(&self) -> bool {
49 self.end < self.start
50 }
51
52 pub fn contains(&self, address: u64) -> bool {
54 address >= self.start && address <= self.end
55 }
56
57 pub fn contains_range(&self, other: AddressRange) -> bool {
61 !other.is_empty() && other.start >= self.start && other.end <= self.end
62 }
63
64 pub fn overlaps(&self, other: AddressRange) -> bool {
66 !self.intersect(other).is_empty()
67 }
68
69 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 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 let end = cmp::max(self.start, other.start) - 1;
94
95 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 let start = cmp::min(self.end, other.end) + 1;
107
108 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 pub fn split_at(&self, split_start: u64) -> (AddressRange, AddressRange) {
124 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 pub fn len(&self) -> Option<u64> {
147 if self.is_empty() {
149 Some(0)
150 } else {
151 (self.end - self.start).checked_add(1)
152 }
153 }
154
155 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
164impl std::fmt::Display for AddressRange {
165 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
166 self.log(f)
167 }
168}
169
170impl std::fmt::Debug for AddressRange {
171 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
172 self.log(f)
173 }
174}
175
176impl From<RangeInclusive<u64>> for AddressRange {
177 fn from(range: RangeInclusive<u64>) -> AddressRange {
178 AddressRange {
179 start: *range.start(),
180 end: *range.end(),
181 }
182 }
183}
184
185impl From<AddressRange> for RangeInclusive<u64> {
186 fn from(address_range: AddressRange) -> RangeInclusive<u64> {
187 address_range.start..=address_range.end
188 }
189}
190
191impl cmp::Ord for AddressRange {
194 fn cmp(&self, other: &Self) -> cmp::Ordering {
195 match (self.is_empty(), other.is_empty()) {
196 (true, true) => cmp::Ordering::Equal,
198 (true, false) => cmp::Ordering::Less,
200 (false, true) => cmp::Ordering::Greater,
202 (false, false) => self
204 .start
205 .cmp(&other.start)
206 .then_with(|| self.end.cmp(&other.end)),
207 }
208 }
209}
210
211impl cmp::PartialOrd for AddressRange {
212 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
213 Some(cmp::Ord::cmp(self, other))
214 }
215}
216
217impl cmp::PartialEq for AddressRange {
218 fn eq(&self, other: &Self) -> bool {
219 cmp::Ord::cmp(self, other) == cmp::Ordering::Equal
220 }
221}
222
223impl cmp::Eq for AddressRange {}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
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]
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 assert!(!AddressRange { start: 5, end: 0 }.contains(3));
261 }
262
263 #[test]
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 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 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 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 assert!(
297 !AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 3, end: 1 })
298 );
299 }
300
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 assert_eq!(a.intersect(b), answer);
317 assert_eq!(b.intersect(a), answer);
318 }
319
320 #[test]
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
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]
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]
353 fn non_overlapping_ranges() {
354 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 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 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 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 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 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 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 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]
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]
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 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 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 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 assert!(AddressRange::from_start_and_size(u64::MAX, 0)
505 .unwrap()
506 .is_empty());
507 }
508
509 #[test]
510 fn from_start_and_size_invalid() {
511 assert_eq!(AddressRange::from_start_and_size(2, u64::MAX), None);
513
514 assert_eq!(AddressRange::from_start_and_size(0x100, u64::MAX), None);
516
517 assert_eq!(
519 AddressRange::from_start_and_size(0x100, u64::MAX - 0xfe),
520 None
521 );
522 }
523
524 #[test]
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]
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]
580 fn cmp_empty() {
581 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}