closed_interval_set/
lib.rs

1//! The `closed_interval_set` crate manipulates disjoint unions of
2//! closed intervals that are represented as vectors ([`RangeVec`]) or
3//! iterators ([`NormalizedRangeIter`]) of pairs of endpoints.  These
4//! intervals are always closed (inclusive at both ends), so the
5//! crate can naturally represent both the empty set (no interval),
6//! and the universe (a closed interval from min to max).
7//!
8//! The crate is designed for usage patterns where sets are
9//! constructed ahead of time (perhaps by combining different sets
10//! together), then frozen (as vectors, internally) for read-only
11//! access.  That said, its iterator implementations of set
12//! [complementation](`NormalizedRangeIter::complement`),
13//! [union](`NormalizedRangeIter::union`), and
14//! [intersection](`NormalizedRangeIter::intersect`) are closed over
15//! the [`NormalizedRangeIter`] trait, so it's reasonable to build up
16//! complex expressions of type-erased [`NormalizedRangeIter`]s
17//! before materializing the result to a [`RangeVec`].
18//!
19//! Using this crate usually starts by constructing [`Vec`]s of closed
20//! ranges (of pairs of [`Endpoint`]s), and passing that to
21//! [`RangeVec::from_vec`].  From that point, we have access to the
22//! set operations on [`RangeVec`] and [`NormalizedRangeIter`].  The
23//! toplevel functions (e.g., [`intersect_vec`] and [`normalize_vec`])
24//! may be helpful to avoid excessive chaining or in subtle
25//! situations, e.g., when the compiler knows whether the input is a
26//! [`RangeVec`] or a [`Vec`] (or [`SmallVec`]) but it's annoying to
27//! track by hand.
28//!
29//! Complementation is tricky when one handles only closed intervals.
30//! We assume [`Endpoint`] types can enumerate values in total order
31//! via [`Endpoint::decrease_toward`] and [`Endpoint::increase_toward`].
32//! That's nonsense for [densely ordered sets](https://en.wikipedia.org/wiki/Dense_order)
33//! like \\(\mathbb{Q},\\) but tends to work OK on computers: it's trivial
34//! to enumerate bounded integers, and there is such a total order for
35//! the finite set of floating point values.  Mathematically, this sorted
36//! enumeration of floating point values makes no sense, nevertheless,
37//! it can be useful in some domains, e.g., static program analysis.
38//!
39//! All operations take at most linear space and \\(\mathcal{O}(n \log
40//! n)\\) time, where \\(n\\) is the total number of ranges in all the
41//! inputs, before any normalization (simplification).  Set operations
42//! on [`NormalizedRangeIter`] always use constant space, and many
43//! operations on [`RangeVec`] reuse storage.
44//!
45//! The container type ([`SmallVec`]`<[_; 2]>`) is hardcoded, for
46//! simplicity.  The [`Endpoint`] trait, however, is fully generic.
47//! This crate comes with implementations of [`Endpoint`] for all
48//! primitive fixed-width integer types ([`i8`], [`i16`], [`i32`], [`i64`],
49//! [`i128`], [`u8`], [`u16`], [`u32`], [`u64`] and [`u128`]), for
50//! [`isize`] and [`usize`], and for the standard floating point
51//! types [`f32`] and [`f64`] (from \\(-\infty\\) to \\(+\infty\\),
52//! with \\(-0\\) and \\(+0\\) as distinct values, and excluding NaNs,
53//! in the same order as [`f32::total_cmp`] and [`f64::total_cmp`]).
54//!
55//! [`SmallVec`]: https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html
56//! [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
57
58#![deny(missing_docs)]
59// https://github.com/taiki-e/cargo-llvm-cov?tab=readme-ov-file#exclude-code-from-coverage
60#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
61// `cargo build --target thumbv6m-none-eabi` is (maybe?) a decent way to check we don't
62// indirectly use the full stdlib.
63#![cfg_attr(not(test), no_std)]
64extern crate alloc; // for `alloc::Vec`
65
66use smallvec::SmallVec;
67
68mod complement;
69mod intersection;
70mod intersection_iterator;
71pub mod iterator_wrapper;
72mod normalize;
73mod overloads;
74mod primitive_endpoint;
75mod range_case;
76mod range_vec;
77mod slice_sequence;
78mod union;
79mod union_iterator;
80
81pub use range_case::RangeCase;
82pub use range_vec::RangeVec;
83
84pub use normalize::is_normalized;
85pub use normalize::normalize_vec;
86
87pub use complement::complement_vec;
88pub use intersection::intersect_vec;
89pub use union::union_vec;
90
91/// Inline storage (in ranges) reserved in a [`RangeVec`].
92///
93/// Controlled by the `inline_storage` feature, which is enabled by
94/// default.  When the `inline_storage` feature is *not* enabled,
95/// this constant is set to 0.
96pub const INLINE_SIZE: usize = if cfg!(feature = "inline_storage") {
97    2
98} else {
99    0
100};
101
102/// Our internal storage type for [`RangeVec`].
103type Backing<T> = SmallVec<[(T, T); INLINE_SIZE]>;
104
105/// An [`Endpoint`] is the left or right limit of a closed interval
106/// `[left, right]`.
107///
108/// [`Endpoint`] types must have maximum and minimum values.  For
109/// bounded integer types, that's simply `T::MIN` or `T::MAX`;
110/// in general, types may have to be extended, just like floating
111/// point values have +/- infinity.
112///
113/// [`Endpoint`] types must also be enumerable in both ascending and
114/// descending order.
115///
116/// There is an implementation for all 10 primitive fixed-width
117/// integer types (signed/unsigned 8, 16, 32, 64, and 128 bits), for
118/// [`isize`] and [`usize`], and for the IEEE floating point types
119/// [`f32`] and [`f64`].
120pub trait Endpoint: Copy {
121    /// The minimum value for values of type [`Endpoint`]:
122    ///
123    /// \\[ \forall x : \mathtt{Self}, x \geq \mathtt{Self::min\\_value}() \\]
124    fn min_value() -> Self;
125
126    /// The maximum value for values of type [`Endpoint`]:
127    ///
128    /// \\[ \forall x : \mathtt{Self}, x \leq \mathtt{Self::max\\_value}() \\]
129    fn max_value() -> Self;
130
131    /// Returns whether `self` is comparable.
132    fn is_valid(self) -> bool;
133
134    /// Compares `self <=> other`.  Both `self` and `other` are
135    /// guaranteed to satisfy [`Endpoint::is_valid()`].
136    /// Implementations may return an arbitrary ordering if that's not
137    /// the case.
138    ///
139    /// See [`core::cmp::Ord`]
140    fn cmp_end(self, other: Self) -> core::cmp::Ordering;
141
142    /// Returns the minimum [`Endpoint`] value strictly
143    /// greater than `self`, or `None` if there is no
144    /// such value (iff `self == Self::max_value()`).
145    ///
146    /// \\[ \forall \mathtt{self}, x: \mathtt{Self}, x > \mathtt{self} \Rightarrow x \geq \mathtt{self.next\\_after}() \\]
147    #[inline(always)]
148    fn next_after(self) -> Option<Self> {
149        self.increase_toward(Self::max_value())
150    }
151
152    /// Returns the maximum [`Endpoint`] value strictly
153    /// less than `self`, or `None` if there is no
154    /// such value (iff `self == Self::min_value()`).
155    ///
156    /// \\[ \forall \mathtt{self}, x: \mathtt{Self}, x < \mathtt{self} \Rightarrow x \leq \mathtt{self.prev\\_before}() \\]
157    #[inline(always)]
158    fn prev_before(self) -> Option<Self> {
159        self.decrease_toward(Self::min_value())
160    }
161
162    /// Returns [`prev_before()`] iff `other < self`, and [`None`]
163    /// otherwise.
164    ///
165    /// In practice, it's usually easier to directly implement this
166    /// method instead of [`prev_before()`] (`other < self` guarantees
167    /// there is a previous value for `self`), so [`prev_before()`] is
168    /// implemented in terms of [`Self::decrease_toward()`].
169    ///
170    /// [`prev_before()`]: `Self::prev_before`
171    fn decrease_toward(self, other: Self) -> Option<Self>;
172
173    /// Returns [`next_after()`] iff `other > self`, and [`None`]
174    /// otherwise.
175    ///
176    /// In practice, it's usually easier to directly implement this
177    /// method instead of [`next_after()`] (`other > self` guarantees
178    /// there is a next value for `self`), so [`next_after()`] is
179    /// implemented in terms of [`Self::increase_toward()`].
180    ///
181    /// [`next_after()`]: `Self::next_after`
182    fn increase_toward(self, other: Self) -> Option<Self>;
183
184    /// Compares two ranges of endpoints.
185    #[doc(hidden)]
186    #[inline(always)]
187    fn cmp_range(left: (Self, Self), right: (Self, Self)) -> core::cmp::Ordering {
188        match left.0.cmp_end(right.0) {
189            core::cmp::Ordering::Equal => left.1.cmp_end(right.1),
190            any => any,
191        }
192    }
193
194    /// Returns the max of two endpoints.
195    #[doc(hidden)]
196    #[inline(always)]
197    fn bot_end(self, other: Self) -> Self {
198        core::cmp::min_by(self, other, |x, y| Self::cmp_end(*x, *y))
199    }
200
201    /// Returns the min of two endpoints.
202    #[doc(hidden)]
203    #[inline(always)]
204    fn top_end(self, other: Self) -> Self {
205        core::cmp::max_by(self, other, |x, y| Self::cmp_end(*x, *y))
206    }
207}
208
209/// We represent closed ranges as pairs of [`Endpoint`]s.
210type Pair<T> = (T, T);
211
212mod private {
213    pub trait Sealed {}
214}
215
216/// A [`ClosedRange`] represents a closed range of values with pairs
217/// of [`Endpoint`]s.
218///
219/// This trait stands for `(T, T)` `&(T, T)`, where `T` implements
220/// [`Endpoint`].
221///
222/// The [`ClosedRange`] trait is sealed and cannot be implemented for
223/// types outside this crate.  External code *may* have to write down
224/// the trait's name, but most likely shouldn't try to actually invoke
225/// any method on that trait.
226pub trait ClosedRange: Copy + private::Sealed {
227    /// The type of the endpoints for this range.
228    #[doc(hidden)]
229    type EndT: Endpoint;
230
231    /// Returns a copy of the range represented by this
232    /// [`ClosedRange`] instance.
233    #[doc(hidden)]
234    fn get(self) -> Pair<Self::EndT>;
235}
236
237/// A [`NormalizedRangeIter`] yields a sorted sequence of
238/// non-overlapping, non-adjacent, non-empty closed ranges.
239///
240/// It's hard to check for this property at runtime, so this
241/// trait is sealed.
242pub trait NormalizedRangeIter: private::Sealed + Iterator<Item: ClosedRange> {
243    /// Determines whether this range iterator represents the empty set.
244    #[inline(always)]
245    #[must_use]
246    fn into_empty_flag(mut self) -> bool
247    where
248        Self: Sized,
249    {
250        self.next().is_none()
251    }
252
253    /// Determines whether this range iterator is non-empty.
254    #[inline(always)]
255    #[must_use]
256    fn into_inhabited_flag(self) -> bool
257    where
258        Self: Sized,
259    {
260        !self.into_empty_flag()
261    }
262
263    /// Determines whether this range iterator is equivalent to
264    /// (represents the same set of values as) another.
265    ///
266    /// This operation takes constant space and time linear in
267    /// the shorter length of the two input iterators.
268    #[must_use]
269    fn eqv(
270        mut self,
271        other: impl IntoNormalizedRangeIter<Item: ClosedRange<EndT = ClosedRangeEnd<Self::Item>>>,
272    ) -> bool
273    where
274        Self: Sized,
275    {
276        use core::cmp::Ordering;
277
278        let mut other = other.into_iter();
279        loop {
280            // No need to fuse, we bail as soon as one iterator returns `None`.
281            match (self.next(), other.next()) {
282                (Some(a), Some(b)) => {
283                    if Endpoint::cmp_range(a.get(), b.get()) != Ordering::Equal {
284                        return false;
285                    }
286                }
287                (None, None) => return true,
288                _ => return false,
289            }
290        }
291    }
292
293    /// Returns an iterator for the complement of this normalized range iterator.
294    ///
295    /// Running the resulting iterator to exhaustion takes constant space and time
296    /// linear in the length of the input iterator.
297    ///
298    /// The result is also a [`NormalizedRangeIter`].
299    #[inline(always)]
300    #[must_use]
301    fn complement(self) -> complement::ComplementIterator<Self>
302    where
303        Self: Sized,
304    {
305        complement::ComplementIterator::new(self)
306    }
307
308    /// Returns an iterator for the intersection of this normalized range iterator
309    /// and another [`RangeVec`] of normalized ranges.
310    ///
311    /// Running the resulting iterator to exhaustion takes constant space and
312    /// \\(\mathcal{O}(\min(m + n, m \log n))\\) time, where \\(m\\) is the
313    /// size of `self`, and \\(n\\) that of `other`.
314    ///
315    /// The result is also a [`NormalizedRangeIter`].
316    #[inline(always)]
317    #[must_use]
318    fn intersect_vec<'a>(
319        self,
320        other: &'a RangeVec<ClosedRangeEnd<Self::Item>>,
321    ) -> intersection::IntersectionIterator<'a, Self>
322    where
323        Self: 'a + Sized,
324    {
325        // Unsafe because the interface assumes both arguments are normalized.
326        unsafe { crate::intersection::intersect(self, other) }
327    }
328
329    /// Returns an iterator for the intersection of this normalized range iterator
330    /// and another iterator of normalized ranges.
331    ///
332    /// Running the resulting iterator to exhaustion takes constant space and
333    /// time linear in the total length of the two input iterators.
334    ///
335    /// The result is also a [`NormalizedRangeIter`].
336    #[inline(always)]
337    #[must_use]
338    fn intersect<Other>(
339        self,
340        other: Other,
341    ) -> intersection_iterator::LinearIntersectionIterator<
342        ClosedRangeEnd<Self::Item>,
343        Self,
344        <Other as IntoIterator>::IntoIter,
345    >
346    where
347        Self: Sized,
348        Other: IntoNormalizedRangeIter<Item: ClosedRange<EndT = ClosedRangeEnd<Self::Item>>>,
349    {
350        intersection_iterator::LinearIntersectionIterator::new(self, other.into_iter())
351    }
352
353    /// Returns an interator for the union of this normalized range
354    /// iterator and another normalized range iterator.
355    ///
356    /// Running the resulting iterator to exhaustion takes constant space and
357    /// time linear in the total length of the two input iterators.
358    ///
359    /// The result is also a [`NormalizedRangeIter`].
360    #[inline(always)]
361    #[must_use]
362    fn union<Other>(
363        self,
364        other: Other,
365    ) -> union_iterator::UnionIterator<
366        ClosedRangeEnd<Self::Item>,
367        Self,
368        <Other as IntoIterator>::IntoIter,
369    >
370    where
371        Self: Sized,
372        Other: IntoNormalizedRangeIter<Item: ClosedRange<EndT = ClosedRangeEnd<Self::Item>>>,
373    {
374        union_iterator::UnionIterator::new(self, other.into_iter())
375    }
376
377    /// Collects the contents of a [`NormalizedRangeIter`] into a [`RangeVec`].
378    ///
379    /// This takes time linear in the length of the input iterator (in addition
380    /// to the resources used by the iterator itself).
381    #[must_use]
382    fn collect_range_vec(self) -> RangeVec<ClosedRangeEnd<Self::Item>>
383    where
384        Self: Sized,
385    {
386        #[cfg(feature = "internal_checks")]
387        let hint = self.size_hint();
388
389        let inner: SmallVec<[_; INLINE_SIZE]> = self.map(|range| range.get()).collect();
390
391        #[cfg(feature = "internal_checks")]
392        {
393            assert!(hint.0 <= inner.len());
394            assert!(inner.len() <= hint.1.unwrap_or(usize::MAX));
395            assert!(is_normalized(&inner));
396        }
397
398        unsafe { RangeVec::new_unchecked(inner) }
399    }
400}
401
402/// Boxes of iterators are iterators.
403impl<T: NormalizedRangeIter + ?Sized> private::Sealed for alloc::boxed::Box<T> {}
404impl<T: NormalizedRangeIter + ?Sized> NormalizedRangeIter for alloc::boxed::Box<T> {}
405
406/// A [`IntoNormalizedRangeIter`] is an [`IntoIterator`] that turns
407/// into an [`NormalizedRangeIter`].
408pub trait IntoNormalizedRangeIter: IntoIterator<IntoIter: NormalizedRangeIter> {}
409
410impl<T: IntoIterator<IntoIter: NormalizedRangeIter>> IntoNormalizedRangeIter for T {}
411
412impl<T: Endpoint> private::Sealed for (T, T) {}
413
414impl<T: Endpoint> ClosedRange for (T, T) {
415    type EndT = T;
416
417    #[inline(always)]
418    fn get(self) -> (T, T) {
419        self
420    }
421}
422
423impl<T: Endpoint> private::Sealed for &(T, T) {}
424
425impl<T: Endpoint> ClosedRange for &(T, T) {
426    type EndT = T;
427
428    #[inline(always)]
429    fn get(self) -> (T, T) {
430        *self
431    }
432}
433
434/// The endpoints of the closed range.
435type ClosedRangeEnd<T> = <T as ClosedRange>::EndT;
436/// The return type of `ClosedRange::get()`.
437type ClosedRangeVal<T> = Pair<ClosedRangeEnd<T>>;
438
439#[cfg(test)]
440#[cfg_attr(coverage_nightly, coverage(off))]
441fn ranges_to_bits(ranges: &[(u8, u8)]) -> alloc::vec::Vec<bool> {
442    use alloc::vec;
443
444    let mut marks = vec![false; 256];
445
446    for (start, stop) in ranges.iter().copied() {
447        if start <= stop {
448            for i in start..=stop {
449                marks[i as usize] = true;
450            }
451        }
452    }
453
454    marks
455}
456
457#[cfg(test)]
458#[cfg_attr(coverage_nightly, coverage(off))]
459mod test {
460    use super::*;
461    use alloc::vec;
462    use alloc::vec::Vec;
463
464    #[test]
465    fn test_min_max() {
466        assert_eq!(<u8 as Endpoint>::min_value(), 0);
467        assert_eq!(<u8 as Endpoint>::max_value(), 255);
468
469        assert_eq!(<i8 as Endpoint>::min_value(), -128);
470        assert_eq!(<i8 as Endpoint>::max_value(), 127);
471
472        assert_eq!(<i32 as Endpoint>::min_value(), i32::MIN);
473        assert_eq!(<i32 as Endpoint>::max_value(), i32::MAX);
474
475        assert_eq!(<isize as Endpoint>::min_value(), isize::MIN);
476        assert_eq!(<isize as Endpoint>::max_value(), isize::MAX);
477
478        assert_eq!(<usize as Endpoint>::min_value(), usize::MIN);
479        assert_eq!(<usize as Endpoint>::max_value(), usize::MAX);
480    }
481
482    #[test]
483    fn test_prev_next_u64() {
484        assert_eq!(0u64.prev_before(), None);
485        assert_eq!(0u64.next_after(), Some(1));
486
487        assert_eq!(u64::MAX.prev_before(), Some(u64::MAX - 1));
488        assert_eq!(u64::MAX.next_after(), None);
489
490        assert_eq!(0u64.decrease_toward(0u64), None);
491        assert_eq!(0u64.increase_toward(10u64), Some(1));
492
493        assert_eq!(1u64.decrease_toward(0u64), Some(0u64));
494        assert_eq!(1u64.decrease_toward(1u64), None);
495        assert_eq!(1u64.decrease_toward(2u64), None);
496
497        assert_eq!(1u64.increase_toward(0u64), None);
498        assert_eq!(1u64.increase_toward(1u64), None);
499        assert_eq!(1u64.increase_toward(2u64), Some(2u64));
500
501        assert_eq!(u64::MAX.increase_toward(u64::MAX), None);
502        assert_eq!(u64::MAX.decrease_toward(0), Some(u64::MAX - 1));
503    }
504
505    #[test]
506    fn test_closed_range() {
507        let ranges = vec![(1u8, 2u8), (10u8, 4u8)];
508
509        assert_eq!(
510            &ranges.iter().map(ClosedRange::get).collect::<Vec<_>>(),
511            &ranges
512        );
513        assert_eq!(
514            ranges
515                .clone()
516                .into_iter()
517                .map(ClosedRange::get)
518                .collect::<Vec<_>>(),
519            ranges
520        );
521    }
522
523    #[test]
524    fn test_empty_inhabited_iter() {
525        assert!(RangeVec::<u8>::new().into_iter().into_empty_flag());
526        assert!(!RangeVec::<u8>::new().into_iter().into_inhabited_flag());
527
528        assert!(!RangeVec::from_vec(vec![(1u8, 1u8)])
529            .into_iter()
530            .into_empty_flag());
531        assert!(RangeVec::from_vec(vec![(1u8, 1u8)])
532            .into_iter()
533            .into_inhabited_flag());
534    }
535
536    #[test]
537    fn test_chain_boxed_iter() {
538        let mut acc: Option<Box<dyn NormalizedRangeIter<Item = (u8, u8)>>> = None;
539
540        for i in 1u8..=4u8 {
541            let vec = RangeVec::from_vec(vec![(2 * i, 10 * i)]);
542
543            acc = match acc.take() {
544                None => Some(Box::new(vec.into_iter())),
545                Some(acc) if i % 2 == 0 => Some(Box::new(acc.intersect(vec.into_iter()))),
546                Some(acc) => Some(Box::new(acc.intersect_vec(Box::leak(Box::new(vec))))),
547            };
548        }
549
550        // Intersection is (8u8, 10u8); union with [0, 6]
551        let singleton: SmallVec<[(u8, u8); 1]> = smallvec::smallvec![(0, 6)];
552        acc = Some(Box::new(
553            acc.unwrap().union(RangeVec::from_smallvec(singleton)),
554        ));
555
556        let expected = RangeVec::from_vec(vec![(7u8, 7u8), (11u8, 255u8)]);
557        assert!(acc.unwrap().complement().eqv(expected));
558    }
559
560    proptest::proptest! {
561        #[test]
562        fn test_increase(x: u8) {
563            assert_eq!(<u8 as Endpoint>::max_value(), u8::MAX);
564
565            if x != u8::MAX {
566                assert_eq!(x.next_after(), Some(x + 1));
567            } else {
568                assert_eq!(x.next_after(), None);
569            }
570        }
571
572        #[test]
573        fn test_decrease(x: u8) {
574            assert_eq!(<u8 as Endpoint>::min_value(), 0u8);
575
576            if x != 0u8 {
577                assert_eq!(x.prev_before(), Some(x - 1));
578            } else {
579                assert_eq!(x.prev_before(), None);
580            }
581        }
582
583        #[test]
584        fn test_toward(x: u8, y: u8) {
585            let (x, y) = (x.min(y), x.max(y));
586
587            assert_eq!(x.decrease_toward(y), None);
588            assert_eq!(y.increase_toward(x), None);
589
590            if x == y {
591                assert_eq!(x.increase_toward(y), None);
592                assert_eq!(x.decrease_toward(y), None);
593                assert_eq!(y.increase_toward(x), None);
594                assert_eq!(y.decrease_toward(x), None);
595            } else {
596                assert_eq!(x.increase_toward(y), Some(x + 1));
597                assert_eq!(y.decrease_toward(x), Some(y - 1));
598            }
599        }
600
601        #[test]
602        fn test_top_bot(x: u8, y: u8) {
603            assert_eq!(x.bot_end(y), x.min(y));
604            assert_eq!(y.bot_end(x), x.min(y));
605
606            assert_eq!(x.top_end(y), x.max(y));
607            assert_eq!(y.top_end(x), x.max(y));
608        }
609
610        #[test]
611        fn test_cmp(x: u8, y: u8) {
612            assert_eq!(x.cmp_end(y), x.cmp(&y));
613            assert_eq!(y.cmp_end(x), y.cmp(&x));
614        }
615
616        #[test]
617        fn test_cmp_range(x: (u8, u8), y: (u8, u8)) {
618            assert_eq!(u8::cmp_range(x, y), x.cmp(&y));
619            assert_eq!(u8::cmp_range(y, x), y.cmp(&x));
620        }
621
622        // Smoke test isize and usize: they're the same as one of the
623        // regular integer types, so not worth fuzzing individually.
624        // However, we still want some coverage.
625        #[test]
626        fn test_increase_isize(x: isize) {
627            assert_eq!(<isize as Endpoint>::max_value(), isize::MAX);
628
629            if x != isize::MAX {
630                assert_eq!(x.next_after(), Some(x + 1));
631            } else {
632                assert_eq!(x.next_after(), None);
633            }
634        }
635
636        #[test]
637        fn test_decrease_isize(x: isize) {
638            assert_eq!(<isize as Endpoint>::min_value(), isize::MIN);
639
640            if x != isize::MIN {
641                assert_eq!(x.prev_before(), Some(x - 1));
642            } else {
643                assert_eq!(x.prev_before(), None);
644            }
645        }
646
647        #[test]
648        fn test_toward_isize(x: isize, y: isize) {
649            let (x, y) = (x.min(y), x.max(y));
650
651            assert_eq!(x.decrease_toward(y), None);
652            assert_eq!(y.increase_toward(x), None);
653
654            if x == y {
655                assert_eq!(x.increase_toward(y), None);
656                assert_eq!(x.decrease_toward(y), None);
657                assert_eq!(y.increase_toward(x), None);
658                assert_eq!(y.decrease_toward(x), None);
659            } else {
660                assert_eq!(x.increase_toward(y), Some(x + 1));
661                assert_eq!(y.decrease_toward(x), Some(y - 1));
662            }
663        }
664
665        #[test]
666        fn test_top_bot_isize(x: isize, y: isize) {
667            assert_eq!(x.bot_end(y), x.min(y));
668            assert_eq!(y.bot_end(x), x.min(y));
669
670            assert_eq!(x.top_end(y), x.max(y));
671            assert_eq!(y.top_end(x), x.max(y));
672        }
673
674        #[test]
675        fn test_cmp_isize(x: isize, y: isize) {
676            assert_eq!(x.cmp_end(y), x.cmp(&y));
677            assert_eq!(y.cmp_end(x), y.cmp(&x));
678        }
679
680        #[test]
681        fn test_cmp_range_isize(x: (isize, isize), y: (isize, isize)) {
682            assert_eq!(isize::cmp_range(x, y), x.cmp(&y));
683            assert_eq!(isize::cmp_range(y, x), y.cmp(&x));
684        }
685
686        #[test]
687        fn test_increase_usize(x: usize) {
688            assert_eq!(<usize as Endpoint>::max_value(), usize::MAX);
689
690            if x != usize::MAX {
691                assert_eq!(x.next_after(), Some(x + 1));
692            } else {
693                assert_eq!(x.next_after(), None);
694            }
695        }
696
697        #[test]
698        fn test_decrease_usize(x: usize) {
699            assert_eq!(<usize as Endpoint>::min_value(), 0usize);
700
701            if x != usize::MIN {
702                assert_eq!(x.prev_before(), Some(x - 1));
703            } else {
704                assert_eq!(x.prev_before(), None);
705            }
706        }
707
708        #[test]
709        fn test_toward_usize(x: usize, y: usize) {
710            let (x, y) = (x.min(y), x.max(y));
711
712            assert_eq!(x.decrease_toward(y), None);
713            assert_eq!(y.increase_toward(x), None);
714
715            if x == y {
716                assert_eq!(x.increase_toward(y), None);
717                assert_eq!(x.decrease_toward(y), None);
718                assert_eq!(y.increase_toward(x), None);
719                assert_eq!(y.decrease_toward(x), None);
720            } else {
721                assert_eq!(x.increase_toward(y), Some(x + 1));
722                assert_eq!(y.decrease_toward(x), Some(y - 1));
723            }
724        }
725
726        #[test]
727        fn test_top_bot_usize(x: usize, y: usize) {
728            assert_eq!(x.bot_end(y), x.min(y));
729            assert_eq!(y.bot_end(x), x.min(y));
730
731            assert_eq!(x.top_end(y), x.max(y));
732            assert_eq!(y.top_end(x), x.max(y));
733        }
734
735        #[test]
736        fn test_cmp_usize(x: usize, y: usize) {
737            assert_eq!(x.cmp_end(y), x.cmp(&y));
738            assert_eq!(y.cmp_end(x), y.cmp(&x));
739        }
740
741        #[test]
742        fn test_cmp_range_usize(x: (usize, usize), y: (usize, usize)) {
743            assert_eq!(usize::cmp_range(x, y), x.cmp(&y));
744            assert_eq!(usize::cmp_range(y, x), y.cmp(&x));
745        }
746    }
747}