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}