reworked the common 4 trait impls and bounds and re-added a startBoundOrd wrapper

This commit is contained in:
ripytide
2023-04-01 15:26:10 +01:00
parent 40912765cc
commit 8d2609baf9
5 changed files with 111 additions and 42 deletions
+39 -38
View File
@@ -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<T> {
/// Mirror of [`Bound::Included`]
/// There is no need for different Start and End variations as the
@@ -69,49 +69,60 @@ impl<T> BoundOrd<T> {
}
}
impl<T> Eq for BoundOrd<T> where T: PartialEq {}
#[rustfmt::skip]
impl<T> PartialOrd for BoundOrd<T>
impl<T> Ord for BoundOrd<T>
where
T: PartialOrd,
T: Ord,
{
#[rustfmt::skip]
#[tested]
fn partial_cmp(&self, other: &Self) -> Option<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),
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<T> PartialOrd for BoundOrd<T> where T: Ord {}
impl<T> PartialEq for BoundOrd<T>
where
T: Ord,
{
fn eq(&self, other: &Self) -> bool {
self.cmp(&other).is_eq()
}
}
impl<T> Eq for BoundOrd<T> 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<T> Ord for BoundOrd<T>
where
T: PartialOrd,
{
#[trivial]
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
impl<T> From<BoundOrd<T>> for Bound<T> {
#[trivial]
fn from(start_bound: BoundOrd<T>) -> Bound<T> {
+1
View File
@@ -228,6 +228,7 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
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::{
+5 -3
View File
@@ -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<I, K, V>
where
I: PartialOrd,
{
starts: BTreeMap<BoundOrd<I>, (K, V)>,
inner: BTreeMap<StartRangeBoundsOrdWrapper<I, K>, V>,
}
/// An error type to represent a [`RangeBounds`] overlapping another
@@ -2130,10 +2131,11 @@ where
Q: RangeBounds<I>,
{
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
fn next(&mut self) -> Option<Self::Item> {
let (key, value) = self.cursor.value()?;
if overlaps(self.query_range_bounds, key) {
self.cursor.move_next();
return Some((key, value));
} else {
return None;
+1 -1
View File
@@ -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<I, K>
where
I: PartialOrd,
+65
View File
@@ -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 <https://www.gnu.org/licenses/>.
*/
use std::cmp::Ordering;
use std::marker::PhantomData;
use std::ops::RangeBounds;
use crate::bound_ord::BoundOrd;
#[derive(Debug, Clone)]
pub struct StartRangeBoundsOrdWrapper<I, K> {
phantom: PhantomData<I>,
inner: K,
}
impl<I, K> Ord for StartRangeBoundsOrdWrapper<I, K>
where
I: Ord,
K: RangeBounds<I>,
{
fn cmp(&self, other: &Self) -> Ordering {
BoundOrd::start(self.inner.start_bound())
.cmp(&BoundOrd::start(other.inner.start_bound()))
}
}
impl<I, K> PartialOrd for StartRangeBoundsOrdWrapper<I, K>
where
I: Ord,
K: RangeBounds<I>,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(&other))
}
}
impl<I, K> PartialEq for StartRangeBoundsOrdWrapper<I, K>
where
I: Ord,
K: RangeBounds<I>,
{
fn eq(&self, other: &Self) -> bool {
self.cmp(&other).is_eq()
}
}
impl<I, K> Eq for StartRangeBoundsOrdWrapper<I, K>
where
I: Ord,
K: RangeBounds<I>,
{
}