1use std::fmt;
16
17pub type SnapshotId = usize;
18
19const BITS_PER_SET: usize = 64;
20const SNAPSHOT_ID_SIZE: usize = 64;
21
22#[derive(Clone, PartialEq, Eq)]
23pub struct SnapshotIdSet {
24 upper_set: u64,
26 lower_set: u64,
28 lower_bound: SnapshotId,
30 below_bound: Option<Box<[SnapshotId]>>,
32}
33
34impl SnapshotIdSet {
35 pub const EMPTY: SnapshotIdSet = SnapshotIdSet {
37 upper_set: 0,
38 lower_set: 0,
39 lower_bound: 0,
40 below_bound: None,
41 };
42
43 pub fn new() -> Self {
45 Self::EMPTY
46 }
47
48 pub fn get(&self, id: SnapshotId) -> bool {
50 let offset = id.wrapping_sub(self.lower_bound);
51
52 if offset < BITS_PER_SET {
53 let mask = 1u64 << offset;
55 (self.lower_set & mask) != 0
56 } else if offset < BITS_PER_SET * 2 {
57 let mask = 1u64 << (offset - BITS_PER_SET);
59 (self.upper_set & mask) != 0
60 } else if id > self.lower_bound {
61 false
63 } else {
64 self.below_bound
66 .as_ref()
67 .map(|arr| arr.binary_search(&id).is_ok())
68 .unwrap_or(false)
69 }
70 }
71
72 pub fn set(&self, id: SnapshotId) -> Self {
74 if id < self.lower_bound {
75 if let Some(ref arr) = self.below_bound {
76 match arr.binary_search(&id) {
77 Ok(_) => {
78 return self.clone();
80 }
81 Err(insert_pos) => {
82 let mut new_arr = Vec::with_capacity(arr.len() + 1);
84 new_arr.extend_from_slice(&arr[..insert_pos]);
85 new_arr.push(id);
86 new_arr.extend_from_slice(&arr[insert_pos..]);
87 return Self {
88 upper_set: self.upper_set,
89 lower_set: self.lower_set,
90 lower_bound: self.lower_bound,
91 below_bound: Some(new_arr.into_boxed_slice()),
92 };
93 }
94 }
95 } else {
96 return Self {
98 upper_set: self.upper_set,
99 lower_set: self.lower_set,
100 lower_bound: self.lower_bound,
101 below_bound: Some(vec![id].into_boxed_slice()),
102 };
103 }
104 }
105
106 let offset = id - self.lower_bound;
107
108 if offset < BITS_PER_SET {
109 let mask = 1u64 << offset;
111 if (self.lower_set & mask) == 0 {
112 return Self {
113 upper_set: self.upper_set,
114 lower_set: self.lower_set | mask,
115 lower_bound: self.lower_bound,
116 below_bound: self.below_bound.clone(),
117 };
118 }
119 } else if offset < BITS_PER_SET * 2 {
120 let mask = 1u64 << (offset - BITS_PER_SET);
122 if (self.upper_set & mask) == 0 {
123 return Self {
124 upper_set: self.upper_set | mask,
125 lower_set: self.lower_set,
126 lower_bound: self.lower_bound,
127 below_bound: self.below_bound.clone(),
128 };
129 }
130 } else if offset >= BITS_PER_SET * 2 {
131 if !self.get(id) {
133 return self.shift_and_set(id);
134 }
135 }
136
137 self.clone()
139 }
140
141 pub fn clear(&self, id: SnapshotId) -> Self {
143 let offset = id.wrapping_sub(self.lower_bound);
144
145 if offset < BITS_PER_SET {
146 let mask = 1u64 << offset;
148 if (self.lower_set & mask) != 0 {
149 return Self {
150 upper_set: self.upper_set,
151 lower_set: self.lower_set & !mask,
152 lower_bound: self.lower_bound,
153 below_bound: self.below_bound.clone(),
154 };
155 }
156 } else if offset < BITS_PER_SET * 2 {
157 let mask = 1u64 << (offset - BITS_PER_SET);
159 if (self.upper_set & mask) != 0 {
160 return Self {
161 upper_set: self.upper_set & !mask,
162 lower_set: self.lower_set,
163 lower_bound: self.lower_bound,
164 below_bound: self.below_bound.clone(),
165 };
166 }
167 } else if id < self.lower_bound {
168 if let Some(ref arr) = self.below_bound
170 && let Ok(pos) = arr.binary_search(&id)
171 {
172 let mut new_arr = Vec::with_capacity(arr.len() - 1);
173 new_arr.extend_from_slice(&arr[..pos]);
174 new_arr.extend_from_slice(&arr[pos + 1..]);
175 return Self {
176 upper_set: self.upper_set,
177 lower_set: self.lower_set,
178 lower_bound: self.lower_bound,
179 below_bound: if new_arr.is_empty() {
180 None
181 } else {
182 Some(new_arr.into_boxed_slice())
183 },
184 };
185 }
186 }
187
188 self.clone()
190 }
191
192 pub fn and_not(&self, other: &Self) -> Self {
194 if other.is_empty() {
195 return self.clone();
196 }
197 if self.is_empty() {
198 return Self::EMPTY;
199 }
200
201 if self.lower_bound == other.lower_bound && self.below_bound_equals(&other.below_bound) {
203 return Self {
204 upper_set: self.upper_set & !other.upper_set,
205 lower_set: self.lower_set & !other.lower_set,
206 lower_bound: self.lower_bound,
207 below_bound: self.below_bound.clone(),
208 };
209 }
210
211 let mut result = self.clone();
213 for id in other.iter() {
214 result = result.clear(id);
215 }
216 result
217 }
218
219 pub fn or(&self, other: &Self) -> Self {
221 if other.is_empty() {
222 return self.clone();
223 }
224 if self.is_empty() {
225 return other.clone();
226 }
227
228 if self.lower_bound == other.lower_bound && self.below_bound_equals(&other.below_bound) {
230 return Self {
231 upper_set: self.upper_set | other.upper_set,
232 lower_set: self.lower_set | other.lower_set,
233 lower_bound: self.lower_bound,
234 below_bound: self.below_bound.clone(),
235 };
236 }
237
238 let mut result = self.clone();
240 for id in other.iter() {
241 result = result.set(id);
242 }
243 result
244 }
245
246 pub fn lowest(&self, upper: SnapshotId) -> SnapshotId {
248 if let Some(ref arr) = self.below_bound
250 && let Some(&lowest) = arr.first()
251 && lowest <= upper
252 {
253 return lowest;
254 }
255
256 if self.lower_set != 0 {
258 let lowest_in_lower = self.lower_bound + self.lower_set.trailing_zeros() as usize;
259 if lowest_in_lower <= upper {
260 return lowest_in_lower;
261 }
262 }
263
264 if self.upper_set != 0 {
266 let lowest_in_upper =
267 self.lower_bound + BITS_PER_SET + self.upper_set.trailing_zeros() as usize;
268 if lowest_in_upper <= upper {
269 return lowest_in_upper;
270 }
271 }
272
273 upper
275 }
276
277 pub fn is_empty(&self) -> bool {
279 self.lower_set == 0 && self.upper_set == 0 && self.below_bound.is_none()
280 }
281
282 pub fn iter(&self) -> SnapshotIdSetIter<'_> {
284 SnapshotIdSetIter::new(self)
285 }
286
287 pub fn to_list(&self) -> Vec<SnapshotId> {
289 self.iter().collect()
290 }
291
292 pub fn add_range(&self, from: SnapshotId, until: SnapshotId) -> Self {
295 if from >= until {
296 return self.clone();
297 }
298 let mut result = self.clone();
299 let mut id = from;
300 while id < until {
301 result = result.set(id);
302 id += 1;
303 }
304 result
305 }
306
307 fn below_bound_equals(&self, other: &Option<Box<[SnapshotId]>>) -> bool {
309 match (&self.below_bound, other) {
310 (None, None) => true,
311 (Some(a), Some(b)) => a == b,
312 _ => false,
313 }
314 }
315
316 fn shift_and_set(&self, id: SnapshotId) -> Self {
318 let target_lower_bound = (id / SNAPSHOT_ID_SIZE) * SNAPSHOT_ID_SIZE;
319
320 let mut new_upper_set = self.upper_set;
321 let mut new_lower_set = self.lower_set;
322 let mut new_lower_bound = self.lower_bound;
323 let mut new_below_bound: Vec<SnapshotId> = if let Some(ref arr) = self.below_bound {
324 arr.to_vec()
325 } else {
326 Vec::new()
327 };
328
329 while new_lower_bound < target_lower_bound {
330 if new_lower_set != 0 {
332 for bit_offset in 0..BITS_PER_SET {
333 if (new_lower_set & (1u64 << bit_offset)) != 0 {
334 let id_to_add = new_lower_bound + bit_offset;
335 match new_below_bound.binary_search(&id_to_add) {
337 Ok(_) => {} Err(pos) => new_below_bound.insert(pos, id_to_add),
339 }
340 }
341 }
342 }
343
344 if new_upper_set == 0 {
346 new_lower_bound = target_lower_bound;
347 new_lower_set = 0;
348 break;
349 }
350
351 new_lower_set = new_upper_set;
352 new_upper_set = 0;
353 new_lower_bound += BITS_PER_SET;
354 }
355
356 let result = Self {
357 upper_set: new_upper_set,
358 lower_set: new_lower_set,
359 lower_bound: new_lower_bound,
360 below_bound: if new_below_bound.is_empty() {
361 None
362 } else {
363 Some(new_below_bound.into_boxed_slice())
364 },
365 };
366
367 result.set(id)
369 }
370}
371
372impl Default for SnapshotIdSet {
373 fn default() -> Self {
374 Self::EMPTY
375 }
376}
377
378impl fmt::Debug for SnapshotIdSet {
379 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380 write!(f, "SnapshotIdSet{{")?;
381 let ids: Vec<_> = self.iter().collect();
382 for (i, id) in ids.iter().enumerate() {
383 if i > 0 {
384 write!(f, ", ")?;
385 }
386 write!(f, "{}", id)?;
387 }
388 write!(f, "}}")
389 }
390}
391
392pub struct SnapshotIdSetIter<'a> {
394 set: &'a SnapshotIdSet,
395 below_index: usize,
396 lower_set: u64,
397 upper_set: u64,
398 current_offset: usize,
399}
400
401impl<'a> SnapshotIdSetIter<'a> {
402 fn new(set: &'a SnapshotIdSet) -> Self {
403 Self {
404 set,
405 below_index: 0,
406 lower_set: set.lower_set,
407 upper_set: set.upper_set,
408 current_offset: 0,
409 }
410 }
411}
412
413impl<'a> Iterator for SnapshotIdSetIter<'a> {
414 type Item = SnapshotId;
415
416 fn next(&mut self) -> Option<Self::Item> {
417 if let Some(ref arr) = self.set.below_bound
419 && self.below_index < arr.len()
420 {
421 let id = arr[self.below_index];
422 self.below_index += 1;
423 return Some(id);
424 }
425
426 while self.current_offset < BITS_PER_SET {
428 if (self.lower_set & (1u64 << self.current_offset)) != 0 {
429 let id = self.set.lower_bound + self.current_offset;
430 self.current_offset += 1;
431 return Some(id);
432 }
433 self.current_offset += 1;
434 }
435
436 while self.current_offset < BITS_PER_SET * 2 {
438 let bit_offset = self.current_offset - BITS_PER_SET;
439 if (self.upper_set & (1u64 << bit_offset)) != 0 {
440 let id = self.set.lower_bound + self.current_offset;
441 self.current_offset += 1;
442 return Some(id);
443 }
444 self.current_offset += 1;
445 }
446
447 None
448 }
449}
450
451#[cfg(test)]
452mod tests {
453 use super::*;
454
455 #[test]
456 fn test_empty_set() {
457 let set = SnapshotIdSet::EMPTY;
458 assert!(set.is_empty());
459 assert!(!set.get(0));
460 assert!(!set.get(100));
461 }
462
463 #[test]
464 fn test_set_and_get_lower_range() {
465 let set = SnapshotIdSet::new();
466 let set = set.set(0);
467 assert!(set.get(0));
468 assert!(!set.get(1));
469
470 let set = set.set(63);
471 assert!(set.get(0));
472 assert!(set.get(63));
473 assert!(!set.get(64));
474 }
475
476 #[test]
477 fn test_set_and_get_upper_range() {
478 let set = SnapshotIdSet::new();
479 let set = set.set(64);
480 assert!(set.get(64));
481 assert!(!set.get(63));
482 assert!(!set.get(128));
483
484 let set = set.set(127);
485 assert!(set.get(64));
486 assert!(set.get(127));
487 assert!(!set.get(128));
488 }
489
490 #[test]
491 fn test_set_idempotent() {
492 let set = SnapshotIdSet::new();
493 let set1 = set.set(10);
494 let set2 = set1.set(10);
495 assert_eq!(set1, set2);
496 }
497
498 #[test]
499 fn test_clear() {
500 let set = SnapshotIdSet::new().set(10).set(20).set(30);
501 assert!(set.get(10));
502 assert!(set.get(20));
503 assert!(set.get(30));
504
505 let set = set.clear(20);
506 assert!(set.get(10));
507 assert!(!set.get(20));
508 assert!(set.get(30));
509 }
510
511 #[test]
512 fn test_clear_idempotent() {
513 let set = SnapshotIdSet::new().set(10);
514 let set1 = set.clear(10);
515 let set2 = set1.clear(10);
516 assert_eq!(set1, set2);
517 }
518
519 #[test]
520 fn test_below_bound_insertion() {
521 let mut set = SnapshotIdSet::new();
522 set = set.set(100);
524 assert_eq!(set.lower_bound, 0);
525
526 set = set.set(50);
528 assert!(set.get(50));
529 assert!(set.get(100));
530
531 set = set.set(25);
532 set = set.set(75);
533 assert!(set.get(25));
534 assert!(set.get(50));
535 assert!(set.get(75));
536 assert!(set.get(100));
537
538 let list = set.to_list();
540 assert_eq!(list, vec![25, 50, 75, 100]);
541 }
542
543 #[test]
544 fn test_below_bound_removal() {
545 let set = SnapshotIdSet::new();
547 let set = set.set(25);
548 let set = set.set(50);
549 let set = set.set(75);
550 let set = set.set(200);
551
552 let set = set.clear(50);
553 assert!(set.get(25));
554 assert!(!set.get(50));
555 assert!(set.get(75));
556 assert!(set.get(200));
557
558 let list = set.to_list();
559 assert_eq!(list, vec![25, 75, 200]);
560 }
561
562 #[test]
563 fn test_shift_and_set() {
564 let set = SnapshotIdSet::new();
565 let set = set.set(10);
566 assert_eq!(set.lower_bound, 0);
567
568 let set = set.set(200);
570 assert!(set.get(10));
571 assert!(set.get(200));
572
573 assert!(set.below_bound.is_some());
575 }
576
577 #[test]
578 fn test_shift_and_set_boundary_values() {
579 let mut set = SnapshotIdSet::new();
580 let boundary = SNAPSHOT_ID_SIZE * 12 - 1;
581 set = set.set(boundary);
582 assert!(set.get(boundary));
583
584 set = set.set(boundary + 1);
585 assert!(set.get(boundary));
586 assert!(set.get(boundary + 1));
587 }
588
589 #[test]
590 fn test_set_below_lower_bound_inserts() {
591 let set = SnapshotIdSet::new().set(200);
592 let lower_bound = set.lower_bound;
593 assert!(lower_bound > 0);
594
595 let below = lower_bound - 1;
596 let set = set.set(below);
597 assert!(set.get(below));
598 assert!(set.get(200));
599 }
600
601 #[test]
602 fn test_and_not_fast_path() {
603 let set1 = SnapshotIdSet::new().set(10).set(20).set(30);
604 let set2 = SnapshotIdSet::new().set(20).set(40);
605
606 let result = set1.and_not(&set2);
607 assert!(result.get(10));
608 assert!(!result.get(20));
609 assert!(result.get(30));
610 assert!(!result.get(40));
611 }
612
613 #[test]
614 fn test_and_not_slow_path() {
615 let set1 = SnapshotIdSet::new().set(10).set(20).set(30);
616 let set2 = SnapshotIdSet::new().set(100).set(20);
618
619 let result = set1.and_not(&set2);
620 assert!(result.get(10));
621 assert!(!result.get(20));
622 assert!(result.get(30));
623 }
624
625 #[test]
626 fn test_or_fast_path() {
627 let set1 = SnapshotIdSet::new().set(10).set(20);
628 let set2 = SnapshotIdSet::new().set(20).set(30);
629
630 let result = set1.or(&set2);
631 assert!(result.get(10));
632 assert!(result.get(20));
633 assert!(result.get(30));
634 }
635
636 #[test]
637 fn test_or_slow_path() {
638 let set1 = SnapshotIdSet::new().set(10).set(20);
639 let set2 = SnapshotIdSet::new().set(100).set(30);
640
641 let result = set1.or(&set2);
642 assert!(result.get(10));
643 assert!(result.get(20));
644 assert!(result.get(30));
645 assert!(result.get(100));
646 }
647
648 #[test]
649 fn test_lowest_in_below_bound() {
650 let set = SnapshotIdSet::new();
652 let set = set.set(25);
653 let set = set.set(50);
654 let set = set.set(200);
655 assert_eq!(set.lowest(1000), 25);
656 assert_eq!(set.lowest(100), 25);
657 assert_eq!(set.lowest(30), 25);
658 }
659
660 #[test]
661 fn test_lowest_in_lower_set() {
662 let set = SnapshotIdSet::new().set(10).set(20).set(30);
663 assert_eq!(set.lowest(1000), 10);
664 assert_eq!(set.lowest(25), 10);
665 }
666
667 #[test]
668 fn test_lowest_in_upper_set() {
669 let set = SnapshotIdSet::new().set(70).set(80).set(90);
670 assert_eq!(set.lowest(1000), 70);
671 }
672
673 #[test]
674 fn test_lowest_returns_upper_if_none_found() {
675 let set = SnapshotIdSet::new().set(100);
676 assert_eq!(set.lowest(50), 50);
677 }
678
679 #[test]
680 fn test_iterator() {
681 let set = SnapshotIdSet::new().set(10).set(20).set(5).set(30);
682 let list: Vec<_> = set.iter().collect();
683 assert_eq!(list, vec![5, 10, 20, 30]);
685 }
686
687 #[test]
688 fn test_iterator_empty() {
689 let set = SnapshotIdSet::new();
690 let list: Vec<_> = set.iter().collect();
691 assert_eq!(list, Vec::<SnapshotId>::new());
692 }
693
694 #[test]
695 fn test_iterator_all_ranges() {
696 let set = SnapshotIdSet::new()
697 .set(5) .set(10) .set(70) .set(200); let list: Vec<_> = set.iter().collect();
703 assert_eq!(list, vec![5, 10, 70, 200]);
704 }
705
706 #[test]
707 fn test_to_list() {
708 let set = SnapshotIdSet::new().set(10).set(20).set(30);
709 assert_eq!(set.to_list(), vec![10, 20, 30]);
710 }
711
712 #[test]
713 fn test_debug_format() {
714 let set = SnapshotIdSet::new().set(10).set(20);
715 let debug_str = format!("{:?}", set);
716 assert_eq!(debug_str, "SnapshotIdSet{10, 20}");
717 }
718
719 #[test]
720 fn test_large_snapshot_ids() {
721 let set = SnapshotIdSet::new();
723 let set = set.set(500);
724 let set = set.set(1000);
725 let set = set.set(2000);
726
727 assert!(set.get(500));
728 assert!(set.get(1000));
729 assert!(set.get(2000));
730 assert!(!set.get(1500));
731 }
732
733 #[test]
734 fn test_boundary_transitions() {
735 let set = SnapshotIdSet::new();
736
737 let set = set.set(63);
739 let set = set.set(64);
740 assert!(set.get(63));
741 assert!(set.get(64));
742
743 let set = set.set(127);
745 let set = set.set(128);
746 assert!(set.get(127));
747 assert!(set.get(128));
748 }
749}