From 1f73f8028fffce5c737412b9e8fb1b5145f67a33 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 28 May 2020 14:51:11 -0400 Subject: util: Add a wrapper to implement Ord on top of PartialOrd This allows nearest neighbors implementations to sort things by distance or coordinate. --- src/lib.rs | 2 ++ src/util.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/util.rs diff --git a/src/lib.rs b/src/lib.rs index 2f6504a..897a5e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,8 @@ pub mod distance; pub mod euclid; pub mod exhaustive; +mod util; + pub use coords::Coordinates; pub use distance::{Distance, Metric, Proximity}; pub use euclid::{euclidean_distance, Euclidean, EuclideanDistance}; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..f838a9b --- /dev/null +++ b/src/util.rs @@ -0,0 +1,54 @@ +//! Internal utilities. + +use std::cmp::Ordering; + +/// A wrapper that converts a partial ordering into a total one by panicking. +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] +pub struct Ordered(T); + +impl Ordered { + /// Wrap a value. + pub fn new(item: T) -> Self { + Self(item) + } +} + +impl From for Ordered { + fn from(item: T) -> Self { + Self::new(item) + } +} + +impl Ord for Ordered { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).expect("Comparison between unordered items") + } +} + +impl Eq for Ordered {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ordered() { + let one = Ordered::new(1.0); + let two = Ordered::new(2.0); + + assert_eq!(one.cmp(&one), Ordering::Equal); + assert_eq!(one.cmp(&two), Ordering::Less); + assert_eq!(two.cmp(&one), Ordering::Greater); + } + + #[test] + #[should_panic(expected = "Comparison between unordered items")] + fn test_unordered() { + let one = Ordered::new(1.0); + let nan = Ordered::new(f64::NAN); + + assert!(!(one < nan)); + assert!(!(nan < one)); + let _ = one.cmp(&nan); + } +} -- cgit v1.2.3