lattices/
ord.rs

1use std::cmp::Ordering;
2
3use crate::{DeepReveal, IsBot, IsTop, LatticeFrom, LatticeOrd, Merge};
4
5/// A totally ordered max lattice. Merging returns the larger value.
6///
7/// Note that the [`Default::default()`] value for numeric type is `MIN`, not zero.
8#[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    /// Create a new `Max` lattice instance from a `T`.
14    pub fn new(val: T) -> Self {
15        Self(val)
16    }
17
18    /// Create a new `Max` lattice instance from an `Into<T>` value.
19    pub fn from(val: impl Into<T>) -> Self {
20        Self::new(val.into())
21    }
22
23    /// Reveal the inner value as a shared reference.
24    pub fn as_reveal_ref(&self) -> &T {
25        &self.0
26    }
27
28    /// Reveal the inner value as an exclusive reference.
29    pub fn as_reveal_mut(&mut self) -> &mut T {
30        &mut self.0
31    }
32
33    /// Gets the inner by value, consuming self.
34    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/// A totally ordered min lattice. Merging returns the smaller value.
70///
71/// This means the lattice order is the reverse of what you might naturally expect: 0 is greater
72/// than 1.
73///
74/// Note that the [`Default::default()`] value for numeric type is `MAX`, not zero.
75#[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    /// Create a new `Min` lattice instance from a `T`.
81    pub fn new(val: T) -> Self {
82        Self(val)
83    }
84
85    /// Create a new `Min` lattice instance from an `Into<T>` value.
86    pub fn new_from(val: impl Into<T>) -> Self {
87        Self::new(val.into())
88    }
89
90    /// Reveal the inner value as a shared reference.
91    pub fn as_reveal_ref(&self) -> &T {
92        &self.0
93    }
94
95    /// Reveal the inner value as an exclusive reference.
96    pub fn as_reveal_mut(&mut self) -> &mut T {
97        &mut self.0
98    }
99
100    /// Gets the inner by value, consuming self.
101    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
153// IsTop, IsBot, Default impls
154impl 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}