parry3d/utils/
sorted_pair.rs

1use core::cmp::PartialOrd;
2use core::mem;
3use core::ops::Deref;
4
5/// A pair of elements sorted in increasing order.
6#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
8#[cfg_attr(
9    feature = "rkyv",
10    derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
11    archive(check_bytes)
12)]
13pub struct SortedPair<T: PartialOrd>([T; 2]);
14
15impl<T: PartialOrd> SortedPair<T> {
16    /// Sorts two elements in increasing order into a new pair.
17    pub fn new(element1: T, element2: T) -> Self {
18        if element1 > element2 {
19            SortedPair([element2, element1])
20        } else {
21            SortedPair([element1, element2])
22        }
23    }
24}
25
26impl<T: PartialOrd> Deref for SortedPair<T> {
27    type Target = (T, T);
28
29    fn deref(&self) -> &(T, T) {
30        unsafe { mem::transmute(self) }
31    }
32}
33
34// TODO: can we avoid these manual impls of Hash/PartialEq/Eq for the archived types?
35#[cfg(feature = "rkyv")]
36impl<T: rkyv::Archive + PartialOrd> core::hash::Hash for ArchivedSortedPair<T>
37where
38    [<T as rkyv::Archive>::Archived; 2]: core::hash::Hash,
39{
40    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
41        self.0.hash(state)
42    }
43}
44
45#[cfg(feature = "rkyv")]
46impl<T: rkyv::Archive + PartialOrd> PartialEq for ArchivedSortedPair<T>
47where
48    [<T as rkyv::Archive>::Archived; 2]: PartialEq,
49{
50    fn eq(&self, other: &Self) -> bool {
51        self.0 == other.0
52    }
53}
54
55#[cfg(feature = "rkyv")]
56impl<T: rkyv::Archive + PartialOrd> Eq for ArchivedSortedPair<T> where
57    [<T as rkyv::Archive>::Archived; 2]: Eq
58{
59}