use std::cmp::Ordering::{self, Equal, Greater, Less};
pub trait Compare<L: ?Sized, R: ?Sized = L> {
fn compare(&self, l: &L, r: &R) -> Ordering;
fn compares_lt(&self, l: &L, r: &R) -> bool {
self.compare(l, r) == Less
}
fn compares_le(&self, l: &L, r: &R) -> bool {
self.compare(l, r) != Greater
}
fn compares_ge(&self, l: &L, r: &R) -> bool {
self.compare(l, r) != Less
}
fn compares_gt(&self, l: &L, r: &R) -> bool {
self.compare(l, r) == Greater
}
fn compares_eq(&self, l: &L, r: &R) -> bool {
self.compare(l, r) == Equal
}
fn compares_ne(&self, l: &L, r: &R) -> bool {
self.compare(l, r) != Equal
}
}
impl<F, L: ?Sized, R: ?Sized> Compare<L, R> for F
where
F: Fn(&L, &R) -> Ordering,
{
fn compare(&self, l: &L, r: &R) -> Ordering {
(*self)(l, r)
}
}
#[cfg(test)]
mod tests {
use std::cmp::Ordering::{Equal, Greater, Less};
use rstest::rstest;
use super::*;
struct Natural;
impl Compare<i32> for Natural {
fn compare(&self, l: &i32, r: &i32) -> Ordering {
l.cmp(r)
}
}
#[rstest]
fn test_compare_trait() {
let cmp = Natural;
assert_eq!(cmp.compare(&1, &2), Less);
assert_eq!(cmp.compare(&2, &1), Greater);
assert_eq!(cmp.compare(&1, &1), Equal);
}
#[rstest]
fn test_closure_comparator() {
let cmp = |l: &i32, r: &i32| l.cmp(r);
assert_eq!(cmp.compare(&1, &2), Less);
assert_eq!(cmp.compare(&2, &1), Greater);
assert_eq!(cmp.compare(&1, &1), Equal);
}
#[rstest]
fn test_reversed_ordering() {
let cmp = |l: &i32, r: &i32| l.cmp(r).reverse();
assert_eq!(cmp.compare(&1, &2), Greater);
assert_eq!(cmp.compare(&2, &1), Less);
}
}