diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06260a0..e66265c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: include: - - rust: 1.6.0 # MSRV + - rust: 1.28.0 # MSRV - rust: stable - rust: beta - rust: nightly diff --git a/Cargo.toml b/Cargo.toml index 8fcf21a..84d0721 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "equivalent" -version = "1.0.1" -rust-version = "1.6" +version = "1.1.0" +rust-version = "1.28" license = "Apache-2.0 OR MIT" description = "Traits for key comparison in maps." repository = "https://github.com/cuviper/equivalent" diff --git a/src/lib.rs b/src/lib.rs index 09ba58d..0cd58ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,6 +56,12 @@ //! assert_eq!(q1.compare(&key), Ordering::Equal); //! assert_eq!(q2.compare(&key), Ordering::Less); //! assert_eq!(q3.compare(&key), Ordering::Greater); +//! +//! // You cannot use `Comparable` with the `RangeBounds::contains` method: +//! // assert!((q1..q3).contains(&key)); +//! +//! // But you can use the `ComparableRangeBounds::compare_contains` method: +//! assert!((q1..q3).compare_contains(&key)); //! } //! ``` @@ -63,6 +69,7 @@ use core::borrow::Borrow; use core::cmp::Ordering; +use core::ops::{Bound, RangeBounds}; /// Key equivalence trait. /// @@ -79,10 +86,10 @@ pub trait Equivalent { fn equivalent(&self, key: &K) -> bool; } -impl Equivalent for Q +impl Equivalent for Q where - Q: Eq, - K: Borrow, + Q: ?Sized + Eq, + K: ?Sized + Borrow, { #[inline] fn equivalent(&self, key: &K) -> bool { @@ -101,13 +108,45 @@ pub trait Comparable: Equivalent { fn compare(&self, key: &K) -> Ordering; } -impl Comparable for Q +impl Comparable for Q where - Q: Ord, - K: Borrow, + Q: ?Sized + Ord, + K: ?Sized + Borrow, { #[inline] fn compare(&self, key: &K) -> Ordering { Ord::cmp(self, key.borrow()) } } + +/// `ComparableRangeBounds` is implemented as an extention to `RangeBounds` to +/// allow for comparison of items with range bounds. +pub trait ComparableRangeBounds: RangeBounds { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// See the [crate-level documentation](crate). + fn compare_contains(&self, item: &K) -> bool + where + Q: Comparable, + K: ?Sized, + { + (match self.start_bound() { + Bound::Included(start) => start.compare(item) != Ordering::Greater, + Bound::Excluded(start) => start.compare(item) == Ordering::Less, + Bound::Unbounded => true, + }) && (match self.end_bound() { + Bound::Included(end) => end.compare(item) != Ordering::Less, + Bound::Excluded(end) => end.compare(item) == Ordering::Greater, + Bound::Unbounded => true, + }) + } +} + +impl ComparableRangeBounds for R +where + R: ?Sized + RangeBounds, + Q: ?Sized, +{ +}