diff options
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/util.rs | 54 |
2 files changed, 56 insertions, 0 deletions
@@ -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>(T); + +impl<T> Ordered<T> { + /// Wrap a value. + pub fn new(item: T) -> Self { + Self(item) + } +} + +impl<T> From<T> for Ordered<T> { + fn from(item: T) -> Self { + Self::new(item) + } +} + +impl<T: PartialOrd> Ord for Ordered<T> { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).expect("Comparison between unordered items") + } +} + +impl<T: PartialEq> Eq for Ordered<T> {} + +#[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); + } +} |