1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/// Result returned by [`Comparator::compare`].
#[derive(Debug, PartialEq, Eq)]
pub enum Comparison {
    L,
    /// Compared values were equal.
    E,
    R,
}

/// Returns [`Comparison`] saying which value is smaller.
///
/// ```rust
/// # use radn::flow::comparator::*;
/// assert_eq!(DefaultComparator.compare(&1, &3), Comparison::L);
/// assert_eq!(DefaultComparator.compare(&2, &2), Comparison::E);
/// assert_eq!(DefaultComparator.compare(&3, &1), Comparison::R);
/// ```
pub trait Comparator<A>: Send + Sync {
    fn compare(&self, kl: &A, kr: &A) -> Comparison;

    fn equal(&self, kl: &A, kr: &A) -> bool {
        matches!(self.compare(kl, kr), Comparison::E)
    }
}

/// Implementation of a [Comparator] relying on [`Ord`].
pub struct DefaultComparator;

impl<A: Ord> Comparator<A> for DefaultComparator {
    fn compare(&self, kl: &A, kr: &A) -> Comparison {
        match kl.cmp(kr) {
            std::cmp::Ordering::Less => Comparison::L,
            std::cmp::Ordering::Equal => Comparison::E,
            std::cmp::Ordering::Greater => Comparison::R,
        }
    }
}

pub struct RcComparator<C>(C);

mod rc_comparator_impl {
    use super::*;
    use std::sync::Arc;

    impl<A, C: Comparator<A>> Comparator<Arc<A>> for RcComparator<C> {
        fn compare(&self, kl: &Arc<A>, kr: &Arc<A>) -> Comparison {
            self.0.compare(kl, kr)
        }
    }
}