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 is equivalent to
244 /// (represents the same set of values as) another.
245 ///
246 /// This operation takes constant space and time linear in
247 /// the shorter length of the two input iterators.
248 #[must_use]
249 fn eqv(
250 mut self,
251 other: impl IntoNormalizedRangeIter<Item: ClosedRange<EndT = ClosedRangeEnd<Self::Item>>>,
252 ) -> bool
253 where
254 Self: Sized,
255 {
256 use core::cmp::Ordering;
257
258 let mut other = other.into_iter();
259 loop {
260 // No need to fuse, we bail as soon as one iterator returns `None`.
261 match (self.next(), other.next()) {
262 (Some(a), Some(b)) => {
263 if Endpoint::cmp_range(a.get(), b.get()) != Ordering::Equal {
264 return false;
265 }
266 }
267 (None, None) => return true,
268 _ => return false,
269 }
270 }
271 }
272
273 /// Returns an iterator for the complement of this normalized range iterator.
274 ///
275 /// Running the resulting iterator to exhaustion takes constant space and time
276 /// linear in the length of the input iterator.
277 ///
278 /// The result is also a [`NormalizedRangeIter`].
279 #[inline(always)]
280 #[must_use]
281 fn complement(self) -> complement::ComplementIterator<Self>
282 where
283 Self: Sized,
284 {
285 complement::ComplementIterator::new(self)
286 }
287
288 /// Returns an iterator for the intersection of this normalized range iterator
289 /// and another [`RangeVec`] of normalized ranges.
290 ///
291 /// Running the resulting iterator to exhaustion takes constant space and
292 /// \\(\mathcal{O}(\min(m + n, m \log n))\\) time, where \\(m\\) is the
293 /// size of `self`, and \\(n\\) that of `other`.
294 ///
295 /// The result is also a [`NormalizedRangeIter`].
296 #[inline(always)]
297 #[must_use]
298 fn intersect_vec<'a>(
299 self,
300 other: &'a RangeVec<ClosedRangeEnd<Self::Item>>,
301 ) -> intersection::IntersectionIterator<'a, Self>
302 where
303 Self: 'a + Sized,
304 {
305 // Unsafe because the interface assumes both arguments are normalized.
306 unsafe { crate::intersection::intersect(self, other) }
307 }
308
309 /// Returns an iterator for the intersection of this normalized range iterator
310 /// and another iterator of normalized ranges.
311 ///
312 /// Running the resulting iterator to exhaustion takes constant space and
313 /// time linear in the total length of the two input iterators.
314 ///
315 /// The result is also a [`NormalizedRangeIter`].
316 #[inline(always)]
317 #[must_use]
318 fn intersect<Other>(
319 self,
320 other: Other,
321 ) -> intersection_iterator::LinearIntersectionIterator<
322 ClosedRangeEnd<Self::Item>,
323 Self,
324 <Other as IntoIterator>::IntoIter,
325 >
326 where
327 Self: Sized,
328 Other: IntoNormalizedRangeIter<Item: ClosedRange<EndT = ClosedRangeEnd<Self::Item>>>,
329 {
330 intersection_iterator::LinearIntersectionIterator::new(self, other.into_iter())
331 }
332
333 /// Returns an interator for the union of this normalized range
334 /// iterator and another normalized range iterator.
335 ///
336 /// Running the resulting iterator to exhaustion takes constant space and
337 /// time linear in the total length of the two input iterators.
338 ///
339 /// The result is also a [`NormalizedRangeIter`].
340 #[inline(always)]
341 #[must_use]
342 fn union<Other>(
343 self,
344 other: Other,
345 ) -> union_iterator::UnionIterator<
346 ClosedRangeEnd<Self::Item>,
347 Self,
348 <Other as IntoIterator>::IntoIter,
349 >
350 where
351 Self: Sized,
352 Other: IntoNormalizedRangeIter<Item: ClosedRange<EndT = ClosedRangeEnd<Self::Item>>>,
353 {
354 union_iterator::UnionIterator::new(self, other.into_iter())
355 }
356
357 /// Collects the contents of a [`NormalizedRangeIter`] into a [`RangeVec`].
358 ///
359 /// This takes time linear in the length of the input iterator (in addition
360 /// to the resources used by the iterator itself).
361 #[must_use]
362 fn collect_range_vec(self) -> RangeVec<ClosedRangeEnd<Self::Item>>
363 where
364 Self: Sized,
365 {
366 #[cfg(feature = "internal_checks")]
367 let hint = self.size_hint();
368
369 let inner: SmallVec<[_; INLINE_SIZE]> = self.map(|range| range.get()).collect();
370
371 #[cfg(feature = "internal_checks")]
372 {
373 assert!(hint.0 <= inner.len());
374 assert!(inner.len() <= hint.1.unwrap_or(usize::MAX));
375 assert!(is_normalized(&inner));
376 }
377
378 unsafe { RangeVec::new_unchecked(inner) }
379 }
380}
381
382/// Boxes of iterators are iterators.
383impl<T: NormalizedRangeIter + ?Sized> private::Sealed for alloc::boxed::Box<T> {}
384impl<T: NormalizedRangeIter + ?Sized> NormalizedRangeIter for alloc::boxed::Box<T> {}
385
386/// A [`IntoNormalizedRangeIter`] is an [`IntoIterator`] that turns
387/// into an [`NormalizedRangeIter`].
388pub trait IntoNormalizedRangeIter: IntoIterator<IntoIter: NormalizedRangeIter> {}
389
390impl<T: IntoIterator<IntoIter: NormalizedRangeIter>> IntoNormalizedRangeIter for T {}
391
392impl<T: Endpoint> private::Sealed for (T, T) {}
393
394impl<T: Endpoint> ClosedRange for (T, T) {
395 type EndT = T;
396
397 #[inline(always)]
398 fn get(self) -> (T, T) {
399 self
400 }
401}
402
403impl<T: Endpoint> private::Sealed for &(T, T) {}
404
405impl<T: Endpoint> ClosedRange for &(T, T) {
406 type EndT = T;
407
408 #[inline(always)]
409 fn get(self) -> (T, T) {
410 *self
411 }
412}
413
414/// The endpoints of the closed range.
415type ClosedRangeEnd<T> = <T as ClosedRange>::EndT;
416/// The return type of `ClosedRange::get()`.
417type ClosedRangeVal<T> = Pair<ClosedRangeEnd<T>>;
418
419#[cfg(test)]
420#[cfg_attr(coverage_nightly, coverage(off))]
421fn ranges_to_bits(ranges: &[(u8, u8)]) -> alloc::vec::Vec<bool> {
422 use alloc::vec;
423
424 let mut marks = vec![false; 256];
425
426 for (start, stop) in ranges.iter().copied() {
427 if start <= stop {
428 for i in start..=stop {
429 marks[i as usize] = true;
430 }
431 }
432 }
433
434 marks
435}
436
437#[cfg(test)]
438#[cfg_attr(coverage_nightly, coverage(off))]
439mod test {
440 use super::*;
441 use alloc::vec;
442 use alloc::vec::Vec;
443
444 #[test]
445 fn test_min_max() {
446 assert_eq!(<u8 as Endpoint>::min_value(), 0);
447 assert_eq!(<u8 as Endpoint>::max_value(), 255);
448
449 assert_eq!(<i8 as Endpoint>::min_value(), -128);
450 assert_eq!(<i8 as Endpoint>::max_value(), 127);
451
452 assert_eq!(<i32 as Endpoint>::min_value(), i32::MIN);
453 assert_eq!(<i32 as Endpoint>::max_value(), i32::MAX);
454
455 assert_eq!(<isize as Endpoint>::min_value(), isize::MIN);
456 assert_eq!(<isize as Endpoint>::max_value(), isize::MAX);
457
458 assert_eq!(<usize as Endpoint>::min_value(), usize::MIN);
459 assert_eq!(<usize as Endpoint>::max_value(), usize::MAX);
460 }
461
462 #[test]
463 fn test_prev_next_u64() {
464 assert_eq!(0u64.prev_before(), None);
465 assert_eq!(0u64.next_after(), Some(1));
466
467 assert_eq!(u64::MAX.prev_before(), Some(u64::MAX - 1));
468 assert_eq!(u64::MAX.next_after(), None);
469
470 assert_eq!(0u64.decrease_toward(0u64), None);
471 assert_eq!(0u64.increase_toward(10u64), Some(1));
472
473 assert_eq!(1u64.decrease_toward(0u64), Some(0u64));
474 assert_eq!(1u64.decrease_toward(1u64), None);
475 assert_eq!(1u64.decrease_toward(2u64), None);
476
477 assert_eq!(1u64.increase_toward(0u64), None);
478 assert_eq!(1u64.increase_toward(1u64), None);
479 assert_eq!(1u64.increase_toward(2u64), Some(2u64));
480
481 assert_eq!(u64::MAX.increase_toward(u64::MAX), None);
482 assert_eq!(u64::MAX.decrease_toward(0), Some(u64::MAX - 1));
483 }
484
485 #[test]
486 fn test_closed_range() {
487 let ranges = vec![(1u8, 2u8), (10u8, 4u8)];
488
489 assert_eq!(
490 &ranges.iter().map(ClosedRange::get).collect::<Vec<_>>(),
491 &ranges
492 );
493 assert_eq!(
494 ranges
495 .clone()
496 .into_iter()
497 .map(ClosedRange::get)
498 .collect::<Vec<_>>(),
499 ranges
500 );
501 }
502
503 #[test]
504 fn test_chain_boxed_iter() {
505 let mut acc: Option<Box<dyn NormalizedRangeIter<Item = (u8, u8)>>> = None;
506
507 for i in 1u8..=4u8 {
508 let vec = RangeVec::from_vec(vec![(2 * i, 10 * i)]);
509
510 acc = match acc.take() {
511 None => Some(Box::new(vec.into_iter())),
512 Some(acc) if i % 2 == 0 => Some(Box::new(acc.intersect(vec.into_iter()))),
513 Some(acc) => Some(Box::new(acc.intersect_vec(Box::leak(Box::new(vec))))),
514 };
515 }
516
517 // Intersection is (8u8, 10u8); union with [0, 6]
518 let singleton: SmallVec<[(u8, u8); 1]> = smallvec::smallvec![(0, 6)];
519 acc = Some(Box::new(
520 acc.unwrap().union(RangeVec::from_smallvec(singleton)),
521 ));
522
523 let expected = RangeVec::from_vec(vec![(7u8, 7u8), (11u8, 255u8)]);
524 assert!(acc.unwrap().complement().eqv(expected));
525 }
526
527 proptest::proptest! {
528 #[test]
529 fn test_increase(x: u8) {
530 assert_eq!(<u8 as Endpoint>::max_value(), u8::MAX);
531
532 if x != u8::MAX {
533 assert_eq!(x.next_after(), Some(x + 1));
534 } else {
535 assert_eq!(x.next_after(), None);
536 }
537 }
538
539 #[test]
540 fn test_decrease(x: u8) {
541 assert_eq!(<u8 as Endpoint>::min_value(), 0u8);
542
543 if x != 0u8 {
544 assert_eq!(x.prev_before(), Some(x - 1));
545 } else {
546 assert_eq!(x.prev_before(), None);
547 }
548 }
549
550 #[test]
551 fn test_toward(x: u8, y: u8) {
552 let (x, y) = (x.min(y), x.max(y));
553
554 assert_eq!(x.decrease_toward(y), None);
555 assert_eq!(y.increase_toward(x), None);
556
557 if x == y {
558 assert_eq!(x.increase_toward(y), None);
559 assert_eq!(x.decrease_toward(y), None);
560 assert_eq!(y.increase_toward(x), None);
561 assert_eq!(y.decrease_toward(x), None);
562 } else {
563 assert_eq!(x.increase_toward(y), Some(x + 1));
564 assert_eq!(y.decrease_toward(x), Some(y - 1));
565 }
566 }
567
568 #[test]
569 fn test_top_bot(x: u8, y: u8) {
570 assert_eq!(x.bot_end(y), x.min(y));
571 assert_eq!(y.bot_end(x), x.min(y));
572
573 assert_eq!(x.top_end(y), x.max(y));
574 assert_eq!(y.top_end(x), x.max(y));
575 }
576
577 #[test]
578 fn test_cmp(x: u8, y: u8) {
579 assert_eq!(x.cmp_end(y), x.cmp(&y));
580 assert_eq!(y.cmp_end(x), y.cmp(&x));
581 }
582
583 #[test]
584 fn test_cmp_range(x: (u8, u8), y: (u8, u8)) {
585 assert_eq!(u8::cmp_range(x, y), x.cmp(&y));
586 assert_eq!(u8::cmp_range(y, x), y.cmp(&x));
587 }
588
589 // Smoke test isize and usize: they're the same as one of the
590 // regular integer types, so not worth fuzzing individually.
591 // However, we still want some coverage.
592 #[test]
593 fn test_increase_isize(x: isize) {
594 assert_eq!(<isize as Endpoint>::max_value(), isize::MAX);
595
596 if x != isize::MAX {
597 assert_eq!(x.next_after(), Some(x + 1));
598 } else {
599 assert_eq!(x.next_after(), None);
600 }
601 }
602
603 #[test]
604 fn test_decrease_isize(x: isize) {
605 assert_eq!(<isize as Endpoint>::min_value(), isize::MIN);
606
607 if x != isize::MIN {
608 assert_eq!(x.prev_before(), Some(x - 1));
609 } else {
610 assert_eq!(x.prev_before(), None);
611 }
612 }
613
614 #[test]
615 fn test_toward_isize(x: isize, y: isize) {
616 let (x, y) = (x.min(y), x.max(y));
617
618 assert_eq!(x.decrease_toward(y), None);
619 assert_eq!(y.increase_toward(x), None);
620
621 if x == y {
622 assert_eq!(x.increase_toward(y), None);
623 assert_eq!(x.decrease_toward(y), None);
624 assert_eq!(y.increase_toward(x), None);
625 assert_eq!(y.decrease_toward(x), None);
626 } else {
627 assert_eq!(x.increase_toward(y), Some(x + 1));
628 assert_eq!(y.decrease_toward(x), Some(y - 1));
629 }
630 }
631
632 #[test]
633 fn test_top_bot_isize(x: isize, y: isize) {
634 assert_eq!(x.bot_end(y), x.min(y));
635 assert_eq!(y.bot_end(x), x.min(y));
636
637 assert_eq!(x.top_end(y), x.max(y));
638 assert_eq!(y.top_end(x), x.max(y));
639 }
640
641 #[test]
642 fn test_cmp_isize(x: isize, y: isize) {
643 assert_eq!(x.cmp_end(y), x.cmp(&y));
644 assert_eq!(y.cmp_end(x), y.cmp(&x));
645 }
646
647 #[test]
648 fn test_cmp_range_isize(x: (isize, isize), y: (isize, isize)) {
649 assert_eq!(isize::cmp_range(x, y), x.cmp(&y));
650 assert_eq!(isize::cmp_range(y, x), y.cmp(&x));
651 }
652
653 #[test]
654 fn test_increase_usize(x: usize) {
655 assert_eq!(<usize as Endpoint>::max_value(), usize::MAX);
656
657 if x != usize::MAX {
658 assert_eq!(x.next_after(), Some(x + 1));
659 } else {
660 assert_eq!(x.next_after(), None);
661 }
662 }
663
664 #[test]
665 fn test_decrease_usize(x: usize) {
666 assert_eq!(<usize as Endpoint>::min_value(), 0usize);
667
668 if x != usize::MIN {
669 assert_eq!(x.prev_before(), Some(x - 1));
670 } else {
671 assert_eq!(x.prev_before(), None);
672 }
673 }
674
675 #[test]
676 fn test_toward_usize(x: usize, y: usize) {
677 let (x, y) = (x.min(y), x.max(y));
678
679 assert_eq!(x.decrease_toward(y), None);
680 assert_eq!(y.increase_toward(x), None);
681
682 if x == y {
683 assert_eq!(x.increase_toward(y), None);
684 assert_eq!(x.decrease_toward(y), None);
685 assert_eq!(y.increase_toward(x), None);
686 assert_eq!(y.decrease_toward(x), None);
687 } else {
688 assert_eq!(x.increase_toward(y), Some(x + 1));
689 assert_eq!(y.decrease_toward(x), Some(y - 1));
690 }
691 }
692
693 #[test]
694 fn test_top_bot_usize(x: usize, y: usize) {
695 assert_eq!(x.bot_end(y), x.min(y));
696 assert_eq!(y.bot_end(x), x.min(y));
697
698 assert_eq!(x.top_end(y), x.max(y));
699 assert_eq!(y.top_end(x), x.max(y));
700 }
701
702 #[test]
703 fn test_cmp_usize(x: usize, y: usize) {
704 assert_eq!(x.cmp_end(y), x.cmp(&y));
705 assert_eq!(y.cmp_end(x), y.cmp(&x));
706 }
707
708 #[test]
709 fn test_cmp_range_usize(x: (usize, usize), y: (usize, usize)) {
710 assert_eq!(usize::cmp_range(x, y), x.cmp(&y));
711 assert_eq!(usize::cmp_range(y, x), y.cmp(&x));
712 }
713 }
714}