ranges 0.4.0

This crate provides a generic alternative to core/std ranges, set-operations to work with them and a range set that can efficiently store them with the least amount of memory possible.
Documentation
use core::{cmp::Ordering, ops::Bound};

use num_bigint::BigUint;

use super::{Domain, Iterable};

impl Domain for BigUint {
    const DISCRETE: bool = true;

    /// Returns `Some(self - 1)` unless `self` is zero, in which case `None` is returned.
    #[allow(clippy::arithmetic_side_effects)]
    fn predecessor(&self) -> Option<Self> {
        match Self::minimum() {
            Bound::Unbounded | Bound::Excluded(_) => unreachable!(),
            Bound::Included(min) => {
                if self == &min {
                    None
                } else {
                    Some(self - Self::from(1_usize))
                }
            }
        }
    }

    /// Returns `Some(self + 1)`.
    #[allow(clippy::arithmetic_side_effects)]
    fn successor(&self) -> Option<Self> {
        Some(self + Self::from(1_usize))
    }

    /// Returns `Included(0)`.
    fn minimum() -> Bound<Self> {
        Bound::Included(Self::from(0_usize))
    }

    #[allow(clippy::arithmetic_side_effects)]
    #[must_use]
    fn shares_neighbour_with(&self, other: &Self) -> bool {
        let other_val = other;

        let (big, small) = match self.cmp(other_val) {
            Ordering::Less => (other_val, self),
            Ordering::Equal => return false,
            Ordering::Greater => (self, other_val),
        };

        big - small == Self::from(2_usize)
    }
}

impl Iterable for BigUint {
    type Output = Self;

    fn next(&self) -> Option<Self::Output> {
        self.successor()
    }
}

#[cfg(test)]
mod tests {
    use num_bigint::BigUint;

    use crate::Domain;

    #[test]
    fn is_next_to() {
        assert!(BigUint::from(2_u8).is_next_to(&BigUint::from(3_u8)));
        assert!(!BigUint::from(2_u8).is_next_to(&BigUint::from(4_u8)));
    }

    #[test]
    fn shares_neighbour_with() {
        // self-distance
        assert!(!BigUint::from(2_u8).shares_neighbour_with(&BigUint::from(2_u8)));

        // "normal" value
        assert!(!BigUint::from(42_u8).shares_neighbour_with(&BigUint::from(45_u8)));
        assert!(!BigUint::from(45_u8).shares_neighbour_with(&BigUint::from(42_u8)));

        assert!(BigUint::from(42_u8).shares_neighbour_with(&BigUint::from(44_u8)));
        assert!(BigUint::from(44_u8).shares_neighbour_with(&BigUint::from(42_u8)));
    }

    #[test]
    fn predecessor() {
        assert_eq!(BigUint::from(42_u8).predecessor(), Some(BigUint::from(41_u8)));
        assert_eq!(BigUint::from(0_u8).predecessor(), None);
    }

    #[test]
    fn successor() {
        assert_eq!(BigUint::from(42_u8).successor(), Some(BigUint::from(43_u8)));
    }
}