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) {
88 if other.is_empty() {
89 return (*self, Self::empty());
90 }
91
92 let before = if self.start >= other.start {
93 Self::empty()
94 } else {
95 let start = cmp::min(self.start, other.start);
96
97 let end = cmp::max(self.start, other.start) - 1;
100
101 let end = cmp::min(end, self.end);
103
104 AddressRange { start, end }
105 };
106
107 let after = if self.end <= other.end {
108 Self::empty()
109 } else {
110 let start = cmp::min(self.end, other.end) + 1;
113
114 let start = cmp::max(start, self.start);
116
117 let end = cmp::max(self.end, other.end);
118
119 AddressRange { start, end }
120 };
121
122 (before, after)
123 }
124
125 pub fn split_at(&self, split_start: u64) -> (AddressRange, AddressRange) {
130 if split_start <= self.start || split_start > self.end {
133 (*self, Self::empty())
134 } else {
135 (
136 AddressRange {
137 start: self.start,
138 end: split_start - 1,
139 },
140 AddressRange {
141 start: split_start,
142 end: self.end,
143 },
144 )
145 }
146 }
147
148 pub fn len(&self) -> Option<u64> {
153 if self.is_empty() {
155 Some(0)
156 } else {
157 (self.end - self.start).checked_add(1)
158 }
159 }
160
161 fn log(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
162 if self.is_empty() {
163 f.write_str("empty")
164 } else {
165 f.write_fmt(format_args!("{:#x}..={:#x}", self.start, self.end))
166 }
167 }
168}
169
170impl std::fmt::Display for AddressRange {
171 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
172 self.log(f)
173 }
174}
175
176impl std::fmt::Debug for AddressRange {
177 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
178 self.log(f)
179 }
180}
181
182impl From<RangeInclusive<u64>> for AddressRange {
183 fn from(range: RangeInclusive<u64>) -> AddressRange {
184 AddressRange {
185 start: *range.start(),
186 end: *range.end(),
187 }
188 }
189}
190
191impl From<AddressRange> for RangeInclusive<u64> {
192 fn from(address_range: AddressRange) -> RangeInclusive<u64> {
193 address_range.start..=address_range.end
194 }
195}
196
197impl cmp::Ord for AddressRange {
200 fn cmp(&self, other: &Self) -> cmp::Ordering {
201 match (self.is_empty(), other.is_empty()) {
202 (true, true) => cmp::Ordering::Equal,
204 (true, false) => cmp::Ordering::Less,
206 (false, true) => cmp::Ordering::Greater,
208 (false, false) => self
210 .start
211 .cmp(&other.start)
212 .then_with(|| self.end.cmp(&other.end)),
213 }
214 }
215}
216
217impl cmp::PartialOrd for AddressRange {
218 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
219 Some(cmp::Ord::cmp(self, other))
220 }
221}
222
223impl cmp::PartialEq for AddressRange {
224 fn eq(&self, other: &Self) -> bool {
225 cmp::Ord::cmp(self, other) == cmp::Ordering::Equal
226 }
227}
228
229impl cmp::Eq for AddressRange {}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn is_empty() {
238 assert!(AddressRange { start: 1, end: 0 }.is_empty());
239 assert!(AddressRange {
240 start: u64::MAX,
241 end: 0
242 }
243 .is_empty());
244 assert!(AddressRange {
245 start: u64::MAX,
246 end: u64::MAX - 1
247 }
248 .is_empty());
249 assert!(AddressRange::empty().is_empty());
250
251 assert!(!AddressRange { start: 0, end: 1 }.is_empty());
252 assert!(!AddressRange { start: 1, end: 1 }.is_empty());
253 }
254
255 #[test]
256 fn contains() {
257 assert!(AddressRange { start: 0, end: 5 }.contains(3));
258 assert!(AddressRange { start: 0, end: 0 }.contains(0));
259 assert!(AddressRange {
260 start: 0,
261 end: u64::MAX
262 }
263 .contains(u64::MAX));
264
265 assert!(!AddressRange { start: 5, end: 0 }.contains(3));
267 }
268
269 #[test]
270 fn contains_range() {
271 assert!(AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 0, end: 5 }));
272 assert!(AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 1, end: 3 }));
273
274 assert!(
276 !AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 3, end: 9 })
277 );
278 assert!(
279 !AddressRange { start: 3, end: 9 }.contains_range(AddressRange { start: 0, end: 5 })
280 );
281
282 assert!(
284 !AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 6, end: 9 })
285 );
286 assert!(
287 !AddressRange { start: 6, end: 9 }.contains_range(AddressRange { start: 0, end: 5 })
288 );
289
290 assert!(
292 !AddressRange { start: 5, end: 0 }.contains_range(AddressRange { start: 0, end: 5 })
293 );
294 assert!(
295 !AddressRange { start: 5, end: 0 }.contains_range(AddressRange { start: 5, end: 0 })
296 );
297 assert!(
298 !AddressRange { start: 5, end: 0 }.contains_range(AddressRange { start: 1, end: 3 })
299 );
300
301 assert!(
303 !AddressRange { start: 0, end: 5 }.contains_range(AddressRange { start: 3, end: 1 })
304 );
305 }
306
307 fn test_intersect(a: (u64, u64), b: (u64, u64), answer: (u64, u64)) {
308 let a = AddressRange {
309 start: a.0,
310 end: a.1,
311 };
312 let b = AddressRange {
313 start: b.0,
314 end: b.1,
315 };
316 let answer = AddressRange {
317 start: answer.0,
318 end: answer.1,
319 };
320
321 assert_eq!(a.intersect(b), answer);
323 assert_eq!(b.intersect(a), answer);
324 }
325
326 #[test]
327 fn intersect() {
328 test_intersect((0, 5), (0, 5), (0, 5));
329 test_intersect((0, 5), (0, 3), (0, 3));
330 test_intersect((0, 5), (3, 5), (3, 5));
331 test_intersect((0, 5), (5, 5), (5, 5));
332 test_intersect((0, 5), (4, 9), (4, 5));
333 test_intersect((0, u64::MAX), (3, 5), (3, 5));
334 test_intersect((10, 20), (5, 15), (10, 15));
335 }
336
337 fn test_intersect_empty(a: (u64, u64), b: (u64, u64)) {
338 let a = AddressRange {
339 start: a.0,
340 end: a.1,
341 };
342 let b = AddressRange {
343 start: b.0,
344 end: b.1,
345 };
346 assert!(a.intersect(b).is_empty());
347 assert!(b.intersect(a).is_empty());
348 }
349
350 #[test]
351 fn intersect_empty() {
352 test_intersect_empty((0, 5), (10, 20));
353 test_intersect_empty((5, 0), (3, 4));
354 test_intersect_empty((10, 20), (20, 10));
355 test_intersect_empty((10, 20), (30, 40));
356 }
357
358 #[test]
359 fn non_overlapping_ranges() {
360 assert_eq!(
362 AddressRange { start: 0, end: 100 }
363 .non_overlapping_ranges(AddressRange { start: 0, end: 100 }),
364 (AddressRange::empty(), AddressRange::empty())
365 );
366
367 assert_eq!(
369 AddressRange { start: 0, end: 100 }
370 .non_overlapping_ranges(AddressRange { start: 10, end: 20 }),
371 (
372 AddressRange { start: 0, end: 9 },
373 AddressRange {
374 start: 21,
375 end: 100
376 }
377 )
378 );
379
380 assert_eq!(
382 AddressRange { start: 0, end: 100 }.non_overlapping_ranges(AddressRange {
383 start: 10,
384 end: 100
385 }),
386 (AddressRange { start: 0, end: 9 }, AddressRange::empty())
387 );
388
389 assert_eq!(
391 AddressRange { start: 0, end: 100 }
392 .non_overlapping_ranges(AddressRange { start: 0, end: 50 }),
393 (
394 AddressRange::empty(),
395 AddressRange {
396 start: 51,
397 end: 100
398 }
399 )
400 );
401
402 assert_eq!(
404 AddressRange { start: 0, end: 100 }.non_overlapping_ranges(AddressRange {
405 start: 200,
406 end: 300
407 }),
408 (AddressRange { start: 0, end: 100 }, AddressRange::empty())
409 );
410
411 assert_eq!(
413 AddressRange {
414 start: 200,
415 end: 300
416 }
417 .non_overlapping_ranges(AddressRange { start: 0, end: 100 }),
418 (
419 AddressRange::empty(),
420 AddressRange {
421 start: 200,
422 end: 300
423 }
424 )
425 );
426
427 assert_eq!(
429 AddressRange { start: 10, end: 20 }
430 .non_overlapping_ranges(AddressRange { start: 15, end: 35 }),
431 (AddressRange { start: 10, end: 14 }, AddressRange::empty())
432 );
433
434 assert_eq!(
436 AddressRange { start: 10, end: 20 }
437 .non_overlapping_ranges(AddressRange { start: 5, end: 15 }),
438 (AddressRange::empty(), AddressRange { start: 16, end: 20 })
439 );
440
441 assert_eq!(
443 AddressRange { start: 0, end: 9 }.non_overlapping_ranges(AddressRange::empty()),
444 (AddressRange { start: 0, end: 9 }, AddressRange::empty())
445 );
446 assert_eq!(
447 AddressRange { start: 0, end: 9 }
448 .non_overlapping_ranges(AddressRange { start: 7, end: 3 }),
449 (AddressRange { start: 0, end: 9 }, AddressRange::empty())
450 );
451 }
452
453 #[test]
454 fn split_at() {
455 assert_eq!(
456 AddressRange { start: 10, end: 20 }.split_at(15),
457 (
458 AddressRange { start: 10, end: 14 },
459 AddressRange { start: 15, end: 20 }
460 )
461 );
462 assert_eq!(
463 AddressRange { start: 10, end: 20 }.split_at(20),
464 (
465 AddressRange { start: 10, end: 19 },
466 AddressRange { start: 20, end: 20 }
467 )
468 );
469 assert_eq!(
470 AddressRange { start: 10, end: 20 }.split_at(10),
471 (AddressRange { start: 10, end: 20 }, AddressRange::empty())
472 );
473 assert_eq!(
474 AddressRange { start: 10, end: 20 }.split_at(21),
475 (AddressRange { start: 10, end: 20 }, AddressRange::empty())
476 );
477 assert_eq!(
478 AddressRange { start: 10, end: 20 }.split_at(9),
479 (AddressRange { start: 10, end: 20 }, AddressRange::empty())
480 );
481 }
482
483 #[test]
484 fn from_start_and_size_valid() {
485 assert_eq!(
486 AddressRange::from_start_and_size(0x100, 0x20),
487 Some(AddressRange {
488 start: 0x100,
489 end: 0x11f
490 })
491 );
492
493 assert_eq!(
495 AddressRange::from_start_and_size(0, u64::MAX),
496 Some(AddressRange {
497 start: 0,
498 end: u64::MAX - 1
499 })
500 );
501
502 assert_eq!(
504 AddressRange::from_start_and_size(1, u64::MAX),
505 Some(AddressRange {
506 start: 1,
507 end: u64::MAX
508 })
509 );
510
511 assert_eq!(
513 AddressRange::from_start_and_size(u64::MAX, 1),
514 Some(AddressRange {
515 start: u64::MAX,
516 end: u64::MAX
517 })
518 );
519
520 assert!(AddressRange::from_start_and_size(u64::MAX, 0)
522 .unwrap()
523 .is_empty());
524 }
525
526 #[test]
527 fn from_start_and_size_invalid() {
528 assert_eq!(AddressRange::from_start_and_size(2, u64::MAX), None);
530
531 assert_eq!(AddressRange::from_start_and_size(0x100, u64::MAX), None);
533
534 assert_eq!(
536 AddressRange::from_start_and_size(0x100, u64::MAX - 0xfe),
537 None
538 );
539 }
540
541 #[test]
542 fn display() {
543 assert_eq!(
544 format!(
545 "{}",
546 AddressRange {
547 start: 0x1234,
548 end: 0x5678
549 }
550 ),
551 "0x1234..=0x5678"
552 );
553 assert_eq!(format!("{}", AddressRange::empty()), "empty");
554 }
555
556 #[test]
557 fn cmp() {
558 assert!(
559 AddressRange {
560 start: 0x1000,
561 end: 0x2000
562 } < AddressRange {
563 start: 0x3000,
564 end: 0x4000
565 }
566 );
567 assert!(
568 AddressRange {
569 start: 0x1000,
570 end: 0x2000
571 } == AddressRange {
572 start: 0x1000,
573 end: 0x2000
574 }
575 );
576 assert!(
577 AddressRange {
578 start: 0x3000,
579 end: 0x4000
580 } > AddressRange {
581 start: 0x1000,
582 end: 0x2000
583 }
584 );
585 assert!(
586 AddressRange {
587 start: 0x1000,
588 end: 0x2000
589 } < AddressRange {
590 start: 0x1000,
591 end: 0x3000
592 }
593 );
594 }
595
596 #[test]
597 fn cmp_empty() {
598 assert!(
600 AddressRange {
601 start: 0x1000,
602 end: 0x2000
603 } > AddressRange::empty()
604 );
605 assert!(
606 AddressRange::empty()
607 < AddressRange {
608 start: 0x1000,
609 end: 0x2000
610 }
611 );
612 assert!(AddressRange { start: 5, end: 3 } == AddressRange { start: 10, end: 1 });
613 }
614}