diff --git a/src/bound_ord.rs b/src/bound_ord.rs index 2fcf85c..a284cf0 100644 --- a/src/bound_ord.rs +++ b/src/bound_ord.rs @@ -34,7 +34,7 @@ use serde::{Deserialize, Serialize}; /// [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html /// [`comparator`]: https://stackoverflow.com/q/34028324 /// [`Cursor`]: https://github.com/rust-lang/rfcs/issues/1778 -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub(crate) enum BoundOrd { /// Mirror of [`Bound::Included`] /// There is no need for different Start and End variations as the @@ -69,49 +69,60 @@ impl BoundOrd { } } -impl Eq for BoundOrd where T: PartialEq {} - -#[rustfmt::skip] -impl PartialOrd for BoundOrd +impl Ord for BoundOrd where - T: PartialOrd, + T: Ord, { + #[rustfmt::skip] #[tested] - fn partial_cmp(&self, other: &Self) -> Option { - match (self, other) { - (BoundOrd::Included(start1), BoundOrd::Included(start2)) => start1.partial_cmp(start2), - (BoundOrd::Included(start1), BoundOrd::StartExcluded(start2)) => partial_cmp_with_priority(start1, start2, true), - (BoundOrd::Included(start1), BoundOrd::EndExcluded(start2)) => partial_cmp_with_priority(start1, start2, false), - (BoundOrd::Included(_), BoundOrd::EndUnbounded) => Some(Ordering::Less), - (BoundOrd::Included(_), BoundOrd::StartUnbounded) => Some(Ordering::Greater), + fn cmp(&self, other: &Self) ->Ordering { + match (self, other) { + (BoundOrd::Included(start1), BoundOrd::Included(start2)) => start1.partial_cmp(start2), + (BoundOrd::Included(start1), BoundOrd::StartExcluded(start2)) => partial_cmp_with_priority(start1, start2, true), + (BoundOrd::Included(start1), BoundOrd::EndExcluded(start2)) => partial_cmp_with_priority(start1, start2, false), + (BoundOrd::Included(_), BoundOrd::EndUnbounded) => Some(Ordering::Less), + (BoundOrd::Included(_), BoundOrd::StartUnbounded) => Some(Ordering::Greater), - (BoundOrd::StartExcluded(start1), BoundOrd::StartExcluded(start2)) => start1.partial_cmp(start2), - (BoundOrd::StartExcluded(start1), BoundOrd::Included(start2)) => partial_cmp_with_priority(start1, start2, false), - (BoundOrd::StartExcluded(start1), BoundOrd::EndExcluded(start2)) => partial_cmp_with_priority(start1, start2, false), - (BoundOrd::StartExcluded(_), BoundOrd::StartUnbounded) => Some(Ordering::Greater), - (BoundOrd::StartExcluded(_), BoundOrd::EndUnbounded) => Some(Ordering::Less), + (BoundOrd::StartExcluded(start1), BoundOrd::StartExcluded(start2)) => start1.partial_cmp(start2), + (BoundOrd::StartExcluded(start1), BoundOrd::Included(start2)) => partial_cmp_with_priority(start1, start2, false), + (BoundOrd::StartExcluded(start1), BoundOrd::EndExcluded(start2)) => partial_cmp_with_priority(start1, start2, false), + (BoundOrd::StartExcluded(_), BoundOrd::StartUnbounded) => Some(Ordering::Greater), + (BoundOrd::StartExcluded(_), BoundOrd::EndUnbounded) => Some(Ordering::Less), (BoundOrd::StartUnbounded, BoundOrd::Included(_)) => Some(Ordering::Less), (BoundOrd::StartUnbounded, BoundOrd::StartExcluded(_)) => Some(Ordering::Less), (BoundOrd::StartUnbounded, BoundOrd::EndExcluded(_)) => Some(Ordering::Less), - (BoundOrd::StartUnbounded, BoundOrd::StartUnbounded) => Some(Ordering::Equal), - (BoundOrd::StartUnbounded, BoundOrd::EndUnbounded) => Some(Ordering::Less), + (BoundOrd::StartUnbounded, BoundOrd::StartUnbounded) => Some(Ordering::Equal), + (BoundOrd::StartUnbounded, BoundOrd::EndUnbounded) => Some(Ordering::Less), - (BoundOrd::EndExcluded(start1), BoundOrd::EndExcluded(start2)) => start1.partial_cmp(start2), - (BoundOrd::EndExcluded(start1), BoundOrd::Included(start2)) => partial_cmp_with_priority(start1, start2, true), - (BoundOrd::EndExcluded(start1), BoundOrd::StartExcluded(start2)) => partial_cmp_with_priority(start1, start2, true), - (BoundOrd::EndExcluded(_), BoundOrd::StartUnbounded) => Some(Ordering::Greater), - (BoundOrd::EndExcluded(_), BoundOrd::EndUnbounded) => Some(Ordering::Less), + (BoundOrd::EndExcluded(start1), BoundOrd::EndExcluded(start2)) => start1.partial_cmp(start2), + (BoundOrd::EndExcluded(start1), BoundOrd::Included(start2)) => partial_cmp_with_priority(start1, start2, true), + (BoundOrd::EndExcluded(start1), BoundOrd::StartExcluded(start2)) => partial_cmp_with_priority(start1, start2, true), + (BoundOrd::EndExcluded(_), BoundOrd::StartUnbounded) => Some(Ordering::Greater), + (BoundOrd::EndExcluded(_), BoundOrd::EndUnbounded) => Some(Ordering::Less), (BoundOrd::EndUnbounded, BoundOrd::Included(_)) => Some(Ordering::Greater), (BoundOrd::EndUnbounded, BoundOrd::StartExcluded(_)) => Some(Ordering::Greater), (BoundOrd::EndUnbounded, BoundOrd::EndExcluded(_)) => Some(Ordering::Greater), - (BoundOrd::EndUnbounded, BoundOrd::EndUnbounded) => Some(Ordering::Equal), - (BoundOrd::EndUnbounded, BoundOrd::StartUnbounded) => Some(Ordering::Greater), - } + (BoundOrd::EndUnbounded, BoundOrd::EndUnbounded) => Some(Ordering::Equal), + (BoundOrd::EndUnbounded, BoundOrd::StartUnbounded) => Some(Ordering::Greater), + } +} +} + +impl PartialOrd for BoundOrd where T: Ord {} + +impl PartialEq for BoundOrd +where + T: Ord, +{ + fn eq(&self, other: &Self) -> bool { + self.cmp(&other).is_eq() } } +impl Eq for BoundOrd where T: Ord {} + /// If they are equal say the item with priority is larger /// where false means left has priority and true means right. #[parent_tested] @@ -134,16 +145,6 @@ where }) } -impl Ord for BoundOrd -where - T: PartialOrd, -{ - #[trivial] - fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).unwrap() - } -} - impl From> for Bound { #[trivial] fn from(start_bound: BoundOrd) -> Bound { diff --git a/src/lib.rs b/src/lib.rs index 507e14a..bfb10af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,6 +228,7 @@ along with range_bounds_map. If not, see . pub(crate) mod bound_ord; pub mod range_bounds_map; pub mod range_bounds_set; +pub(crate) mod start_range_bounds_ord_wrapper; pub mod try_from_bounds; pub use crate::range_bounds_map::{ diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs index 03723f6..8458df2 100644 --- a/src/range_bounds_map.rs +++ b/src/range_bounds_map.rs @@ -32,6 +32,7 @@ use serde::ser::SerializeMap; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::bound_ord::BoundOrd; +use crate::start_range_bounds_ord_wrapper::StartRangeBoundsOrdWrapper; use crate::TryFromBounds; /// An ordered map of non-overlapping [`RangeBounds`] based on [`BTreeMap`]. @@ -126,12 +127,12 @@ use crate::TryFromBounds; /// /// [`RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html /// [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone)] pub struct RangeBoundsMap where I: PartialOrd, { - starts: BTreeMap, (K, V)>, + inner: BTreeMap, V>, } /// An error type to represent a [`RangeBounds`] overlapping another @@ -2130,10 +2131,11 @@ where Q: RangeBounds, { type Item = (&'a K, &'a V); - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { let (key, value) = self.cursor.value()?; if overlaps(self.query_range_bounds, key) { + self.cursor.move_next(); return Some((key, value)); } else { return None; diff --git a/src/range_bounds_set.rs b/src/range_bounds_set.rs index a6ef124..972667e 100644 --- a/src/range_bounds_set.rs +++ b/src/range_bounds_set.rs @@ -109,7 +109,7 @@ use crate::{ /// ``` /// /// [`RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone)] pub struct RangeBoundsSet where I: PartialOrd, diff --git a/src/start_range_bounds_ord_wrapper.rs b/src/start_range_bounds_ord_wrapper.rs new file mode 100644 index 0000000..77aaf61 --- /dev/null +++ b/src/start_range_bounds_ord_wrapper.rs @@ -0,0 +1,65 @@ +/* +Copyright 2022 James Forster + +This file is part of range_bounds_map. + +range_bounds_map is free software: you can redistribute it and/or +modify it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +range_bounds_map is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with range_bounds_map. If not, see . +*/ + +use std::cmp::Ordering; +use std::marker::PhantomData; +use std::ops::RangeBounds; + +use crate::bound_ord::BoundOrd; + +#[derive(Debug, Clone)] +pub struct StartRangeBoundsOrdWrapper { + phantom: PhantomData, + inner: K, +} + +impl Ord for StartRangeBoundsOrdWrapper +where + I: Ord, + K: RangeBounds, +{ + fn cmp(&self, other: &Self) -> Ordering { + BoundOrd::start(self.inner.start_bound()) + .cmp(&BoundOrd::start(other.inner.start_bound())) + } +} +impl PartialOrd for StartRangeBoundsOrdWrapper +where + I: Ord, + K: RangeBounds, +{ + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} +impl PartialEq for StartRangeBoundsOrdWrapper +where + I: Ord, + K: RangeBounds, +{ + fn eq(&self, other: &Self) -> bool { + self.cmp(&other).is_eq() + } +} +impl Eq for StartRangeBoundsOrdWrapper +where + I: Ord, + K: RangeBounds, +{ +}