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