-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcursor.rs
174 lines (153 loc) · 5.95 KB
/
cursor.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
use std::{
mem,
ops::{Bound, Range},
};
use crate::{Inner, RangeTree};
impl<K: Ord + Copy, V: Clone> RangeTree<K, V> {
pub fn get(&self, key: K) -> Option<(Range<K>, &V)> {
// Find the last segment that starts before or at the key.
let cursor = self.tree.upper_bound(Bound::Included(&key));
// Check if the segment includes the key.
let (&start, &Inner { end, ref value }) = cursor.key_value()?;
(key < end).then_some((start..end, value))
}
pub fn insert(&mut self, range: Range<K>, new_value: V) {
// Ignore empty ranges.
if range.is_empty() {
return;
}
// Iterate in reverse order: we want to process any entries that begin
// before the end of the range and that end after the start of the range.
let mut cursor = self.tree.upper_bound_mut(Bound::Excluded(&range.end));
while let Some((
&start,
&mut Inner {
ref mut end,
ref mut value,
},
)) = cursor.key_value_mut()
{
// This segment is entirely before the start of the range.
if *end <= range.start {
// We're done.
break;
}
// This segment is entirely within the range.
if start > range.start && *end <= range.end {
// Just remove it.
cursor.remove_current_and_move_back();
continue;
}
// This segment starts at the same position as the range.
if start == range.start {
// Replace the current segment with our new range.
let old_end = mem::replace(end, range.end);
let old_value = mem::replace(value, new_value);
// Create a suffix segment if the old segment extended past the
// end of the range.
if *end > range.end {
cursor.insert_after_unchecked(
range.end,
Inner {
end: old_end,
value: old_value,
},
);
}
// This must be the last segment, and we've already inserted the
// new range into the tree.
return;
}
// This segment starts before the range.
if start < range.start {
// Shrink the segment to only cover the part before the range.
let old_end = *end;
*end = range.start;
// Create a suffix segment if the old segment extended past the
// end of the range.
if old_end > range.end {
let value = value.clone();
cursor.insert_after_unchecked(
range.end,
Inner {
end: old_end,
value,
},
);
}
// This must be the last segment, exit the loop to insert the
// new range between the two parts of the old segment.
break;
}
// Last remaining case: this segment extends past the end of the
// range. Modify it so that it only covers the suffix.
*cursor.key_mut_unchecked().unwrap() = range.end;
cursor.move_prev();
}
// We've removed all intersecting segments, now insert our new value.
// At this point the cursor is pointing to the segment just below the
// new range.
cursor.insert_after_unchecked(
range.start,
Inner {
end: range.end,
value: new_value,
},
);
}
pub fn remove(&mut self, range: Range<K>) {
// Iterate in reverse order: we want to process any entries that begin
// before the end of the range and that end after the start of the range.
let mut cursor = self.tree.upper_bound_mut(Bound::Excluded(&range.end));
while let Some((
&start,
&mut Inner {
ref mut end,
ref value,
},
)) = cursor.key_value_mut()
{
// This segment is entirely before the start of the range.
if *end <= range.start {
// We're done.
break;
}
// This segment is entirely within the range.
if start > range.start && *end <= range.end {
// Just remove it.
cursor.remove_current_and_move_back();
continue;
}
// This segment starts before the range.
if start < range.start {
// Shrink the segment to only cover the part before the range.
let old_end = *end;
*end = range.start;
// Create a suffix segment if the old segment extended past the
// end of the range.
if old_end > range.end {
let value = value.clone();
cursor.insert_after_unchecked(
range.end,
Inner {
end: old_end,
value,
},
);
}
// This must be the last segment, exit the loop.
break;
}
// Last remaining case: this segment extends past the end of the
// range. Modify it so that it only covers the suffix.
*cursor.key_mut_unchecked().unwrap() = range.end;
// Optimization: avoid looking at the next entry if we know this is
// the last one.
if start <= range.start {
break;
} else {
cursor.move_prev();
}
}
}
}