wrote all of bound.rs docs and added examples n stuff to set.rs

This commit is contained in:
ripytide
2022-11-28 20:42:22 +00:00
parent 673e7601a7
commit f70c1d0669
7 changed files with 155 additions and 25 deletions
Generated
+25
View File
@@ -2,15 +2,40 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "ordered-float"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf"
dependencies = [
"num-traits",
]
[[package]]
name = "range_bounds_map"
version = "0.0.1"
dependencies = [
"either",
"ordered-float",
]
+3
View File
@@ -7,3 +7,6 @@ edition = "2021"
[dependencies]
either = "1.8.0"
[dev-dependencies]
ordered-float = "3.4.0"
+2
View File
@@ -25,6 +25,8 @@
- turn overlaps back into a trait to make it public, mabye
- review caveats again
- run cargo fmt
- run and fix cargo clippy
- take a look around idiomatic rust for a bit first
+32 -4
View File
@@ -20,20 +20,44 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
use std::cmp::Ordering;
use std::ops::Bound;
/// An Ord newtype of [`Bound`] specific to [`start_bound()`].
///
/// This type is used to circumvent [`BTreeMap`]s (and rust collections
/// in general) lack of methods for searching with custom
/// [`comparator`] functions and/or it's lack of a [`Cursor`]-like
/// API
///
/// [`start_bound()`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html#tymethod.start_bound
/// [`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(PartialEq, Debug)]
pub(crate) enum StartBound<T> {
/// Mirror of [`Bound::Included`]
Included(T),
/// Mirror of [`Bound::Excluded`]
Excluded(T),
/// Mirror of [`Bound::Unbounded`]
Unbounded,
//workaround types used only as ends_bounds in meta-bound
//StartBound range searches in overlapping() (non need for
//reverseIncluded as it would be equivalent to normal included)
/// Workaround type used to represent [`Bound::Excluded`] in [`end_bound()`] in meta-bound
/// [`BTreeMap::range`] searches in [`crate::RangeBoundsMap::overlapping()`]
///
/// [`end_bound()`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html#tymethod.end_bound
/// [`BTreeMap::range`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range
ReverseExcluded(T),
/// Workaround type used to represent [`Bound::Unbounded`] in [`end_bound()`] in meta-bound
/// [`BTreeMap::range`] searches in [`crate::RangeBoundsMap::overlapping()`]
///
/// [`end_bound()`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html#tymethod.end_bound
/// [`BTreeMap::range`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range
ReverseUnbounded,
}
impl<T> StartBound<T> {
//when using this as an end value in a range search
/// Converts the [`StartBound`] to the appropriate type for use as
/// an [`end_bound()`] in a range search
///
/// [`end_bound()`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html#tymethod.end_bound
pub(crate) fn as_end_bound(self) -> StartBound<T> {
match self {
//flipping is unnecessary
@@ -48,6 +72,10 @@ impl<T> StartBound<T> {
impl<T> Eq for StartBound<T> where T: PartialEq {}
/// The [`PartialOrd`] implementaion with the goal of allowing the use
/// of [`BTreeMap::range`] on [`StartBound`]s
///
/// [`BTreeMap::range`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range
#[rustfmt::skip]
impl<T> PartialOrd for StartBound<T>
where
+2 -4
View File
@@ -32,7 +32,6 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
//!
//! ```
//! # use range_bounds_map::RangeBoundsMap;
//!
//! let mut range_bounds_map = RangeBoundsMap::new();
//!
//! range_bounds_map.insert(0..5, true);
@@ -48,7 +47,6 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
//! # use std::ops::RangeBounds;
//! # use std::ops::Bound;
//! # use range_bounds_map::RangeBoundsMap;
//!
//! #[derive(Debug)]
//! enum Reservation {
//! // Start, End (Inclusive-Inclusive)
@@ -97,8 +95,8 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
//! Most of the [`RangeBounds`]-specific methods on [`RangeBoundsMap`]
//! utilize the [`RangeBoundsMap::overlapping()`] method which
//! internally uses [`BTreeMap`]'s [`range()`] function. To allow
//! using [`range()`] for this purpose a newtype wrapper wrapped
//! around the [`start_bound()`]s so that we apply our custom [`Ord`]
//! using [`range()`] for this purpose a newtype wrapper is wrapped
//! around the [`start_bound()`]s so that we can apply our custom [`Ord`]
//! implementation onto all the [`start_bound()`]s.
//!
//! # Improvements/Caveats
+18 -15
View File
@@ -60,7 +60,7 @@ where
}
pub fn contains_point(&self, point: &I) -> bool {
self.get(point).is_some()
self.get_at_point(point).is_some()
}
pub fn overlaps<Q>(&self, search_range_bounds: &Q) -> bool
@@ -77,6 +77,8 @@ where
where
Q: RangeBounds<I>,
{
//todo panic on invalid search range
//optimisation fix this without cloning
let start =
StartBound::from(search_range_bounds.start_bound().cloned());
@@ -123,23 +125,13 @@ where
);
}
pub fn get(&self, point: &I) -> Option<&V> {
self.get_key_value(point).map(|(_, value)| value)
pub fn get_at_point(&self, point: &I) -> Option<&V> {
self.get_key_value_at_point(point).map(|(_, value)| value)
}
pub fn get_key_value(&self, point: &I) -> Option<(&K, &V)> {
//a zero-range included-included range is equivalent to a point
return self
.overlapping(&(
Bound::Included(point.clone()),
Bound::Included(point.clone()),
))
.next();
}
pub fn get_mut(&mut self, point: &I) -> Option<&mut V> {
pub fn get_at_point_mut(&mut self, point: &I) -> Option<&mut V> {
if let Some(overlapping_start_bound) =
self.get_key_value(point).map(|(key, _)| key.start_bound())
self.get_key_value_at_point(point).map(|(key, _)| key.start_bound())
{
return self
.starts
@@ -150,6 +142,17 @@ where
return None;
}
pub fn get_key_value_at_point(&self, point: &I) -> Option<(&K, &V)> {
//a zero-range included-included range is equivalent to a point
return self
.overlapping(&(
Bound::Included(point.clone()),
Bound::Included(point.clone()),
))
.next();
}
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.starts.iter().map(|(_, (key, value))| (key, value))
}
+73 -2
View File
@@ -21,6 +21,77 @@ use std::ops::RangeBounds;
use crate::range_bounds_map::RangeBoundsMap;
/// An ordered set of [`RangeBounds`] based on [`BTreeSet`]
///
/// # Examples
/// ```
/// # use range_bounds_map::RangeBoundsSet;
/// let mut visits = RangeBoundsSet::new();
///
/// // Add some ranges
/// visits.insert(4..8);
/// visits.insert(8..18);
/// visits.insert(20..100);
///
/// // Check if a point is contained in the set
/// if visits.contains_point(&0) {
/// println!("No visit at the beginning ;(");
/// }
///
/// // Iterate over the ranges overlapping another range
/// for visit in visits.overlapping(&(2..=8)) {
/// println!("{visit:?}");
/// }
/// ```
/// Example using a custom [`RangeBounds`] type:
/// ```
/// # use std::ops::Bound;
/// # use std::ops::RangeBounds;
/// # use ordered_float::NotNan;
/// # use range_bounds_map::RangeBoundsSet;
/// // An Exlusive-Exlusive range of [`f32`]s not provided by any
/// // std::ops ranges
/// // We use [`ordered_float::NotNan`]s as the inner type must be Ord
/// // similar to a normal [`BTreeSet`]
/// struct ExEx {
/// start: NotNan<f32>,
/// end: NotNan<f32>,
/// }
/// # impl ExEx {
/// # fn new(start: f32, end: f32) -> ExEx {
/// # ExEx {
/// # start: NotNan::new(start).unwrap(),
/// # end: NotNan::new(end).unwrap(),
/// # }
/// # }
/// # }
///
/// // Implement RangeBounds<f32> on our new type
/// impl RangeBounds<NotNan<f32>> for ExEx {
/// fn start_bound(&self) -> Bound<&NotNan<f32>> {
/// Bound::Excluded(&self.start)
/// }
/// fn end_bound(&self) -> Bound<&NotNan<f32>> {
/// Bound::Excluded(&self.start)
/// }
/// }
///
/// // Now we can make a [`RangeBoundsSet`] of [`ExEx``]s
/// let mut set = RangeBoundsSet::new();
///
/// set.insert(ExEx::new(0.0, 5.0));
/// set.insert(ExEx::new(5.0, 7.5));
///
/// assert!(NotNan::new(5.0).unwrap() < NotNan::new(5.0).unwrap());
/// panic!();
///
/// assert_eq!(set.contains_point(&(NotNan::new(5.0).unwrap())), false);
/// assert_eq!(set.contains_point(&(NotNan::new(7.0).unwrap())), true);
/// assert_eq!(set.contains_point(&(NotNan::new(7.5).unwrap())), false);
/// ```
///
/// [`RangeBounds`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html
/// [`BTreeSet`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html
pub struct RangeBoundsSet<I, K> {
map: RangeBoundsMap<I, K, ()>,
}
@@ -61,8 +132,8 @@ where
.map(|(key, _)| key)
}
pub fn get(&self, point: &I) -> Option<&K> {
self.map.get_key_value(point).map(|(key, _)| key)
pub fn get_at_point(&self, point: &I) -> Option<&K> {
self.map.get_key_value_at_point(point).map(|(key, _)| key)
}
pub fn contains_point(&self, point: &I) -> bool {