use std::cmp::Ordering;
pub trait Orderer<T> {
fn compare(&self, left: &T, right: &T) -> Ordering;
}
#[derive(Default)]
pub struct OrdOrderer {}
impl OrdOrderer {
pub fn new() -> Self {
Default::default()
}
}
impl<T: Ord> Orderer<T> for OrdOrderer {
fn compare(&self, left: &T, right: &T) -> Ordering {
left.cmp(right)
}
}
pub struct KeyOrderer<F> {
key_extractor: F,
}
impl<F> KeyOrderer<F> {
pub fn new<T, K>(key_extractor: F) -> Self
where
F: Fn(&T) -> K,
K: Ord,
{
Self { key_extractor }
}
}
impl<F, T, K> Orderer<T> for KeyOrderer<F>
where
F: Fn(&T) -> K,
K: Ord,
{
fn compare(&self, left: &T, right: &T) -> Ordering {
let left = (self.key_extractor)(left);
let right = (self.key_extractor)(right);
left.cmp(&right)
}
}
pub struct FuncOrderer<F> {
comparator: F,
}
impl<F> FuncOrderer<F> {
pub fn new<T>(comparator: F) -> Self
where
F: Fn(&T, &T) -> Ordering,
{
Self { comparator }
}
}
impl<F, T> Orderer<T> for FuncOrderer<F>
where
F: Fn(&T, &T) -> Ordering,
{
fn compare(&self, left: &T, right: &T) -> Ordering {
(self.comparator)(left, right)
}
}