|
1 | 1 | use std::{ |
2 | | - cmp, |
3 | | - cmp::Ordering, |
| 2 | + cmp::{Ordering, max}, |
4 | 3 | collections::{BTreeMap, btree_map}, |
5 | 4 | ops::{ |
6 | 5 | Bound::{Excluded, Included}, |
@@ -69,14 +68,17 @@ impl RangeSet { |
69 | 68 | x.start = start; |
70 | 69 | } |
71 | 70 | } |
72 | | - while let Some((next_start, next_end)) = self.succ(x.start) { |
73 | | - if next_start > x.end { |
74 | | - break; |
75 | | - } |
76 | | - // Overlaps with successor |
77 | | - self.0.remove(&next_start); |
78 | | - x.end = cmp::max(next_end, x.end); |
| 71 | + |
| 72 | + let existing_end = self |
| 73 | + .0 |
| 74 | + .extract_if((Excluded(x.start), Included(x.end)), |_, _| true) |
| 75 | + .last() |
| 76 | + .map(|(_start, end)| end); |
| 77 | + |
| 78 | + if let Some(existing_end) = existing_end { |
| 79 | + x.end = max(x.end, existing_end); |
79 | 80 | } |
| 81 | + |
80 | 82 | self.0.insert(x.start, x.end); |
81 | 83 | true |
82 | 84 | } |
@@ -378,4 +380,61 @@ mod tests { |
378 | 380 | assert_eq!(set.len(), 1); |
379 | 381 | assert_eq!(set.peek_min().unwrap(), 0..4); |
380 | 382 | } |
| 383 | + |
| 384 | + #[test] |
| 385 | + fn insert_merges_abutting_range() { |
| 386 | + // given |
| 387 | + let mut set = RangeSet::new(); |
| 388 | + set.insert(10..20); |
| 389 | + |
| 390 | + // when |
| 391 | + set.insert(5..10); |
| 392 | + |
| 393 | + // then |
| 394 | + let expected_inner = BTreeMap::from_iter([(5, 20)]); |
| 395 | + assert_eq!(set.0, expected_inner, "Ranges should have merged."); |
| 396 | + } |
| 397 | + |
| 398 | + #[test] |
| 399 | + fn insert_merges_existing_crossing_range() { |
| 400 | + // given |
| 401 | + let mut set = RangeSet::new(); |
| 402 | + set.insert(10..20); |
| 403 | + |
| 404 | + // when |
| 405 | + set.insert(12..25); |
| 406 | + |
| 407 | + // then |
| 408 | + let expected_inner = BTreeMap::from_iter([(10, 25)]); |
| 409 | + assert_eq!(set.0, expected_inner, "Ranges should have merged."); |
| 410 | + } |
| 411 | + |
| 412 | + #[test] |
| 413 | + fn insert_ignored_if_wholly_contained() { |
| 414 | + // given |
| 415 | + let mut set = RangeSet::new(); |
| 416 | + set.insert(10..20); |
| 417 | + |
| 418 | + // when |
| 419 | + set.insert(12..15); |
| 420 | + |
| 421 | + // then |
| 422 | + let expected_inner = BTreeMap::from_iter([(10, 20)]); |
| 423 | + assert_eq!(set.0, expected_inner, "Ranges should have merged."); |
| 424 | + } |
| 425 | + |
| 426 | + #[test] |
| 427 | + fn insert_bridges_disjoint_ranges() { |
| 428 | + // given |
| 429 | + let mut set = RangeSet::new(); |
| 430 | + set.insert(0..10); |
| 431 | + set.insert(20..30); |
| 432 | + |
| 433 | + // when |
| 434 | + set.insert(10..20); |
| 435 | + |
| 436 | + // then |
| 437 | + let expected_inner = BTreeMap::from_iter([(0, 30)]); |
| 438 | + assert_eq!(set.0, expected_inner, "Ranges should have merged."); |
| 439 | + } |
381 | 440 | } |
0 commit comments