1#![deny(missing_docs)]
6
7use std::ops::Range;
8
9#[derive(Debug)]
13pub struct PresentList {
14 list: Vec<bool>,
15 min_possible_idx: usize,
18}
19
20impl PresentList {
21 pub fn new(num_of_pages: usize) -> Self {
27 Self {
28 list: vec![false; num_of_pages],
29 min_possible_idx: num_of_pages,
30 }
31 }
32
33 pub fn get(&self, idx: usize) -> Option<&bool> {
39 self.list.get(idx)
40 }
41
42 pub fn mark_as_present(&mut self, idx_range: Range<usize>) -> bool {
48 let result = self.update(idx_range, true);
49 self.min_possible_idx = 0;
56 result
57 }
58
59 pub fn clear_range(&mut self, idx_range: Range<usize>) -> bool {
65 let result = self.update(idx_range.clone(), false);
66 if result
68 && idx_range.start <= self.min_possible_idx
69 && self.min_possible_idx < idx_range.end
70 {
71 self.min_possible_idx = idx_range.end;
72 }
73 result
74 }
75
76 fn update(&mut self, idx_range: Range<usize>, value: bool) -> bool {
77 if let Some(list) = self.list.get_mut(idx_range) {
78 for v in list {
79 *v = value;
80 }
81 true
82 } else {
83 false
84 }
85 }
86
87 pub fn first_data_range(&mut self, max_pages: usize) -> Option<Range<usize>> {
94 if let Some(idx_range) = self.find_data_range(self.min_possible_idx, max_pages) {
95 self.min_possible_idx = idx_range.start;
98 Some(idx_range)
99 } else {
100 self.min_possible_idx = self.list.len();
102 None
103 }
104 }
105
106 pub fn find_data_range(&self, head_idx: usize, max_pages: usize) -> Option<Range<usize>> {
115 let head_idx = head_idx + self.list[head_idx..].iter().position(|v| *v)?;
116 let tail_idx = std::cmp::min(self.list.len() - head_idx, max_pages) + head_idx;
117 let tail_idx = self.list[head_idx + 1..tail_idx]
118 .iter()
119 .position(|v| !*v)
120 .map_or(tail_idx, |offset| offset + head_idx + 1);
121 Some(head_idx..tail_idx)
122 }
123
124 pub fn all_present_pages(&self) -> usize {
126 self.list[self.min_possible_idx..]
127 .iter()
128 .map(|v| usize::from(*v))
129 .sum()
130 }
131}
132
133#[cfg(test)]
134mod tests {
135
136 use super::*;
137
138 #[test]
139 fn get_default() {
140 let list = PresentList::new(200);
141
142 assert_eq!(*list.get(0).unwrap(), false);
143 assert_eq!(*list.get(10).unwrap(), false);
144 }
145
146 #[test]
147 fn get_out_of_range() {
148 let list = PresentList::new(200);
149
150 assert!(list.get(200).is_none());
151 }
152
153 #[test]
154 fn mark_as_present() {
155 let mut list = PresentList::new(200);
156
157 assert!(list.mark_as_present(10..12));
158 assert_eq!(*list.get(9).unwrap(), false);
159 assert_eq!(*list.get(10).unwrap(), true);
160 assert_eq!(*list.get(11).unwrap(), true);
161 assert_eq!(*list.get(12).unwrap(), false);
162 }
163
164 #[test]
165 fn mark_as_present_duplicated() {
166 let mut list = PresentList::new(200);
167
168 assert!(list.mark_as_present(10..12));
169 assert!(list.mark_as_present(11..13));
170 assert_eq!(*list.get(9).unwrap(), false);
171 assert_eq!(*list.get(10).unwrap(), true);
172 assert_eq!(*list.get(11).unwrap(), true);
173 assert_eq!(*list.get(12).unwrap(), true);
174 assert_eq!(*list.get(13).unwrap(), false);
175 }
176
177 #[test]
178 fn mark_as_present_out_of_range() {
179 let mut list = PresentList::new(200);
180
181 assert!(!list.mark_as_present(10..201));
182 assert_eq!(*list.get(10).unwrap(), false);
183 }
184
185 #[test]
186 fn clear_range() {
187 let mut list = PresentList::new(200);
188
189 assert!(list.mark_as_present(10..14));
190 assert!(list.clear_range(11..13));
191 assert_eq!(*list.get(9).unwrap(), false);
192 assert_eq!(*list.get(10).unwrap(), true);
193 assert_eq!(*list.get(11).unwrap(), false);
194 assert_eq!(*list.get(12).unwrap(), false);
195 assert_eq!(*list.get(13).unwrap(), true);
196 assert_eq!(*list.get(14).unwrap(), false);
197 }
198
199 #[test]
200 fn clear_range_duplicated() {
201 let mut list = PresentList::new(200);
202
203 assert!(list.mark_as_present(10..14));
204 assert!(list.clear_range(11..13));
205 assert!(list.clear_range(12..15));
206 assert_eq!(*list.get(9).unwrap(), false);
207 assert_eq!(*list.get(10).unwrap(), true);
208 assert_eq!(*list.get(11).unwrap(), false);
209 assert_eq!(*list.get(12).unwrap(), false);
210 assert_eq!(*list.get(13).unwrap(), false);
211 assert_eq!(*list.get(14).unwrap(), false);
212 assert_eq!(*list.get(15).unwrap(), false);
213 }
214
215 #[test]
216 fn clear_range_out_of_range() {
217 let mut list = PresentList::new(200);
218
219 assert!(list.mark_as_present(10..11));
220 assert!(!list.clear_range(10..201));
221 assert_eq!(*list.get(10).unwrap(), true);
222 }
223
224 #[test]
225 fn first_data_range() {
226 let mut list = PresentList::new(200);
227
228 list.mark_as_present(1..3);
229 list.mark_as_present(12..13);
230 list.mark_as_present(20..22);
231 list.mark_as_present(22..23);
232 list.mark_as_present(23..30);
233
234 assert_eq!(list.first_data_range(200).unwrap(), 1..3);
235 list.clear_range(1..3);
236 assert_eq!(list.first_data_range(200).unwrap(), 12..13);
237 list.clear_range(12..13);
238 assert_eq!(list.first_data_range(200).unwrap(), 20..30);
239 list.clear_range(20..30);
240 assert!(list.first_data_range(200).is_none());
241 }
242
243 #[test]
244 fn first_data_range_clear_partially() {
245 let mut list = PresentList::new(200);
246
247 list.mark_as_present(10..20);
248
249 list.clear_range(5..10);
250 assert_eq!(list.first_data_range(200).unwrap(), 10..20);
251 list.clear_range(5..12);
252 assert_eq!(list.first_data_range(200).unwrap(), 12..20);
253 list.clear_range(19..21);
254 assert_eq!(list.first_data_range(200).unwrap(), 12..19);
255 list.clear_range(16..17);
256 assert_eq!(list.first_data_range(200).unwrap(), 12..16);
257 }
258
259 #[test]
260 fn first_data_range_mark_after_clear() {
261 let mut list = PresentList::new(200);
262
263 list.mark_as_present(10..20);
264
265 list.clear_range(10..15);
266 assert_eq!(list.first_data_range(200).unwrap(), 15..20);
267 list.mark_as_present(5..15);
268 assert_eq!(list.first_data_range(200).unwrap(), 5..20);
269 }
270
271 #[test]
272 fn first_data_range_end_is_full() {
273 let mut list = PresentList::new(20);
274
275 list.mark_as_present(10..20);
276
277 assert_eq!(list.first_data_range(20).unwrap(), 10..20);
278 }
279
280 #[test]
281 fn first_data_range_max_pages() {
282 let mut list = PresentList::new(20);
283
284 list.mark_as_present(10..13);
285
286 assert_eq!(list.first_data_range(1).unwrap(), 10..11);
287 assert_eq!(list.first_data_range(2).unwrap(), 10..12);
288 assert_eq!(list.first_data_range(3).unwrap(), 10..13);
289 assert_eq!(list.first_data_range(4).unwrap(), 10..13);
290 }
291
292 #[test]
293 fn find_data_range() {
294 let mut list = PresentList::new(200);
295
296 list.mark_as_present(1..3);
297 list.mark_as_present(12..13);
298 list.mark_as_present(20..22);
299 list.mark_as_present(22..23);
300 list.mark_as_present(23..30);
301
302 assert_eq!(list.find_data_range(0, 200).unwrap(), 1..3);
303 assert_eq!(list.find_data_range(3, 200).unwrap(), 12..13);
304 assert_eq!(list.find_data_range(13, 200).unwrap(), 20..30);
305 assert_eq!(list.find_data_range(22, 5).unwrap(), 22..27);
306 assert!(list.find_data_range(30, 200).is_none());
307 assert!(list.find_data_range(200, 200).is_none());
308 }
309
310 #[test]
311 fn find_data_range_clear_partially() {
312 let mut list = PresentList::new(200);
313
314 list.mark_as_present(10..20);
315
316 list.clear_range(5..10);
317 assert_eq!(list.find_data_range(0, 200).unwrap(), 10..20);
318 list.clear_range(5..12);
319 assert_eq!(list.find_data_range(0, 200).unwrap(), 12..20);
320 list.clear_range(19..21);
321 assert_eq!(list.find_data_range(0, 200).unwrap(), 12..19);
322 list.clear_range(16..17);
323 assert_eq!(list.find_data_range(0, 200).unwrap(), 12..16);
324 }
325
326 #[test]
327 fn find_data_range_mark_after_clear() {
328 let mut list = PresentList::new(200);
329
330 list.mark_as_present(10..20);
331
332 list.clear_range(10..15);
333 assert_eq!(list.find_data_range(0, 200).unwrap(), 15..20);
334 list.mark_as_present(5..15);
335 assert_eq!(list.find_data_range(0, 200).unwrap(), 5..20);
336 }
337
338 #[test]
339 fn find_data_range_end_is_full() {
340 let mut list = PresentList::new(20);
341
342 list.mark_as_present(10..20);
343
344 assert_eq!(list.find_data_range(0, 20).unwrap(), 10..20);
345 }
346
347 #[test]
348 fn find_data_range_max_pages() {
349 let mut list = PresentList::new(20);
350
351 list.mark_as_present(10..13);
352
353 assert_eq!(list.find_data_range(0, 1).unwrap(), 10..11);
354 assert_eq!(list.find_data_range(0, 2).unwrap(), 10..12);
355 assert_eq!(list.find_data_range(0, 3).unwrap(), 10..13);
356 assert_eq!(list.find_data_range(0, 4).unwrap(), 10..13);
357 }
358
359 #[test]
360 fn all_present_pages() {
361 let mut list = PresentList::new(20);
362
363 list.mark_as_present(1..5);
364 list.mark_as_present(12..13);
365
366 assert_eq!(list.all_present_pages(), 5);
367 }
368}