ranges/domain/
i32.rs

1use core::{cmp::Ordering, ops::Bound};
2
3use super::{Domain, Iterable};
4
5impl Domain for i32 {
6    const DISCRETE: bool = true;
7
8    /// Always returns `Some(self - 1)` unless `self` is `Self::MIN`.
9    #[inline]
10    #[must_use]
11    #[allow(clippy::arithmetic_side_effects)]
12    fn predecessor(&self) -> Option<Self> {
13        match *self {
14            Self::MIN => None,
15            _ => Some(self - 1_i32),
16        }
17    }
18
19    /// Always returns `Some(self + 1)` unless `self` is `Self::MAX`.
20    #[inline]
21    #[must_use]
22    #[allow(clippy::arithmetic_side_effects)]
23    fn successor(&self) -> Option<Self> {
24        match *self {
25            Self::MAX => None,
26            _ => Some(self + 1_i32),
27        }
28    }
29
30    /// Returns `Included(Self::MIN)`.
31    #[inline]
32    #[must_use]
33    fn minimum() -> Bound<Self> {
34        Bound::Included(Self::MIN)
35    }
36
37    /// Returns `Included(Self::MAX)`.
38    #[inline]
39    #[must_use]
40    fn maximum() -> Bound<Self> {
41        Bound::Included(Self::MAX)
42    }
43
44    #[inline]
45    #[must_use]
46    #[allow(clippy::shadow_reuse, clippy::arithmetic_side_effects, clippy::as_conversions)]
47    fn shares_neighbour_with(&self, other: &Self) -> bool {
48        let (big, small) = match self.cmp(other) {
49            Ordering::Less => (other, self),
50            Ordering::Equal => return false,
51            Ordering::Greater => (self, other),
52        };
53
54        #[allow(clippy::cast_sign_loss)]
55        let big = (big ^ Self::MIN) as u32;
56        #[allow(clippy::cast_sign_loss)]
57        let small = (small ^ Self::MIN) as u32;
58
59        big - small == 2
60    }
61}
62
63impl Iterable for i32 {
64    type Output = Self;
65
66    #[inline]
67    #[must_use]
68    fn next(&self) -> Option<Self::Output> {
69        if *self == Self::MAX {
70            None
71        } else {
72            #[allow(clippy::arithmetic_side_effects)]
73            Some(*self + 1_i32)
74        }
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use crate::Domain;
81
82    #[test]
83    fn is_next_to() {
84        assert!(i32::MIN.is_next_to(&(i32::MIN + 1)));
85        assert!((i32::MIN + 1).is_next_to(&i32::MIN));
86        assert!(!i32::MIN.is_next_to(&(i32::MIN + 2)));
87        assert!(!i32::MIN.is_next_to(&i32::MAX));
88        assert!(!i32::MAX.is_next_to(&i32::MIN));
89    }
90
91    #[test]
92    fn shares_neighbour_with() {
93        // self-distance
94        assert!(!i32::MIN.shares_neighbour_with(&i32::MIN));
95
96        // "normal" value
97        assert!(!42_i32.shares_neighbour_with(&45));
98        assert!(!45_i32.shares_neighbour_with(&42));
99
100        assert!(42_i32.shares_neighbour_with(&44));
101        assert!(44_i32.shares_neighbour_with(&42));
102
103        // boundary check
104        assert!(!i32::MIN.shares_neighbour_with(&i32::MAX));
105        assert!(!i32::MAX.shares_neighbour_with(&i32::MIN));
106    }
107}