inter_val/
bound_type.rs

1use std::marker::PhantomData;
2
3use crate::traits::{Boundary, BoundaryOf, Flip, IntoGeneral};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
6pub struct Inclusive;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
9pub struct Exclusive;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
12pub enum BoundType {
13    Inclusive,
14    Exclusive,
15}
16
17#[derive(Debug, Clone, Copy)]
18pub struct Left;
19
20#[derive(Debug, Clone, Copy)]
21pub struct Right;
22
23#[derive(Debug, Clone, Copy)]
24pub struct BoundOrderingKey<B, LR>(B, PhantomData<LR>);
25
26mod ordering {
27    use super::{BoundOrderingKey, Left, Right};
28    use crate::{BoundType, Exclusive, Inclusive};
29
30    impl<B: PartialEq, LR> PartialEq for BoundOrderingKey<B, LR> {
31        fn eq(&self, other: &Self) -> bool {
32            self.0 == other.0
33        }
34    }
35    impl<B: Eq, LR> Eq for BoundOrderingKey<B, LR> {}
36
37    macro_rules! impl_ord {
38        (($lhs:ident, $rhs:ident): $type:ty => $body:expr) => {
39            impl PartialOrd for $type {
40                fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
41                    Some(self.cmp(other))
42                }
43            }
44            impl Ord for $type {
45                fn cmp(&self, other: &Self) -> std::cmp::Ordering {
46                    let $lhs = self;
47                    let $rhs = other;
48                    $body
49                }
50            }
51        };
52    }
53
54    impl_ord!((_lhs, _rhs): BoundOrderingKey<Inclusive, Left> => std::cmp::Ordering::Equal);
55    impl_ord!((_lhs, _rhs): BoundOrderingKey<Exclusive, Left> => std::cmp::Ordering::Equal);
56    impl_ord!((_lhs, _rhs): BoundOrderingKey<Inclusive, Right> => std::cmp::Ordering::Equal);
57    impl_ord!((_lhs, _rhs): BoundOrderingKey<Exclusive, Right> => std::cmp::Ordering::Equal);
58    impl_ord!((lhs, rhs): BoundOrderingKey<BoundType, Left> => match (lhs.0, rhs.0) {
59        (BoundType::Inclusive, BoundType::Inclusive) => std::cmp::Ordering::Equal,
60        (BoundType::Inclusive, BoundType::Exclusive) => std::cmp::Ordering::Less,
61        (BoundType::Exclusive, BoundType::Inclusive) => std::cmp::Ordering::Greater,
62        (BoundType::Exclusive, BoundType::Exclusive) => std::cmp::Ordering::Equal,
63    });
64    impl_ord!((lhs, rhs): BoundOrderingKey<BoundType, Right> => match (lhs.0, rhs.0) {
65        (BoundType::Inclusive, BoundType::Inclusive) => std::cmp::Ordering::Equal,
66        (BoundType::Inclusive, BoundType::Exclusive) => std::cmp::Ordering::Greater,
67        (BoundType::Exclusive, BoundType::Inclusive) => std::cmp::Ordering::Less,
68        (BoundType::Exclusive, BoundType::Exclusive) => std::cmp::Ordering::Equal,
69    });
70}
71
72impl IntoGeneral for Inclusive {
73    type General = BoundType;
74    fn into_general(self) -> Self::General {
75        BoundType::Inclusive
76    }
77}
78impl IntoGeneral for Exclusive {
79    type General = BoundType;
80    fn into_general(self) -> Self::General {
81        BoundType::Exclusive
82    }
83}
84
85impl Flip for Inclusive {
86    type Flip = Exclusive;
87    fn flip(self) -> Self::Flip {
88        Exclusive
89    }
90}
91impl Flip for Exclusive {
92    type Flip = Inclusive;
93    fn flip(self) -> Self::Flip {
94        Inclusive
95    }
96}
97impl Flip for BoundType {
98    type Flip = Self;
99    fn flip(self) -> Self {
100        match self {
101            Self::Inclusive => Self::Exclusive,
102            Self::Exclusive => Self::Inclusive,
103        }
104    }
105}
106impl Flip for Left {
107    type Flip = Right;
108    fn flip(self) -> Self::Flip {
109        Right
110    }
111}
112impl Flip for Right {
113    type Flip = Left;
114    fn flip(self) -> Self::Flip {
115        Left
116    }
117}
118
119impl PartialEq<BoundType> for Inclusive {
120    fn eq(&self, other: &BoundType) -> bool {
121        match other {
122            BoundType::Inclusive => true,
123            BoundType::Exclusive => false,
124        }
125    }
126}
127impl PartialEq<BoundType> for Exclusive {
128    fn eq(&self, other: &BoundType) -> bool {
129        match other {
130            BoundType::Inclusive => false,
131            BoundType::Exclusive => true,
132        }
133    }
134}
135
136impl Boundary for Inclusive {
137    fn less<T: PartialOrd>(&self, this: &T, t: &T) -> bool {
138        this <= t
139    }
140}
141impl Boundary for Exclusive {
142    fn less<T: PartialOrd>(&self, this: &T, t: &T) -> bool {
143        this < t
144    }
145}
146impl Boundary for BoundType {
147    fn less<T: PartialOrd>(&self, this: &T, t: &T) -> bool {
148        match self {
149            BoundType::Inclusive => this <= t,
150            BoundType::Exclusive => this < t,
151        }
152    }
153}
154
155impl<LR> BoundaryOf<LR> for Inclusive
156where
157    BoundOrderingKey<Self, LR>: Ord,
158{
159    type Ordered = BoundOrderingKey<Self, LR>;
160    fn into_ordered(self) -> Self::Ordered {
161        BoundOrderingKey(self, PhantomData)
162    }
163}
164impl<LR> BoundaryOf<LR> for Exclusive
165where
166    BoundOrderingKey<Self, LR>: Ord,
167{
168    type Ordered = BoundOrderingKey<Self, LR>;
169    fn into_ordered(self) -> Self::Ordered {
170        BoundOrderingKey(self, PhantomData)
171    }
172}
173impl<LR> BoundaryOf<LR> for BoundType
174where
175    BoundOrderingKey<Self, LR>: Ord,
176{
177    type Ordered = BoundOrderingKey<Self, LR>;
178    fn into_ordered(self) -> Self::Ordered {
179        BoundOrderingKey(self, PhantomData)
180    }
181}