1use std::cmp::Ordering;
2
3use crate::{DeepReveal, IsBot, IsTop, LatticeFrom, LatticeOrd, Merge};
4
5#[repr(transparent)]
9#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Max<T>(T);
12impl<T> Max<T> {
13 pub fn new(val: T) -> Self {
15 Self(val)
16 }
17
18 pub fn from(val: impl Into<T>) -> Self {
20 Self::new(val.into())
21 }
22
23 pub fn as_reveal_ref(&self) -> &T {
25 &self.0
26 }
27
28 pub fn as_reveal_mut(&mut self) -> &mut T {
30 &mut self.0
31 }
32
33 pub fn into_reveal(self) -> T {
35 self.0
36 }
37}
38
39impl<T> DeepReveal for Max<T> {
40 type Revealed = T;
41
42 fn deep_reveal(self) -> Self::Revealed {
43 self.0
44 }
45}
46
47impl<T> Merge<Max<T>> for Max<T>
48where
49 T: Ord,
50{
51 fn merge(&mut self, other: Max<T>) -> bool {
52 if self.0 < other.0 {
53 self.0 = other.0;
54 true
55 } else {
56 false
57 }
58 }
59}
60
61impl<T> LatticeFrom<Max<T>> for Max<T> {
62 fn lattice_from(other: Max<T>) -> Self {
63 other
64 }
65}
66
67impl<T> LatticeOrd<Self> for Max<T> where Self: PartialOrd<Self> {}
68
69#[repr(transparent)]
76#[derive(Copy, Clone, Debug, PartialEq, Eq)]
77#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78pub struct Min<T>(T);
79impl<T> Min<T> {
80 pub fn new(val: T) -> Self {
82 Self(val)
83 }
84
85 pub fn new_from(val: impl Into<T>) -> Self {
87 Self::new(val.into())
88 }
89
90 pub fn as_reveal_ref(&self) -> &T {
92 &self.0
93 }
94
95 pub fn as_reveal_mut(&mut self) -> &mut T {
97 &mut self.0
98 }
99
100 pub fn into_reveal(self) -> T {
102 self.0
103 }
104}
105
106impl<T> DeepReveal for Min<T> {
107 type Revealed = T;
108
109 fn deep_reveal(self) -> Self::Revealed {
110 self.0
111 }
112}
113
114impl<T> Merge<Min<T>> for Min<T>
115where
116 T: Ord,
117{
118 fn merge(&mut self, other: Min<T>) -> bool {
119 if other.0 < self.0 {
120 self.0 = other.0;
121 true
122 } else {
123 false
124 }
125 }
126}
127
128impl<T> LatticeFrom<Min<T>> for Min<T> {
129 fn lattice_from(other: Min<T>) -> Self {
130 other
131 }
132}
133
134impl<T> PartialOrd for Min<T>
135where
136 T: PartialOrd,
137{
138 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
139 self.0.partial_cmp(&other.0).map(Ordering::reverse)
140 }
141}
142impl<T> LatticeOrd<Self> for Min<T> where Self: PartialOrd<Self> {}
143
144impl<T> Ord for Min<T>
145where
146 T: Ord,
147{
148 fn cmp(&self, other: &Self) -> Ordering {
149 self.0.cmp(&other.0).reverse()
150 }
151}
152
153impl IsTop for Max<()> {
155 fn is_top(&self) -> bool {
156 true
157 }
158}
159impl IsBot for Max<()> {
160 fn is_bot(&self) -> bool {
161 true
162 }
163}
164impl IsTop for Min<()> {
165 fn is_top(&self) -> bool {
166 true
167 }
168}
169impl IsBot for Min<()> {
170 fn is_bot(&self) -> bool {
171 true
172 }
173}
174
175impl IsTop for Max<bool> {
176 fn is_top(&self) -> bool {
177 self.0
178 }
179}
180impl IsBot for Max<bool> {
181 fn is_bot(&self) -> bool {
182 !self.0
183 }
184}
185impl Default for Max<bool> {
186 fn default() -> Self {
187 Self(false)
188 }
189}
190impl IsTop for Min<bool> {
191 fn is_top(&self) -> bool {
192 !self.0
193 }
194}
195impl IsBot for Min<bool> {
196 fn is_bot(&self) -> bool {
197 self.0
198 }
199}
200impl Default for Min<bool> {
201 fn default() -> Self {
202 Self(true)
203 }
204}
205
206impl IsTop for Max<char> {
207 fn is_top(&self) -> bool {
208 char::MAX == self.0
209 }
210}
211impl IsBot for Max<char> {
212 fn is_bot(&self) -> bool {
213 '\x00' == self.0
214 }
215}
216impl Default for Max<char> {
217 fn default() -> Self {
218 Self('\x00')
219 }
220}
221impl IsTop for Min<char> {
222 fn is_top(&self) -> bool {
223 '\x00' == self.0
224 }
225}
226impl IsBot for Min<char> {
227 fn is_bot(&self) -> bool {
228 char::MAX == self.0
229 }
230}
231impl Default for Min<char> {
232 fn default() -> Self {
233 Self(char::MAX)
234 }
235}
236
237macro_rules! impls_numeric {
238 (
239 $( $x:ty ),*
240 ) => {
241 $(
242 impl IsTop for Max<$x> {
243 fn is_top(&self) -> bool {
244 <$x>::MAX == self.0
245 }
246 }
247 impl IsBot for Max<$x> {
248 fn is_bot(&self) -> bool {
249 <$x>::MIN == self.0
250 }
251 }
252
253 impl Default for Max<$x> {
254 fn default() -> Self {
255 Self(<$x>::MIN)
256 }
257 }
258
259 impl IsTop for Min<$x> {
260 fn is_top(&self) -> bool {
261 <$x>::MIN == self.0
262 }
263 }
264 impl IsBot for Min<$x> {
265 fn is_bot(&self) -> bool {
266 <$x>::MAX == self.0
267 }
268 }
269 impl Default for Min<$x> {
270 fn default() -> Self {
271 Self(<$x>::MAX)
272 }
273 }
274 )*
275 };
276}
277impls_numeric! {
278 isize, i8, i16, i32, i64, i128, usize, u8, u16, u32, u64, u128
279}
280
281#[cfg(test)]
282mod test {
283 use std::cmp::Ordering::*;
284
285 use super::*;
286 use crate::test::check_all;
287
288 #[test]
289 fn ordering() {
290 assert_eq!(Max::new(0).cmp(&Max::new(0)), Equal);
291 assert_eq!(Max::new(0).cmp(&Max::new(1)), Less);
292 assert_eq!(Max::new(1).cmp(&Max::new(0)), Greater);
293
294 assert_eq!(Min::new(0).cmp(&Min::new(0)), Equal);
295 assert_eq!(Min::new(0).cmp(&Min::new(1)), Greater);
296 assert_eq!(Min::new(1).cmp(&Min::new(0)), Less);
297 }
298
299 #[test]
300 fn eq() {
301 assert!(Max::new(0).eq(&Max::new(0)));
302 assert!(!Max::new(0).eq(&Max::new(1)));
303 assert!(!Max::new(1).eq(&Max::new(0)));
304
305 assert!(Min::new(0).eq(&Min::new(0)));
306 assert!(!Min::new(0).eq(&Min::new(1)));
307 assert!(!Min::new(1).eq(&Min::new(0)));
308 }
309
310 #[test]
311 fn consistency_max_bool() {
312 let items = &[Max::new(false), Max::new(true)];
313 check_all(items);
314 }
315
316 #[test]
317 fn consistency_min_bool() {
318 let items = &[Min::new(false), Min::new(true)];
319 check_all(items);
320 }
321
322 #[test]
323 fn consistency_max_char() {
324 let items: Vec<_> = "\x00\u{10FFFF}✨🤦♀️踊るx".chars().map(Max::new).collect();
325 check_all(&items);
326 }
327
328 #[test]
329 fn consistency_min_char() {
330 let items: Vec<_> = "\x00\u{10FFFF}✨🤦♀️踊るx".chars().map(Min::new).collect();
331 check_all(&items);
332 }
333
334 #[test]
335 fn consistency_max_i32() {
336 let items = &[
337 Max::new(0),
338 Max::new(1),
339 Max::new(i32::MIN),
340 Max::new(i32::MAX),
341 ];
342 check_all(items);
343 }
344
345 #[test]
346 fn consistency_min_i32() {
347 let items = &[
348 Min::new(0),
349 Min::new(1),
350 Min::new(i32::MIN),
351 Min::new(i32::MAX),
352 ];
353 check_all(items);
354 }
355}