Skip to main content

dag/
idset.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8//! # idset
9//!
10//! See [`IdSet`] for the main structure.
11
12use std::cmp::Ordering;
13use std::cmp::Ordering::Equal;
14use std::cmp::Ordering::Greater;
15use std::cmp::Ordering::Less;
16use std::collections::BinaryHeap;
17use std::collections::VecDeque;
18use std::fmt;
19use std::fmt::Debug;
20use std::iter::Rev;
21use std::ops::Bound;
22use std::ops::RangeBounds;
23use std::ops::RangeInclusive;
24use std::sync::Arc;
25
26use dag_types::FlatSegment;
27use serde::Deserialize;
28use serde::Serialize;
29
30use crate::bsearch::BinarySearchBy;
31use crate::id::Id;
32
33/// Range `low..=high`. `low` must be <= `high`.
34#[derive(Copy, Clone, Debug, Eq, Serialize, Deserialize)]
35pub struct Span {
36    #[serde(with = "flat_id")]
37    pub(crate) low: Id,
38    #[serde(with = "flat_id")]
39    pub(crate) high: Id,
40}
41
42/// A set of integer spans.
43#[derive(Clone, Serialize, Deserialize, Default)]
44pub struct IdSet {
45    /// `spans` are sorted in DESC order.
46    spans: VecDeque<Span>,
47}
48
49impl PartialOrd for Span {
50    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51        Some(match self.high.cmp(&other.high) {
52            Less => Less,
53            Greater => Greater,
54            Equal => self.low.cmp(&other.low),
55        })
56    }
57}
58
59impl PartialEq for Span {
60    fn eq(&self, other: &Self) -> bool {
61        other.low == self.low && other.high == self.high
62    }
63}
64
65impl Ord for Span {
66    fn cmp(&self, other: &Self) -> Ordering {
67        match self.high.cmp(&other.high) {
68            Less => Less,
69            Greater => Greater,
70            Equal => self.low.cmp(&other.low),
71        }
72    }
73}
74
75impl Span {
76    pub fn new(low: Id, high: Id) -> Self {
77        assert!(low <= high, "low {:?} <= high {:?}", low, high);
78        Self { low, high }
79    }
80
81    pub fn count(self) -> u64 {
82        self.high.0 - self.low.0 + 1
83    }
84
85    /// Get the n-th [`Id`] in this [`Span`].
86    ///
87    /// Similar to [`IdSet`], ids are sorted in descending order.
88    /// The 0-th Id is `high`.
89    pub fn nth(self, n: u64) -> Option<Id> {
90        if n >= self.count() {
91            None
92        } else {
93            Some(self.high - n)
94        }
95    }
96
97    pub(crate) fn contains(self, value: Id) -> bool {
98        self.low <= value && value <= self.high
99    }
100
101    /// Construct a full [`Span`] that contains everything.
102    /// Warning: The [`Id`] in this span might be unknown to an actual storage.
103    pub fn full() -> Self {
104        (Id::MIN..=Id::MAX).into()
105    }
106
107    /// Test if this span overlaps with another.
108    pub fn overlaps_with(&self, other: &Self) -> bool {
109        self.low <= other.high && other.low <= self.high
110    }
111
112    pub(crate) fn try_from_bounds(bounds: impl RangeBounds<Id>) -> Option<Self> {
113        use Bound::Excluded;
114        use Bound::Included;
115        #[cfg(debug_assertions)]
116        {
117            use Bound::Unbounded;
118            match (bounds.start_bound(), bounds.end_bound()) {
119                (Excluded(_), _) | (Unbounded, _) | (_, Unbounded) => {
120                    panic!("unsupported bound type")
121                }
122                _ => {}
123            }
124        }
125        match (bounds.start_bound(), bounds.end_bound()) {
126            (Included(&low), Included(&high)) if low <= high => Some(Span { low, high }),
127            (Included(&low), Excluded(&high_plus_one)) if low < high_plus_one => {
128                let high = high_plus_one - 1;
129                Some(Span { low, high })
130            }
131            _ => None,
132        }
133    }
134}
135
136/// Subspan is a trait for an object that
137/// (a) Can be mapped into Span
138/// (b) Can return 'subspan' for any given non-empty subset of it's span
139pub trait Subspan {
140    fn span(&self) -> Span;
141
142    /// Provided span should be subset of T::span(), otherwise this method behavior is undefined
143    fn subspan(&self, span: Span) -> Self;
144
145    /// Overlaps two objects and returns result of overlap and remainders for left and right object
146    /// This method is generally defined for any two types that implement Subspan
147    /// Type of an overlap if the same as type of Self
148    ///
149    /// Returns:
150    ///  - overlap: overlap between two objects
151    ///  - rem_left: remaining non-overlapping part of left object
152    ///  - rem_right: remaining non-overlapping part of right object
153    ///
154    /// L: [123456]
155    /// R:    [456789]
156    /// overlap(L, R) = ([456], [123], None)
157    fn intersect<R: Subspan>(&self, r: &R) -> (Option<Self>, Option<Self>, Option<R>)
158    where
159        Self: Sized,
160    {
161        let left = self.span();
162        let right = r.span();
163        let span_low = left.low.max(right.low);
164        let span_high = left.high.min(right.high);
165        let overlap = Span::try_from_bounds(span_low..=span_high);
166
167        let rem_left = Span::try_from_bounds(left.low..(left.high + 1).min(span_low));
168        let rem_right = Span::try_from_bounds(right.low..(right.high + 1).min(span_low));
169
170        let overlap = overlap.map(|s| self.subspan(s));
171        let rem_left = rem_left.map(|s| self.subspan(s));
172        let rem_right = rem_right.map(|s| r.subspan(s));
173        (overlap, rem_left, rem_right)
174    }
175}
176
177/// Calculates the intersection of two ordered iterators of span-like objects.
178pub fn intersect_iter<
179    L: Subspan,
180    R: Subspan,
181    LI: Iterator<Item = L>,
182    RI: Iterator<Item = R>,
183    P: FnMut(L),
184>(
185    mut lhs: LI,
186    mut rhs: RI,
187    mut push: P,
188) {
189    let mut next_left = lhs.next();
190    let mut next_right = rhs.next();
191
192    while let (Some(left), Some(right)) = (next_left, next_right) {
193        // current:
194        //   |------- A --------|
195        //         |------- B ------|
196        //         |--- span ---|
197        // next:
198        //   |- A -| (remaining part of A)
199        //           (next B)
200        // note: (A, B) can be either (left, right) or (right, left)
201        let (span, rem_left, rem_right) = left.intersect(&right);
202
203        if let Some(span) = span {
204            push(span);
205        }
206
207        next_right = rem_right.or_else(|| rhs.next());
208        next_left = rem_left.or_else(|| lhs.next());
209    }
210}
211
212impl Subspan for Span {
213    fn span(&self) -> Span {
214        *self
215    }
216
217    fn subspan(&self, span: Span) -> Self {
218        assert!(self.low <= span.low);
219        assert!(self.high >= span.high);
220        span
221    }
222}
223
224impl Subspan for FlatSegment {
225    fn span(&self) -> Span {
226        Span::new(self.low, self.high)
227    }
228
229    fn subspan(&self, span: Span) -> Self {
230        assert!(self.low <= span.low);
231        assert!(self.high >= span.high);
232        if span.low == self.low {
233            FlatSegment {
234                low: span.low,
235                high: span.high,
236                parents: self.parents.clone(),
237            }
238        } else {
239            FlatSegment {
240                low: span.low,
241                high: span.high,
242                parents: vec![span.low - 1],
243            }
244        }
245    }
246}
247
248// This is for users who want shorter code than [`Span::new`].
249// Internal logic here should use [`Span::new`], or [`Span::try_from_bounds`],
250// or construct [`Span`] directly.
251impl From<RangeInclusive<Id>> for Span {
252    fn from(range: RangeInclusive<Id>) -> Span {
253        Span::new(*range.start(), *range.end())
254    }
255}
256
257impl From<Id> for Span {
258    fn from(id: Id) -> Span {
259        Span::new(id, id)
260    }
261}
262
263impl<T: Into<Span>> From<T> for IdSet {
264    fn from(span: T) -> IdSet {
265        IdSet::from_single_span(span.into())
266    }
267}
268
269impl From<Span> for RangeInclusive<Id> {
270    fn from(span: Span) -> RangeInclusive<Id> {
271        span.low..=span.high
272    }
273}
274
275// This is used by `gca(set)` where `set` usually contains 2 ids. The code
276// can then be written as `gca((a, b))`.
277impl From<(Id, Id)> for IdSet {
278    fn from(ids: (Id, Id)) -> IdSet {
279        IdSet::from_spans([ids.0, ids.1].iter().cloned())
280    }
281}
282
283impl IdSet {
284    /// Construct a [`IdSet`] containing given spans.
285    /// Overlapped or adjacent spans will be merged automatically.
286    pub fn from_spans<T: Into<Span>, I: IntoIterator<Item = T>>(spans: I) -> Self {
287        let mut heap: BinaryHeap<Span> = spans.into_iter().map(|span| span.into()).collect();
288        let mut spans = VecDeque::with_capacity(heap.len().min(64));
289        while let Some(span) = heap.pop() {
290            push_with_union(&mut spans, span);
291        }
292        let result = IdSet { spans };
293        // `result` should be valid because the use of `push_with_union`.
294        #[cfg(debug_assertions)]
295        result.validate();
296        result
297    }
298
299    /// Construct a [`IdSet`] that contains a single span.
300    pub fn from_single_span(span: Span) -> Self {
301        let spans: VecDeque<_> = std::iter::once(span).collect();
302        Self { spans }
303    }
304
305    /// Construct a [`IdSet`] containing given spans.
306    /// The given spans must be already sorted (i.e. larger ids first), and do
307    /// not have overlapped spans.
308    /// Adjacent spans will be merged automatically.
309    pub fn from_sorted_spans<T: Into<Span>, I: IntoIterator<Item = T>>(span_iter: I) -> Self {
310        let mut spans = VecDeque::<Span>::new();
311        for span in span_iter {
312            let span = span.into();
313            push_with_union(&mut spans, span);
314        }
315        let result = Self { spans };
316        #[cfg(debug_assertions)]
317        result.validate();
318        result
319    }
320
321    /// Construct an empty [`IdSet`].
322    pub fn empty() -> Self {
323        let spans = VecDeque::new();
324        IdSet { spans }
325    }
326
327    /// Construct a full [`IdSet`] that contains everything.
328    /// Warning: The [`Id`] in this set might be unknown to an actual storage.
329    pub fn full() -> Self {
330        Span::full().into()
331    }
332
333    /// Check if this [`IdSet`] contains nothing.
334    pub fn is_empty(&self) -> bool {
335        self.spans.is_empty()
336    }
337
338    /// Validate the spans are in the expected order and there are no mergable
339    /// adjacent spans.
340    #[cfg(debug_assertions)]
341    fn validate(&self) {
342        for (i, span) in self.spans.iter().enumerate() {
343            assert!(span.low <= span.high);
344            if i > 0 {
345                assert!(
346                    span.high + 1 < self.spans[i - 1].low,
347                    "{:?} is not in DESC order or has mergable adjacent spans (around #{})",
348                    &self.spans,
349                    i
350                );
351            }
352        }
353    }
354
355    /// Count integers covered by this [`IdSet`].
356    pub fn count(&self) -> u64 {
357        self.spans.iter().fold(0, |acc, span| acc + span.count())
358    }
359
360    /// Tests if a given [`Id`] or [`Span`] is covered by this set.
361    pub fn contains(&self, value: impl Into<Span>) -> bool {
362        self.span_contains(value).is_some()
363    }
364
365    /// Find the [`Span`] that covers the given `value`.
366    pub fn span_contains(&self, value: impl Into<Span>) -> Option<&Span> {
367        let span = value.into();
368        let idx = match self.spans.bsearch_by(|probe| span.low.cmp(&probe.low)) {
369            Ok(idx) => idx,
370            Err(idx) => idx,
371        };
372        if let Some(existing_span) = self.spans.get(idx) {
373            debug_assert!(existing_span.low <= span.low);
374            if existing_span.high >= span.high {
375                return Some(existing_span);
376            }
377        }
378        None
379    }
380
381    /// Skip the first `n` items.
382    pub fn skip(&self, mut n: u64) -> Self {
383        #[cfg(test)]
384        let expected = n.max(self.count()) - n;
385        let mut result = IdSet::empty();
386        for span in self.as_spans() {
387            if n == 0 {
388                result.push_span(*span);
389            } else {
390                let count = span.count();
391                if count <= n {
392                    // This span is skipped entirely.
393                    n -= count;
394                } else {
395                    // This span is skipped partially.
396                    debug_assert!(n > 0);
397                    debug_assert!(n < count);
398                    let high = span.high - n;
399                    n = 0;
400                    result.push_span((span.low..=high).into());
401                }
402            }
403        }
404        #[cfg(test)]
405        assert_eq!(result.count(), expected);
406        result
407    }
408
409    /// Only take the first `n` items.
410    pub fn take(&self, mut n: u64) -> Self {
411        #[cfg(test)]
412        let expected = n.min(self.count());
413        let mut result = IdSet::empty();
414        for span in self.as_spans() {
415            if n == 0 {
416                break;
417            } else {
418                let count = span.count();
419                if count <= n {
420                    // This span is taken entirely.
421                    n -= count;
422                    result.push_span(*span);
423                } else {
424                    // Part of the span is the last to be taken.
425                    debug_assert!(n > 0);
426                    debug_assert!(n < count);
427                    let low = span.high - (n - 1);
428                    n = 0;
429                    result.push_span((low..=span.high).into());
430                }
431            }
432        }
433        #[cfg(test)]
434        assert_eq!(result.count(), expected);
435        result
436    }
437
438    /// Calculates the union of two sets.
439    pub fn union(&self, rhs: &IdSet) -> IdSet {
440        let mut spans = VecDeque::with_capacity((self.spans.len() + rhs.spans.len()).min(32));
441        let mut iter_left = self.spans.iter().cloned();
442        let mut iter_right = rhs.spans.iter().cloned();
443        let mut next_left = iter_left.next();
444        let mut next_right = iter_right.next();
445        let mut push = |span: Span| push_with_union(&mut spans, span);
446
447        loop {
448            match (next_left, next_right) {
449                (Some(left), Some(right)) => {
450                    if left.high < right.high {
451                        push(right);
452                        next_right = iter_right.next();
453                    } else {
454                        push(left);
455                        next_left = iter_left.next();
456                    }
457                }
458                (Some(span), None) => {
459                    push(span);
460                    next_left = iter_left.next();
461                }
462                (None, Some(span)) => {
463                    push(span);
464                    next_right = iter_right.next();
465                }
466                (None, None) => {
467                    let result = IdSet { spans };
468                    #[cfg(debug_assertions)]
469                    result.validate();
470                    return result;
471                }
472            }
473        }
474    }
475
476    /// Calculates the intersection of two sets.
477    pub fn intersection(&self, rhs: &IdSet) -> IdSet {
478        let mut spans = VecDeque::with_capacity(self.spans.len().max(rhs.spans.len()).min(32));
479        let push = |span: Span| push_with_union(&mut spans, span);
480        intersect_iter(self.spans.iter().cloned(), rhs.spans.iter().cloned(), push);
481
482        let result = IdSet { spans };
483        #[cfg(debug_assertions)]
484        result.validate();
485        result
486    }
487
488    /// Calculates spans that are included only by this set, not `rhs`.
489    pub fn difference(&self, rhs: &IdSet) -> IdSet {
490        let mut spans = VecDeque::with_capacity(self.spans.len().max(rhs.spans.len()).min(32));
491        let mut iter_left = self.spans.iter().cloned();
492        let mut iter_right = rhs.spans.iter().cloned();
493        let mut next_left = iter_left.next();
494        let mut next_right = iter_right.next();
495        let mut push = |span: Span| push_with_union(&mut spans, span);
496
497        loop {
498            match (next_left, next_right) {
499                (Some(left), Some(right)) => {
500                    if right.low > left.high {
501                        next_right = iter_right.next();
502                    } else {
503                        next_left = if right.high < left.low {
504                            push(left);
505                            iter_left.next()
506                        } else {
507                            // |----------------- left ------------------|
508                            // |--- span1 ---|--- right ---|--- span2 ---|
509                            if let Some(span2) = Span::try_from_bounds(right.high + 1..=left.high) {
510                                push(span2);
511                            }
512
513                            Span::try_from_bounds(left.low..right.low).or_else(|| iter_left.next())
514                        };
515                    }
516                }
517                (Some(left), None) => {
518                    push(left);
519                    next_left = iter_left.next();
520                }
521                (None, _) => {
522                    let result = IdSet { spans };
523                    #[cfg(debug_assertions)]
524                    result.validate();
525                    return result;
526                }
527            }
528        }
529    }
530
531    /// Iterate `Id`s in descending order.
532    pub fn iter_desc(&self) -> IdSetIter<&IdSet> {
533        let len = self.spans.len();
534        let back = (
535            len as isize - 1,
536            if len == 0 {
537                0
538            } else {
539                let span = self.spans[len - 1];
540                span.high.0 - span.low.0
541            },
542        );
543        IdSetIter {
544            span_set: self,
545            front: (0, 0),
546            back,
547        }
548    }
549
550    /// Iterate `Id`s in ascending order.
551    pub fn iter_asc(&self) -> Rev<IdSetIter<&Self>> {
552        self.iter_desc().rev()
553    }
554
555    /// Iterate `Span`s in descending order.
556    pub fn iter_span_desc(&self) -> impl Iterator<Item = &Span> {
557        self.as_spans().iter()
558    }
559
560    /// Iterate `Span`s in ascending order.
561    pub fn iter_span_asc(&self) -> impl Iterator<Item = &Span> {
562        self.as_spans().iter().rev()
563    }
564
565    /// Get the maximum id in this set.
566    pub fn max(&self) -> Option<Id> {
567        self.spans.front().map(|span| span.high)
568    }
569
570    /// Get the minimal id in this set.
571    pub fn min(&self) -> Option<Id> {
572        self.spans
573            .get(self.spans.len().max(1) - 1)
574            .map(|span| span.low)
575    }
576
577    /// Internal use only. Append a span, which must have lower boundaries
578    /// than existing spans.
579    pub(crate) fn push_span(&mut self, span: Span) {
580        push_with_union(&mut self.spans, span);
581    }
582
583    /// Internal use only. Append a span, which must have high boundaries
584    /// than existing spans. In other words, spans passed to this function
585    /// should be in ascending order.
586    pub(crate) fn push_span_asc(&mut self, span: Span) {
587        if self.spans.is_empty() {
588            self.spans.push_back(span);
589        } else {
590            let last = &mut self.spans[0];
591            // | last |
592            //     | span |  | span |
593            debug_assert!(span.low >= last.low);
594            if last.high + 1 >= span.low {
595                // Update in-place.
596                last.high = span.high.max(last.high);
597            } else {
598                self.spans.push_front(span);
599            }
600        }
601    }
602
603    /// Internal use only. Append a [`IdSet`], which must have lower
604    /// boundaries than the existing spans.
605    ///
606    /// This is faster than [`IdSet::union`]. used when it's known
607    /// that the all ids in `set` being added is below the minimal id
608    /// in the `self` set.
609    pub(crate) fn push_set(&mut self, set: &IdSet) {
610        for span in &set.spans {
611            self.push_span(*span);
612        }
613    }
614
615    /// Get a reference to the spans.
616    pub fn as_spans(&self) -> &VecDeque<Span> {
617        &self.spans
618    }
619
620    /// Make this [`IdSet`] contain the specified `span`.
621    ///
622    /// The current implementation works best when spans are pushed in
623    /// ascending or descending order.
624    pub fn push(&mut self, span: impl Into<Span>) {
625        let span = span.into();
626        if self.spans.is_empty() {
627            self.spans.push_back(span)
628        } else {
629            let len = self.spans.len();
630            {
631                // Fast path: pushing to the last span.
632                // 30->22 20->12 last H->L
633                //               span H------>L union [Case 1]
634                //                         H->L new   [Case 2]
635                let last = &mut self.spans[len - 1];
636                if last.high >= span.high {
637                    if last.low <= span.high + 1 {
638                        // Union spans in-place [Case 1]
639                        last.low = last.low.min(span.low);
640                    } else {
641                        // New back span [Case 2]
642                        self.spans.push_back(span)
643                    }
644                    return;
645                }
646            }
647            {
648                // Fast path: pushing to the last span.
649                // first      H->L  20->12 10->12
650                // span  H------>L union [Case 3]
651                //       H->L      new   [Case 4]
652                // Fast path: pushing to the first span.
653                let first = &mut self.spans[0];
654                if span.low >= first.low {
655                    if span.low <= first.high + 1 {
656                        // Union [Case 3]
657                        first.high = first.high.max(span.high);
658                    } else {
659                        // New front span [Case 4]
660                        self.spans.push_front(span);
661                    }
662                    return;
663                }
664            }
665            {
666                // Fast path: modify a span in-place.
667                // higher H1---->L1     cur H2---->L2     lower H3---->L3
668                // safe range        L1-2---------------->H3+2
669                // Exceeding the safe range would cause spans to overlap and this path cannot
670                // handle that.
671                let idx = match self
672                    .spans
673                    .bsearch_by(|probe| (span.high + 1).cmp(&probe.low))
674                {
675                    Ok(idx) => idx,
676                    Err(idx) => idx,
677                };
678                for idx in [idx] {
679                    if let Some(cur) = self.spans.get(idx) {
680                        // Not overlap with span?
681                        if span.high + 1 < cur.low || cur.high + 1 < span.low {
682                            continue;
683                        }
684                        // Might merge with a higher span? (Not in safe range)
685                        if idx > 0 {
686                            if let Some(higher) = self.spans.get(idx - 1) {
687                                if span.high + 1 >= higher.low {
688                                    continue;
689                                }
690                            }
691                        }
692                        // Might merge with a lower span? (Not in safe range)
693                        if let Some(lower) = self.spans.get(idx + 1) {
694                            if lower.high + 1 >= span.low {
695                                continue;
696                            }
697                        }
698                        // Passed all checks. Merge the span.
699                        let cur = &mut self.spans[idx];
700                        cur.high = cur.high.max(span.high);
701                        cur.low = cur.low.min(span.low);
702                        return;
703                    }
704                }
705            }
706            {
707                // PERF: There might be a better way to do this by bisecting
708                // spans and insert or delete in-place.  For now, this code
709                // path remains not optimized since it is rarely used.
710                *self = self.union(&IdSet::from(span))
711            }
712        }
713    }
714
715    /// Intersection with a span. Return the min Id.
716    ///
717    /// This is not a general purpose API, but useful for internal logic
718    /// like DAG descendant calculation.
719    pub(crate) fn intersection_span_min(&self, rhs: Span) -> Option<Id> {
720        let i = match self.spans.bsearch_by(|probe| rhs.low.cmp(&probe.high)) {
721            Ok(idx) => idx,
722            Err(idx) => idx.max(1) - 1,
723        };
724        // Prefer small index so we get the span that might overlap:
725        // |----spans[1]----|      |----spans[0]----|
726        //                     |----rhs-----|
727        //                     (want spans[0], not spans[1])
728        if i < self.spans.len() {
729            let lhs = self.spans[i];
730            if lhs.low <= rhs.high && lhs.high >= rhs.low {
731                Some(lhs.low.max(rhs.low))
732            } else {
733                None
734            }
735        } else {
736            // Happens if the set is empty.
737            None
738        }
739    }
740}
741
742/// Push a span to `VecDeque<Span>`. Try to union them in-place.
743fn push_with_union(spans: &mut VecDeque<Span>, span: Span) {
744    if spans.is_empty() {
745        spans.push_back(span);
746    } else {
747        let len = spans.len();
748        let last = &mut spans[len - 1];
749        debug_assert!(last.high >= span.high);
750        if last.low <= span.high + 1 {
751            // Union spans in-place.
752            last.low = last.low.min(span.low);
753        } else {
754            spans.push_back(span)
755        }
756    }
757}
758
759impl Debug for IdSet {
760    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
761        // Limit spans to show.
762        let limit = f.width().unwrap_or(12);
763        let mut ranges: Vec<String> = self
764            .spans
765            .iter()
766            .rev()
767            .take(limit)
768            .flat_map(|s| {
769                if s.low + 2 >= s.high {
770                    // "low..=high" form is not shorter.
771                    (s.low.to(s.high)).map(|i| format!("{}", i)).collect()
772                } else {
773                    vec![format!("{}..={}", s.low, s.high)]
774                }
775            })
776            .collect();
777        let total = self.spans.len();
778        if total == limit + 1 {
779            ranges.push("and 1 span".into());
780        } else if total > limit {
781            ranges.push(format!("and {} spans", total - limit));
782        }
783        write!(f, "{}", ranges.join(" "))
784    }
785}
786
787/// Similar to `Span` but the iteration order is defined by `start` (inclusive) and `end`
788/// (inclusive), not hardcoded DESC. `start` might be larger or smaller than `end`.
789#[derive(Clone, Copy, Debug)]
790pub struct OrderedSpan {
791    pub start: Id,
792    pub end: Id,
793}
794
795impl OrderedSpan {
796    /// Number of `Id`s in the span. Must >= 1.
797    pub fn count(&self) -> u64 {
798        self.start.0.abs_diff(self.end.0) + 1
799    }
800
801    pub fn min(&self) -> Id {
802        self.start.min(self.end)
803    }
804
805    pub fn max(&self) -> Id {
806        self.start.max(self.end)
807    }
808
809    fn nth(&self, n: u64) -> Option<Id> {
810        if self.start <= self.end {
811            let id = self.start + n;
812            if id > self.end { None } else { Some(id) }
813        } else {
814            let id = self.start - n;
815            if id < self.end { None } else { Some(id) }
816        }
817    }
818
819    fn skip(&self, n: u64) -> Option<Self> {
820        if n >= self.count() {
821            None
822        } else if self.start <= self.end {
823            Some(Self {
824                start: self.start + n,
825                end: self.end,
826            })
827        } else {
828            Some(Self {
829                start: self.start - n,
830                end: self.end,
831            })
832        }
833    }
834
835    fn take(&self, n: u64) -> Option<Self> {
836        if n == 0 {
837            None
838        } else if n >= self.count() {
839            Some(*self)
840        } else if self.start <= self.end {
841            Some(Self {
842                start: self.start,
843                end: self.start + n - 1,
844            })
845        } else {
846            Some(Self {
847                start: self.start,
848                end: self.start + 1 - n,
849            })
850        }
851    }
852
853    /// Attempt to push an `Id` to the current span and preserve iteration order.
854    /// For example, `OrderedSpan { start: 10, end: 20 }.push(21)` produces
855    /// `OrderedSpan { start: 10, end: 21 }`.
856    fn maybe_push(&self, id: Id) -> Option<Self> {
857        if id.group() == self.start.group()
858            && ((self.start <= self.end && id == self.end + 1)
859                || (self.start >= self.end && id + 1 == self.end))
860        {
861            Some(Self {
862                start: self.start,
863                end: id,
864            })
865        } else {
866            None
867        }
868    }
869
870    /// Attempt to push another [`OrderedSpan`] and preserve iteration order.
871    /// For example,
872    /// `OrderedSpan { start: 10, end: 20 }.push(OrderedSpan { start : 21, end: 30 })`
873    /// produces `OrderedSpan { start: 10, end: 30 }`.
874    fn maybe_push_span(&self, span: Self) -> Option<Self> {
875        if span.start.group() == self.start.group()
876            && ((self.start <= self.end && span.start == self.end + 1 && span.start <= span.end)
877                || (self.start >= self.end && span.start + 1 == self.end && span.start >= span.end))
878        {
879            Some(Self {
880                start: self.start,
881                end: span.end,
882            })
883        } else {
884            None
885        }
886    }
887}
888
889/// Used by [`IdSetIter`] for more flexible iteration.
890pub trait IndexSpan {
891    /// Get the span (start, end).
892    /// The iteration starts from `start` (inclusive) and ends at `end` (inclusive).
893    fn get_span(&self, index: usize) -> OrderedSpan;
894}
895
896impl IndexSpan for IdSet {
897    fn get_span(&self, index: usize) -> OrderedSpan {
898        let Span { low, high } = self.spans[index];
899        // Iterate from `high` to `low` by default.
900        OrderedSpan {
901            start: high,
902            end: low,
903        }
904    }
905}
906
907impl IndexSpan for &IdSet {
908    fn get_span(&self, index: usize) -> OrderedSpan {
909        <IdSet as IndexSpan>::get_span(self, index)
910    }
911}
912
913/// Iterator of integers in a [`IdSet`].
914#[derive(Clone)]
915pub struct IdSetIter<T> {
916    span_set: T,
917    // (index of span_set.spans, index of span_set.spans[i])
918    front: (isize, u64),
919    back: (isize, u64),
920}
921
922impl<T: IndexSpan> IdSetIter<T> {
923    fn count_remaining(&self) -> u64 {
924        let mut front = self.front;
925        let back = self.back;
926        let mut count = 0;
927        while front <= back {
928            let (vec_id, span_id) = front;
929            let (back_vec_id, back_span_id) = back;
930            if vec_id < back_vec_id {
931                let span = self.span_set.get_span(vec_id as usize);
932                count += span.count().saturating_sub(span_id);
933                front = (vec_id + 1, 0);
934            } else {
935                count += back_span_id - span_id + 1;
936                front = (vec_id + 1, 0);
937            }
938        }
939        count
940    }
941}
942
943impl<T: IndexSpan> Iterator for IdSetIter<T> {
944    type Item = Id;
945
946    fn next(&mut self) -> Option<Id> {
947        if self.front > self.back {
948            #[cfg(test)]
949            assert_eq!(self.size_hint().0, 0);
950            None
951        } else {
952            #[cfg(test)]
953            let old_size = self.size_hint().0;
954            let (vec_id, span_id) = self.front;
955            let span = self.span_set.get_span(vec_id as usize);
956            self.front = if span_id + 1 == span.count() {
957                (vec_id + 1, 0)
958            } else {
959                (vec_id, span_id + 1)
960            };
961            #[cfg(test)]
962            assert_eq!(self.size_hint().0 + 1, old_size);
963            span.nth(span_id)
964        }
965    }
966
967    fn nth(&mut self, n: usize) -> Option<Self::Item> {
968        #[cfg(test)]
969        let expected_size = self.size_hint().0.max(n + 1) - n - 1;
970        let mut n = n as u64;
971        while self.front <= self.back {
972            let (vec_id, span_id) = self.front;
973            let span = self.span_set.get_span(vec_id as usize);
974            let span_remaining = span.count() - span_id;
975            if n >= span_remaining {
976                n -= span_remaining;
977                self.front = (vec_id + 1, 0)
978            } else {
979                let span_id = span_id + n;
980                self.front = (vec_id, span_id);
981                let result = self.next();
982                #[cfg(test)]
983                assert_eq!(self.size_hint().0, expected_size);
984                return result;
985            };
986        }
987        None
988    }
989
990    fn size_hint(&self) -> (usize, Option<usize>) {
991        let size = self.count_remaining() as _;
992        (size, Some(size))
993    }
994
995    fn count(self) -> usize {
996        self.count_remaining() as _
997    }
998
999    fn last(mut self) -> Option<Self::Item> {
1000        self.next_back()
1001    }
1002}
1003
1004impl<T: IndexSpan> DoubleEndedIterator for IdSetIter<T> {
1005    fn next_back(&mut self) -> Option<Id> {
1006        if self.front > self.back {
1007            #[cfg(test)]
1008            assert_eq!(self.size_hint().0, 0);
1009            None
1010        } else {
1011            #[cfg(test)]
1012            let old_size = self.size_hint().0;
1013            let (vec_id, span_id) = self.back;
1014            let span = self.span_set.get_span(vec_id as usize);
1015            self.back = if span_id == 0 {
1016                let span_len = if vec_id > 0 {
1017                    let span = self.span_set.get_span((vec_id - 1) as usize);
1018                    span.count() - 1
1019                } else {
1020                    0
1021                };
1022                (vec_id - 1, span_len)
1023            } else {
1024                (vec_id, span_id - 1)
1025            };
1026            #[cfg(test)]
1027            assert_eq!(self.size_hint().0 + 1, old_size);
1028            span.nth(span_id)
1029        }
1030    }
1031
1032    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1033        #[cfg(test)]
1034        let expected_size = self.size_hint().0.max(n + 1) - n - 1;
1035        let mut n = n as u64;
1036        while self.front <= self.back {
1037            let (vec_id, span_id) = self.back;
1038            let span = self.span_set.get_span(vec_id as usize);
1039            let span_remaining = span_id + 1;
1040            if n >= span_remaining {
1041                n -= span_remaining;
1042                let span_end = if vec_id > 0 {
1043                    self.span_set.get_span((vec_id - 1) as usize).count() - 1
1044                } else {
1045                    0
1046                };
1047                self.back = (vec_id - 1, span_end);
1048            } else {
1049                let span_id = span_id - n;
1050                self.back = (vec_id, span_id);
1051                let result = if self.front <= self.back {
1052                    if span_id == 0 {
1053                        let span_end = if vec_id > 0 {
1054                            self.span_set.get_span((vec_id - 1) as usize).count() - 1
1055                        } else {
1056                            0
1057                        };
1058                        self.back = (vec_id - 1, span_end);
1059                    } else {
1060                        self.back.1 -= 1;
1061                    }
1062                    span.nth(span_id)
1063                } else {
1064                    None
1065                };
1066                #[cfg(test)]
1067                assert_eq!(self.size_hint().0, expected_size);
1068                return result;
1069            }
1070        }
1071        None
1072    }
1073}
1074
1075impl<T: IndexSpan> ExactSizeIterator for IdSetIter<T> {
1076    fn len(&self) -> usize {
1077        self.count_remaining() as _
1078    }
1079}
1080
1081impl IntoIterator for IdSet {
1082    type Item = Id;
1083    type IntoIter = IdSetIter<IdSet>;
1084
1085    /// Get an iterator for integers in this [`IdSet`].
1086    fn into_iter(self) -> IdSetIter<IdSet> {
1087        let len = self.spans.len();
1088        let back = (
1089            len as isize - 1,
1090            if len == 0 {
1091                0
1092            } else {
1093                let span = self.spans[len - 1];
1094                span.high.0 - span.low.0
1095            },
1096        );
1097        IdSetIter {
1098            span_set: self,
1099            front: (0, 0),
1100            back,
1101        }
1102    }
1103}
1104
1105/// Mainly for iteration (skip, take, count, into_iter) handling.
1106#[derive(Clone, Debug)]
1107pub struct IdList(Arc<Vec<OrderedSpan>>);
1108
1109impl IdList {
1110    /// Creates `IdList`. Preserves `ids` iteration order.
1111    pub fn from_ids<I: Into<Id>>(ids: impl IntoIterator<Item = I>) -> Self {
1112        let mut list = Vec::new();
1113        let mut span = None;
1114        for id in ids {
1115            let id = id.into();
1116            span = match span {
1117                None => Some(OrderedSpan { start: id, end: id }),
1118                Some(current) => match current.maybe_push(id) {
1119                    Some(next) => Some(next),
1120                    None => {
1121                        list.push(current);
1122                        Some(OrderedSpan { start: id, end: id })
1123                    }
1124                },
1125            }
1126        }
1127        if let Some(span) = span.take() {
1128            list.push(span)
1129        }
1130        Self(Arc::new(list))
1131    }
1132
1133    /// Creates `IdList`. Preserves `ids` iteration order.
1134    pub fn from_spans<S: Into<OrderedSpan>>(spans: impl IntoIterator<Item = S>) -> Self {
1135        let mut list = Vec::new();
1136        let mut span = None;
1137        for s in spans {
1138            let s = s.into();
1139            span = match span {
1140                None => Some(s),
1141                Some(current) => match current.maybe_push_span(s) {
1142                    Some(next) => Some(next),
1143                    None => {
1144                        list.push(current);
1145                        Some(s)
1146                    }
1147                },
1148            }
1149        }
1150        if let Some(span) = span.take() {
1151            list.push(span)
1152        }
1153        Self(Arc::new(list))
1154    }
1155
1156    /// Count all `Id`s in the list.
1157    pub fn count(&self) -> u64 {
1158        self.0.iter().map(|i| i.count()).sum()
1159    }
1160
1161    /// Skip the first `n` items.
1162    pub fn skip(&self, mut n: u64) -> Self {
1163        #[cfg(test)]
1164        let expected = self.count().saturating_sub(n);
1165        let mut result = Vec::new();
1166        for span in self.0.as_ref() {
1167            if n == 0 {
1168                result.push(*span);
1169            } else {
1170                let count = span.count();
1171                if count <= n {
1172                    // This span is skipped entirely.
1173                    n -= count;
1174                } else {
1175                    // This span is skipped partially.
1176                    debug_assert!(n > 0);
1177                    debug_assert!(n < count);
1178                    if let Some(span) = span.skip(n) {
1179                        result.push(span)
1180                    }
1181                    n = 0;
1182                }
1183            }
1184        }
1185        let result = Self(Arc::new(result));
1186        #[cfg(test)]
1187        assert_eq!(result.count(), expected);
1188        result
1189    }
1190
1191    /// Only take the first `n` items.
1192    pub fn take(&self, mut n: u64) -> Self {
1193        #[cfg(test)]
1194        let expected = n.min(self.count());
1195        let mut result = Vec::new();
1196        for span in self.0.as_ref() {
1197            if n == 0 {
1198                break;
1199            } else {
1200                let count = span.count();
1201                if count <= n {
1202                    // This span is taken entirely.
1203                    n -= count;
1204                    result.push(*span);
1205                } else {
1206                    // Part of the span is the last to be taken.
1207                    debug_assert!(n > 0);
1208                    debug_assert!(n < count);
1209                    if let Some(span) = span.take(n) {
1210                        result.push(span)
1211                    }
1212                    n = 0;
1213                }
1214            }
1215        }
1216        let result = Self(Arc::new(result));
1217        #[cfg(test)]
1218        assert_eq!(result.count(), expected);
1219        result
1220    }
1221
1222    /// Convert to `IdSet`.
1223    pub fn to_set(&self) -> IdSet {
1224        let spans = self.0.iter().map(|OrderedSpan { start, end }| {
1225            let (low, high) = if start <= end {
1226                (*start, *end)
1227            } else {
1228                (*end, *start)
1229            };
1230            Span::new(low, high)
1231        });
1232        IdSet::from_spans(spans)
1233    }
1234
1235    /// Access `OrderedSpan` directly. This can be useful to figure out if the
1236    /// spans are in a particular order.
1237    pub fn as_spans(&self) -> &[OrderedSpan] {
1238        &self.0
1239    }
1240}
1241
1242impl IndexSpan for Arc<Vec<OrderedSpan>> {
1243    fn get_span(&self, index: usize) -> OrderedSpan {
1244        self[index]
1245    }
1246}
1247
1248impl IntoIterator for &IdList {
1249    type Item = Id;
1250    type IntoIter = IdSetIter<Arc<Vec<OrderedSpan>>>;
1251
1252    fn into_iter(self) -> Self::IntoIter {
1253        let len = self.0.len();
1254        let back = (
1255            len as isize - 1,
1256            if len == 0 {
1257                0
1258            } else {
1259                self.0[len - 1].count() - 1
1260            },
1261        );
1262        IdSetIter {
1263            span_set: self.0.clone(),
1264            front: (0, 0),
1265            back,
1266        }
1267    }
1268}
1269
1270// `#[serde(transparent)]` on the `Id` struct.
1271// This would be easier if `Id` has `#[serde(transparent)]`.
1272// But that might be a breaking change now...
1273mod flat_id {
1274    use serde::de;
1275    use serde::de::Visitor;
1276    use serde::Deserializer;
1277    use serde::Serializer;
1278
1279    use super::*;
1280
1281    pub fn serialize<S: Serializer>(id: &Id, serializer: S) -> Result<S::Ok, S::Error> {
1282        serializer.serialize_u64(id.0)
1283    }
1284
1285    pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Id, D::Error> {
1286        struct IdVisitor;
1287        impl<'de> Visitor<'de> for IdVisitor {
1288            type Value = Id;
1289            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1290                formatter.write_str("u64")
1291            }
1292            fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
1293                Ok(Id(value))
1294            }
1295        }
1296        deserializer.deserialize_u64(IdVisitor)
1297    }
1298}
1299
1300#[cfg(test)]
1301#[allow(clippy::redundant_clone)]
1302mod tests {
1303    use std::collections::HashSet;
1304
1305    use quickcheck::quickcheck;
1306
1307    use super::*;
1308    use crate::tests::dbg;
1309    use crate::tests::nid;
1310
1311    impl From<RangeInclusive<u64>> for Span {
1312        fn from(range: RangeInclusive<u64>) -> Span {
1313            Span::new(Id(*range.start()), Id(*range.end()))
1314        }
1315    }
1316
1317    impl From<u64> for Span {
1318        fn from(id: u64) -> Span {
1319            let id = Id(id);
1320            Span::new(id, id)
1321        }
1322    }
1323
1324    impl From<(u64, u64)> for IdSet {
1325        fn from(ids: (u64, u64)) -> IdSet {
1326            IdSet::from_spans([ids.0, ids.1].iter().cloned().map(Id))
1327        }
1328    }
1329
1330    impl From<Span> for RangeInclusive<u64> {
1331        fn from(span: Span) -> RangeInclusive<u64> {
1332            span.low.0..=span.high.0
1333        }
1334    }
1335
1336    #[test]
1337    fn test_overlapped_spans() {
1338        let span = IdSet::from_spans(vec![1..=3, 3..=4]);
1339        assert_eq!(span.as_spans(), &[Span::from(1..=4)]);
1340    }
1341
1342    #[test]
1343    fn test_valid_spans() {
1344        IdSet::empty();
1345        IdSet::from_spans(vec![4..=4, 3..=3, 1..=2]);
1346    }
1347
1348    #[test]
1349    fn test_from_sorted_spans_merge() {
1350        let s = IdSet::from_sorted_spans(vec![4..=4, 3..=3, 1..=2]);
1351        assert_eq!(dbg(s), "1..=4");
1352    }
1353
1354    #[test]
1355    fn test_count() {
1356        let set = IdSet::empty();
1357        assert_eq!(set.count(), 0);
1358
1359        let set = IdSet::from_spans(vec![1..=10, 20..=20, 31..=40]);
1360        assert_eq!(set.count(), 10 + 1 + 10);
1361    }
1362
1363    #[test]
1364    fn test_skip() {
1365        let set = IdSet::from_spans(vec![1..=10, 20..=20, 31..=40]);
1366        let skip = |n| dbg(set.skip(n));
1367        assert_eq!(skip(0), "1..=10 20 31..=40");
1368        assert_eq!(skip(1), "1..=10 20 31..=39");
1369        assert_eq!(skip(9), "1..=10 20 31");
1370        assert_eq!(skip(10), "1..=10 20");
1371        assert_eq!(skip(11), "1..=10");
1372        assert_eq!(skip(12), "1..=9");
1373        assert_eq!(skip(20), "1");
1374        assert_eq!(skip(21), "");
1375        assert_eq!(skip(22), "");
1376        assert_eq!(skip(50), "");
1377    }
1378
1379    #[test]
1380    fn test_take() {
1381        let set = IdSet::from_spans(vec![1..=10, 20..=20, 31..=40]);
1382        let take = |n| dbg(set.take(n));
1383        assert_eq!(take(0), "");
1384        assert_eq!(take(1), "40");
1385        assert_eq!(take(9), "32..=40");
1386        assert_eq!(take(10), "31..=40");
1387        assert_eq!(take(11), "20 31..=40");
1388        assert_eq!(take(12), "10 20 31..=40");
1389        assert_eq!(take(20), "2..=10 20 31..=40");
1390        assert_eq!(take(21), "1..=10 20 31..=40");
1391        assert_eq!(take(22), "1..=10 20 31..=40");
1392        assert_eq!(take(50), "1..=10 20 31..=40");
1393    }
1394
1395    #[test]
1396    fn test_contains() {
1397        let set = IdSet::empty();
1398        assert!(!set.contains(0));
1399        assert!(!set.contains(10));
1400
1401        let set = IdSet::from_spans(vec![1..=1, 2..=9, 10..=10, 20..=20, 31..=35, 36..=40]);
1402        assert!(!set.contains(0));
1403        assert!(set.contains(1));
1404        assert!(set.contains(5));
1405        assert!(set.contains(10));
1406        assert!(!set.contains(11));
1407
1408        assert!(set.contains(1..=10));
1409        assert!(set.contains(1..=8));
1410        assert!(set.contains(3..=10));
1411        assert!(set.contains(3..=7));
1412        assert!(!set.contains(1..=11));
1413        assert!(!set.contains(0..=10));
1414
1415        assert!(!set.contains(19));
1416        assert!(!set.contains(19..=20));
1417        assert!(set.contains(20));
1418        assert!(!set.contains(20..=21));
1419        assert!(!set.contains(21));
1420
1421        assert!(!set.contains(30));
1422        assert!(set.contains(31));
1423        assert!(set.contains(32));
1424        assert!(set.contains(39));
1425        assert!(set.contains(40));
1426        assert!(!set.contains(41));
1427
1428        assert!(set.contains(31..=40));
1429        assert!(set.contains(32..=40));
1430        assert!(set.contains(31..=39));
1431        assert!(set.contains(31..=39));
1432        assert!(!set.contains(31..=41));
1433        assert!(!set.contains(30..=40));
1434        assert!(!set.contains(30..=41));
1435    }
1436
1437    fn union(a: Vec<impl Into<Span>>, b: Vec<impl Into<Span>>) -> Vec<RangeInclusive<u64>> {
1438        let a = IdSet::from_spans(a);
1439        let b = IdSet::from_spans(b);
1440        let spans1 = a.union(&b).spans;
1441        let spans2 = b.union(&a).spans;
1442        assert_eq!(spans1, spans2);
1443        spans1.into_iter().map(|span| span.into()).collect()
1444    }
1445
1446    #[test]
1447    fn test_union() {
1448        assert_eq!(union(vec![1..=10], vec![10..=20]), vec![1..=20]);
1449        assert_eq!(union(vec![1..=30], vec![10..=20]), vec![1..=30]);
1450        assert_eq!(union(vec![6, 8, 10], vec![5, 7, 9]), vec![5..=10]);
1451        assert_eq!(
1452            union(vec![6..=6, 8..=9, 10..=10], vec![5]),
1453            vec![8..=10, 5..=6]
1454        );
1455    }
1456
1457    fn intersect(a: Vec<impl Into<Span>>, b: Vec<impl Into<Span>>) -> Vec<RangeInclusive<u64>> {
1458        let a = IdSet::from_spans(a);
1459        let b = IdSet::from_spans(b);
1460        let spans1 = a.intersection(&b).spans;
1461        let spans2 = b.intersection(&a).spans;
1462        assert_eq!(spans1, spans2);
1463        spans1.into_iter().map(|span| span.into()).collect()
1464    }
1465
1466    #[test]
1467    fn test_intersection() {
1468        assert_eq!(intersect(vec![1..=10], vec![11..=20]), vec![]);
1469        assert_eq!(intersect(vec![1..=10], vec![10..=20]), vec![10..=10]);
1470        assert_eq!(intersect(vec![1..=30], vec![10..=20]), vec![10..=20]);
1471        assert_eq!(
1472            intersect(vec![0..=10, 15..=20], vec![0..=30]),
1473            vec![15..=20, 0..=10]
1474        );
1475        assert_eq!(
1476            intersect(vec![0..=10, 15..=20], vec![5..=19]),
1477            vec![15..=19, 5..=10]
1478        );
1479        assert_eq!(intersect(vec![10, 9, 8, 7], vec![8..=11]), vec![8..=10]);
1480        assert_eq!(intersect(vec![10, 9, 8, 7], vec![5..=8]), vec![7..=8]);
1481    }
1482
1483    fn difference(a: Vec<impl Into<Span>>, b: Vec<impl Into<Span>>) -> Vec<RangeInclusive<u64>> {
1484        let a = IdSet::from_spans(a);
1485        let b = IdSet::from_spans(b);
1486        let spans1 = a.difference(&b).spans;
1487        let spans2 = b.difference(&a).spans;
1488
1489        // |------------- a -------------------|
1490        // |--- spans1 ---|--- intersection ---|--- spans2 ---|
1491        //                |------------------- b -------------|
1492        let intersected = intersect(
1493            a.spans.iter().cloned().collect(),
1494            b.spans.iter().cloned().collect(),
1495        );
1496        let unioned = union(
1497            a.spans.iter().cloned().collect(),
1498            b.spans.iter().cloned().collect(),
1499        );
1500        assert_eq!(
1501            union(intersected.clone(), spans1.iter().cloned().collect()),
1502            union(a.spans.iter().cloned().collect(), Vec::<Span>::new())
1503        );
1504        assert_eq!(
1505            union(intersected.clone(), spans2.iter().cloned().collect()),
1506            union(b.spans.iter().cloned().collect(), Vec::<Span>::new())
1507        );
1508        assert_eq!(
1509            union(
1510                spans1.iter().cloned().collect(),
1511                union(intersected.clone(), spans2.iter().cloned().collect())
1512            ),
1513            unioned.clone(),
1514        );
1515
1516        assert!(
1517            intersect(
1518                spans1.iter().cloned().collect(),
1519                spans2.iter().cloned().collect()
1520            )
1521            .is_empty()
1522        );
1523        assert!(intersect(spans1.iter().cloned().collect(), intersected.clone()).is_empty());
1524        assert!(intersect(spans2.iter().cloned().collect(), intersected.clone()).is_empty());
1525
1526        spans1.into_iter().map(|span| span.into()).collect()
1527    }
1528
1529    #[test]
1530    fn test_difference() {
1531        assert_eq!(difference(vec![0..=5], Vec::<Span>::new()), vec![0..=5]);
1532        assert_eq!(difference(Vec::<Span>::new(), vec![0..=5]), vec![]);
1533        assert_eq!(difference(vec![0..=0], vec![1..=1]), vec![0..=0]);
1534        assert_eq!(difference(vec![0..=0], vec![0..=1]), vec![]);
1535        assert_eq!(difference(vec![0..=10], vec![0..=5]), vec![6..=10]);
1536
1537        assert_eq!(
1538            difference(vec![0..=10], vec![3..=4, 7..=8]),
1539            vec![9..=10, 5..=6, 0..=2]
1540        );
1541        assert_eq!(
1542            difference(vec![3..=4, 7..=8, 10..=12], vec![4..=11]),
1543            vec![12..=12, 3..=3]
1544        );
1545    }
1546
1547    #[test]
1548    fn test_iter() {
1549        let set = IdSet::empty();
1550        assert!(set.iter_desc().next().is_none());
1551        assert!(set.iter_desc().next_back().is_none());
1552        assert_eq!(set.iter_desc().size_hint(), (0, Some(0)));
1553
1554        let set = IdSet::from(0..=1);
1555        assert_eq!(set.iter_desc().collect::<Vec<Id>>(), vec![1, 0]);
1556        assert_eq!(set.iter_desc().rev().collect::<Vec<Id>>(), vec![0, 1]);
1557        assert_eq!(set.iter_desc().size_hint(), (2, Some(2)));
1558        assert_eq!(set.iter_desc().count(), 2);
1559
1560        let mut iter = set.iter_desc();
1561        assert!(iter.next().is_some());
1562        assert!(iter.next_back().is_some());
1563        assert!(iter.next_back().is_none());
1564
1565        let set = IdSet::from_spans(vec![3..=5, 7..=8]);
1566        assert_eq!(set.iter_desc().collect::<Vec<Id>>(), vec![8, 7, 5, 4, 3]);
1567        assert_eq!(
1568            set.iter_desc().rev().collect::<Vec<Id>>(),
1569            vec![3, 4, 5, 7, 8]
1570        );
1571        assert_eq!(set.iter_desc().size_hint(), (5, Some(5)));
1572        assert_eq!(set.iter_desc().last(), Some(Id(3)));
1573
1574        assert_eq!(
1575            set.clone().into_iter().collect::<Vec<Id>>(),
1576            vec![8, 7, 5, 4, 3]
1577        );
1578        assert_eq!(
1579            set.clone().into_iter().rev().collect::<Vec<Id>>(),
1580            vec![3, 4, 5, 7, 8]
1581        );
1582        assert_eq!(
1583            set.clone()
1584                .into_iter()
1585                .rev()
1586                .skip(1)
1587                .take(2)
1588                .rev()
1589                .collect::<Vec<Id>>(),
1590            vec![5, 4]
1591        );
1592
1593        let set = IdSet::from_spans(vec![3..=5, 7..=8]);
1594        let mut iter = set.iter_desc();
1595        assert_eq!(iter.next().unwrap(), 8);
1596        assert_eq!(iter.next_back().unwrap(), 3);
1597
1598        let mut iter2 = iter.clone();
1599        assert_eq!(iter.next().unwrap(), 7);
1600        assert_eq!(iter.next_back().unwrap(), 4);
1601        assert_eq!(iter2.next().unwrap(), 7);
1602        assert_eq!(iter2.next_back().unwrap(), 4);
1603    }
1604
1605    #[test]
1606    fn test_push() {
1607        let mut set = IdSet::from(10..=20);
1608        set.push(5..=15);
1609        assert_eq!(set.as_spans(), &vec![Span::from(5..=20)]);
1610
1611        let mut set = IdSet::from(10..=20);
1612        set.push(5..=9);
1613        assert_eq!(set.as_spans(), &vec![Span::from(5..=20)]);
1614
1615        let mut set = IdSet::from(10..=20);
1616        set.push(5..=8);
1617        assert_eq!(
1618            set.as_spans(),
1619            &vec![Span::from(10..=20), Span::from(5..=8)]
1620        );
1621
1622        let mut set = IdSet::from(10..=20);
1623        set.push(5..=30);
1624        assert_eq!(set.as_spans(), &vec![Span::from(5..=30)]);
1625
1626        let mut set = IdSet::from(10..=20);
1627        set.push(20..=30);
1628        assert_eq!(set.as_spans(), &vec![Span::from(10..=30)]);
1629
1630        let mut set = IdSet::from(10..=20);
1631        set.push(10..=20);
1632        assert_eq!(set.as_spans(), &vec![Span::from(10..=20)]);
1633
1634        let mut set = IdSet::from(10..=20);
1635        set.push(22..=30);
1636        assert_eq!(
1637            set.as_spans(),
1638            &vec![Span::from(22..=30), Span::from(10..=20)]
1639        );
1640    }
1641
1642    #[test]
1643    fn test_push_brute_force() {
1644        // Brute force pushing all spans in 1..=45 range to a IdSet.
1645        let set = IdSet::from_spans(vec![5..=10, 15..=16, 18..=20, 23..=23, 26..=30, 35..=40]);
1646        for low in 1..=45 {
1647            for high in low..=45 {
1648                let expected = IdSet::from_spans(
1649                    (1..=45)
1650                        .filter(|&i| (i >= low && i <= high) || set.contains(Id(i)))
1651                        .map(Id),
1652                );
1653                let mut set = set.clone();
1654                set.push(low..=high);
1655                assert_eq!(set.as_spans(), expected.as_spans());
1656            }
1657        }
1658    }
1659
1660    #[test]
1661    fn test_span_contains_brute_force() {
1662        let set = IdSet::from_spans(vec![5..=10, 15..=16, 18..=20, 23..=23, 26..=30, 35..=40]);
1663        for low in 1..=45 {
1664            for high in low..=45 {
1665                let span = Span::from(low..=high);
1666                let result1 = set.span_contains(span);
1667                let result2 = set
1668                    .as_spans()
1669                    .iter()
1670                    .find(|s| s.contains(Id(low)) && s.contains(Id(high)));
1671                assert_eq!(result1, result2);
1672            }
1673        }
1674    }
1675
1676    #[test]
1677    fn test_span_iter_nth() {
1678        let set = IdSet::from_spans(vec![5..=10, 15..=15, 18..=20, 23..=23, 26..=30, 35..=40]);
1679        let vec: Vec<Id> = set.iter_desc().collect();
1680        for n in 0..=(vec.len() + 2) {
1681            assert_eq!(set.iter_desc().nth(n), vec.get(n).cloned());
1682        }
1683    }
1684
1685    #[test]
1686    fn test_span_iter_nth_back() {
1687        let set = IdSet::from_spans(vec![5..=10, 15..=15, 18..=20, 23..=23, 26..=30, 35..=40]);
1688        let vec: Vec<Id> = set.iter_asc().collect();
1689        for n in 0..=(vec.len() + 2) {
1690            assert_eq!(set.iter_desc().nth_back(n), vec.get(n).cloned());
1691        }
1692    }
1693
1694    #[test]
1695    fn test_intersection_span_min() {
1696        let set = IdSet::from_spans(vec![1..=10, 11..=20, 30..=40]);
1697        assert_eq!(set.intersection_span_min((15..=45).into()), Some(Id(15)));
1698        assert_eq!(set.intersection_span_min((20..=32).into()), Some(Id(20)));
1699        assert_eq!(set.intersection_span_min((21..=29).into()), None);
1700        assert_eq!(set.intersection_span_min((21..=32).into()), Some(Id(30)));
1701        assert_eq!(set.intersection_span_min((35..=45).into()), Some(Id(35)));
1702        assert_eq!(set.intersection_span_min((45..=55).into()), None);
1703    }
1704
1705    #[test]
1706    fn test_debug() {
1707        let set = IdSet::from_spans(vec![1..=1, 2..=9, 10..=10, 20..=20, 31..=35, 36..=40]);
1708        assert_eq!(format!("{:10?}", &set), "1..=10 20 31..=40");
1709        assert_eq!(format!("{:3?}", &set), "1..=10 20 31..=40");
1710        assert_eq!(format!("{:2?}", &set), "1..=10 20 and 1 span");
1711        assert_eq!(format!("{:1?}", &set), "1..=10 and 2 spans");
1712    }
1713
1714    #[test]
1715    fn test_span_overlaps_with() {
1716        const N: u64 = 10;
1717        for span1_low in 0..N {
1718            for span1_high in span1_low..N {
1719                for span2_low in 0..N {
1720                    for span2_high in span2_low..N {
1721                        let span1 = Span::new(Id(span1_low), Id(span1_high));
1722                        let span2 = Span::new(Id(span2_low), Id(span2_high));
1723                        let overlap_naive = (span1_low..=span1_high)
1724                            .collect::<HashSet<_>>()
1725                            .intersection(&(span2_low..=span2_high).collect::<HashSet<_>>())
1726                            .count()
1727                            > 0;
1728                        assert_eq!(overlap_naive, span1.overlaps_with(&span2));
1729                    }
1730                }
1731            }
1732        }
1733    }
1734
1735    fn check_id_list_iter(ids: &[Id]) {
1736        let list = IdList::from_ids(ids.iter().copied());
1737        assert_eq!(list.into_iter().next(), ids.first().copied());
1738        assert_eq!(list.into_iter().next_back(), ids.last().copied());
1739        let iter = list.into_iter();
1740        assert_eq!(iter.size_hint(), (ids.len(), Some(ids.len())));
1741        assert_eq!(iter.collect::<Vec<Id>>(), ids.to_vec());
1742        let iter = list.into_iter();
1743        let mut rev_ids = ids.to_vec();
1744        rev_ids.reverse();
1745        assert_eq!(iter.rev().collect::<Vec<Id>>(), rev_ids);
1746        for i in 0..=ids.len().min(10) {
1747            let nth = list.into_iter().nth(i);
1748            assert_eq!(nth, ids.get(i).copied(), "{:?}.nth({})", ids, i);
1749        }
1750    }
1751
1752    #[test]
1753    fn test_id_list_iter() {
1754        check_id_list_iter(&[]);
1755        check_id_list_iter(&[
1756            Id(0),
1757            Id(1),
1758            Id(2),
1759            Id(5),
1760            Id(4),
1761            Id(3),
1762            nid(1),
1763            nid(2),
1764            nid(4),
1765            nid(3),
1766        ]);
1767    }
1768
1769    #[test]
1770    fn test_id_list_iter_quickcheck() {
1771        fn check(ids: Vec<u8>) -> bool {
1772            let ids = ids.into_iter().map(|i| Id(i as u64)).collect::<Vec<Id>>();
1773            check_id_list_iter(&ids);
1774            true
1775        }
1776        quickcheck(check as fn(Vec<u8>) -> bool);
1777    }
1778
1779    fn check_id_list_skip_take(list: &IdList, skip: u64, take: u64) {
1780        let sub_list = list.skip(skip);
1781        let sub_list = sub_list.take(take);
1782        let iter = list.into_iter();
1783        let ids = iter.skip(skip as _).take(take as _).collect::<Vec<_>>();
1784        assert_eq!(
1785            sub_list.into_iter().collect::<Vec<Id>>(),
1786            ids,
1787            "{:?}.skip({}).take({})",
1788            list,
1789            skip,
1790            take
1791        );
1792    }
1793
1794    #[test]
1795    fn test_id_list_skip_take() {
1796        for ids in [
1797            &[] as &[u64],
1798            &[1],
1799            &[1, 2, 3, 7, 6, 5],
1800            &[7, 6, 5, 1, 2, 3],
1801            &[11, 12, 22, 21, 31, 32],
1802            &[10, 30, 20, 50, 40],
1803        ] {
1804            let len = ids.len() as u64;
1805            let list = IdList::from_ids(ids.iter().map(|&i| Id(i)));
1806            for skip in 0..=len + 2 {
1807                for take in 0..=len + 2 {
1808                    check_id_list_skip_take(&list, skip, take)
1809                }
1810            }
1811        }
1812    }
1813
1814    #[test]
1815    fn test_id_list_skip_take_quickcheck() {
1816        fn check(ids: Vec<u8>, skip: u8, take: u8) -> bool {
1817            let list = IdList::from_ids(ids.into_iter().map(|i| Id(i as u64)));
1818            check_id_list_skip_take(&list, skip as _, take as _);
1819            true
1820        }
1821        quickcheck(check as fn(Vec<u8>, u8, u8) -> bool);
1822    }
1823
1824    #[test]
1825    fn test_id_list_to_id_set() {
1826        let list = IdList::from_ids([1, 3, 2, 4, 9, 8, 11, 12, 6, 10].iter().map(|i| Id(*i)));
1827        let set = list.to_set();
1828        assert_eq!(dbg(set), "1..=4 6 8..=12");
1829    }
1830
1831    #[test]
1832    fn test_id_list_from_spans() {
1833        let list = IdList::from_spans(
1834            [
1835                (10, 20),
1836                (21, 30),
1837                (90, 80),
1838                (79, 60),
1839                (51, 51),
1840                (50, 50),
1841                (55, 55),
1842                (56, 56),
1843            ]
1844            .iter()
1845            .map(|(a, b)| OrderedSpan {
1846                start: Id(*a),
1847                end: Id(*b),
1848            }),
1849        );
1850        assert_eq!(
1851            dbg(list.0),
1852            "[OrderedSpan { start: 10, end: 30 }, OrderedSpan { start: 90, end: 60 }, OrderedSpan { start: 51, end: 50 }, OrderedSpan { start: 55, end: 56 }]"
1853        );
1854    }
1855}