1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
#![no_std]
/// A trait for values that permit contiguous subranges.
///
/// Implementations that override the provided functions must ensure
/// their custom implementations are equivalent to the provided ones.
///
/// Implementations must uphold the following invariants:
/// 1. `ix.in_range(min, max)` if and only if `Ix::range(min, max).any(|x| x == ix)`
/// 2. If `ix.in_range(min, max)`, then `Ix::range(min, max).nth(ix.index(min, max)).unwrap() == ix`
/// 3. `Ix::range(min, max).map(|x| x.index(min, max))` yields equal items to `0..Ix::range_size(min, max)`
/// 4. `Ix::range_size(min, max)` = `Ix::range(min, max).count()`
///
/// # Examples
///
/// ```
/// # use ix_rs::Ix;
/// for (ix, i) in Ix::range(-45i128, 483).zip(0..) {
/// assert_eq!(ix.index(-45, 483), i);
/// } // Property 3
/// ```
/// ```
/// # use ix_rs::Ix;
/// assert!(20i32.in_range(17, 5432));
/// assert_eq!(Ix::range(17i32, 5432).nth(20i32.index(17, 5432)).unwrap(), 20);
/// // Property 2
/// ```
/// ```
/// # use ix_rs::Ix;
/// assert!(!(-30289i16).in_range(-746, 15564));
/// ```
/// ```
/// # use ix_rs::Ix;
/// assert!(0.in_range(-31597i16, 16417));
/// assert_eq!(Ix::range(-31597i16, 16417).nth(0.index(-31597i16, 16417)).unwrap(), 0);
/// // Property 2
/// ```
/// ```
/// # use ix_rs::Ix;
/// assert_eq!(
/// 2410117514u32.in_range(2073922791, 3401563124),
/// Ix::range(2073922791u32, 3401563124).any(|x| x == 2410117514)
/// ); // Property 1
/// ```
/// ```
/// # use ix_rs::Ix;
/// assert_eq!(Ix::range(8079u32, 1836091).count(), Ix::range_size(8079u32, 1836091))
/// // Property 4
/// ```
pub trait Ix: PartialOrd + Sized {
/// An iterator over the elements in a range of the implementing type.
type Range: Iterator<Item = Self>;
/// Generate an iterator over a range starting from `min` and stopping at `max`.
/// The resulting iterator must produce `min` and `max` at some point, each.
///
/// # Panics
///
/// Should panic if `min` is greater than `max`.
fn range(min: Self, max: Self) -> Self::Range;
/// Get the position of a value inside a range.
///
/// # Panics
///
/// Should panic if `min` is greater than `max`.
///
/// Should panic if the value is not in the range (as determined by [`in_range`]).
///
/// Panics if the resulting index is not representable as a [`usize`].
/// The default implementation does this by unwrapping the return value of [`index_checked`].
///
/// [`in_range`]: Ix::in_range
/// [`index_checked`]: Ix::index_checked
fn index(self, min: Self, max: Self) -> usize {
self.index_checked(min, max).expect("index too large")
}
/// Get the position of a value inside a range.
/// Checked version of [`index`].
///
/// # Panics
///
/// Should panic if `min` is greater than `max`.
///
/// Should panic if the value is not in the range (as determined by [`in_range`]).
///
/// [`index`]: Ix::index
/// [`in_range`]: Ix::in_range
fn index_checked(self, min: Self, max: Self) -> Option<usize>;
/// Check if a given value is inside a range.
///
/// # Panics
///
/// Should panic if `min` is greater than `max`.
fn in_range(self, min: Self, max: Self) -> bool;
/// Get the length of a range.
///
/// # Panics
///
/// Should panic if `min` is greater than `max`.
///
/// Panics if the resulting index is not representable as a [`usize`].
/// The default implementation does this by unwrapping the return value of [`range_size_checked`].
///
/// [`range_size_checked`]: Ix::range_size_checked
fn range_size(min: Self, max: Self) -> usize {
Ix::range_size_checked(min, max).expect("range size too large")
}
/// Get the length of a range.
/// Checked version of [`range_size`].
///
/// # Panics
///
/// Should panic if `min` is greater than `max`.
///
/// [`range_size`]: Ix::range_size
fn range_size_checked(min: Self, max: Self) -> Option<usize>;
}
mod macros;
pub mod usize_like;
use macros::impl_ix_numeric;
impl_ix_numeric!(u8);
impl_ix_numeric!(u16);
impl_ix_numeric!(u32);
impl_ix_numeric!(u64);
impl_ix_numeric!(u128);
impl_ix_numeric!(i8);
impl_ix_numeric!(i16);
impl_ix_numeric!(i32);
impl_ix_numeric!(i64);
impl_ix_numeric!(i128);
impl_ix_numeric!(usize);
impl_ix_numeric!(isize);