switch to APL

This commit is contained in:
ripytide
2022-12-12 03:58:51 +00:00
parent 270e21f8ea
commit f44cf2a306
9 changed files with 289 additions and 150 deletions
Generated
+4 -4
View File
@@ -118,18 +118,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.148" version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.148" version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
+5 -8
View File
@@ -6,20 +6,17 @@ edition = "2021"
description = """ description = """
This crate provides `RangeBoundsMap` and `RangeBoundsSet`. This crate provides `RangeBoundsMap` and `RangeBoundsSet`.
`RangeBoundsMap` is similar to `BTreeMap` except `RangeBoundsMap` `RangeBoundsMap` is an ordered map of non-overlapping [`RangeBounds`]
uses any type that implements the `RangeBounds` trait as keys, while based on [`BTreeMap`].
maintaining two invariants:
- No two keys may overlap
- A keys' `start_bound()` <= its `end_bound()`
`RangeBoundsSet` is like `RangeBoundsMap` except it `RangeBoundsSet` is an ordered set of non-overlapping [`RangeBounds`]
uses `()` as values, as `BTreeSet` does for `BTreeMap` based on [`RangeBoundsMap`].
""" """
documentation = "https://docs.rs/range_bounds_map" documentation = "https://docs.rs/range_bounds_map"
readme = "README.md" readme = "README.md"
homepage = "https://github.com/ripytide/range_bounds_map" homepage = "https://github.com/ripytide/range_bounds_map"
repository = "https://github.com/ripytide/range_bounds_map" repository = "https://github.com/ripytide/range_bounds_map"
license = "GPL-3.0-or-later" license = "AGPL-3.0-or-later"
keywords = ["data-structures", "map", "data", "library"] keywords = ["data-structures", "map", "data", "library"]
categories = ["data-structures"] categories = ["data-structures"]
+41 -66
View File
@@ -2,41 +2,19 @@
[![Crates.io](https://img.shields.io/crates/v/range_bounds_set)](https://crates.io/crates/range_bounds_set) [![Crates.io](https://img.shields.io/crates/v/range_bounds_set)](https://crates.io/crates/range_bounds_set)
[![Docs](https://docs.rs/range_bounds_set/badge)](https://docs.rs/range_bounds_set) [![Docs](https://docs.rs/range_bounds_set/badge)](https://docs.rs/range_bounds_set)
[![Maintained]](https://img.shields.io/maintenance/yes/2023)
<p align="center"> <p align="center">
<img src="logo.svg" alt="range_bounds_map_logo" width="350"> <img src="logo.svg" alt="range_bounds_map_logo" width="350">
</p> </p>
This crate provides [`RangeBoundsMap`] and [`RangeBoundsSet`]. This crate provides [`RangeBoundsMap`] and [`RangeBoundsSet`.]
[`RangeBoundsMap`] is similar to [`BTreeMap`] except [`RangeBoundsMap`] [`RangeBoundsMap`] is an ordered map of non-overlapping [`RangeBounds`]
uses any type that implements the [`RangeBounds`] trait as keys, while based on [`BTreeMap`].
maintaining two invariants:
- No two keys may overlap [`RangeBoundsSet`] is an ordered set of non-overlapping [`RangeBounds`]
- A keys' [`start_bound()`] <= its [`end_bound()`] based on [`RangeBoundsMap`].
[`RangeBoundsSet`] is like [`RangeBoundsMap`] except it
uses `()` as values, as [`BTreeSet`] does for [`BTreeMap`]
## Key Definitions:
### Overlap
Two `RangeBounds` are "overlapping" if there exists a point that is
contained within both `RangeBounds`.
### Touching
Two `RangeBounds` are "touching" if they do not overlap and
there exists no value between them. For example, `2..4` and
`4..6` are touching but `2..4` and `6..8` are not, neither are
`2..6` and `4..8`.
### Coalesce
When a `RangeBounds` "coalesces" other `RangeBounds` it absorbs them
to become larger.
## Example using [`Range`]s ## Example using [`Range`]s
@@ -45,8 +23,8 @@ use range_bounds_map::RangeBoundsMap;
let mut range_bounds_map = RangeBoundsMap::new(); let mut range_bounds_map = RangeBoundsMap::new();
range_bounds_map.insert(0..5, true); range_bounds_map.insert_platonic(0..5, true);
range_bounds_map.insert(5..10, false); range_bounds_map.insert_platonic(5..10, false);
assert_eq!(range_bounds_map.overlaps(&(-2..12)), true); assert_eq!(range_bounds_map.overlaps(&(-2..12)), true);
assert_eq!(range_bounds_map.contains_point(&20), false); assert_eq!(range_bounds_map.contains_point(&20), false);
@@ -112,54 +90,51 @@ assert_eq!(
); );
``` ```
# How ## Key Definitions:
Most of the [`RangeBounds`]-specific methods on [`RangeBoundsMap`] ### Overlap
utilize the [`RangeBoundsMap::overlapping()`] method which
internally uses [`BTreeMap`]'s [`range()`] function. To allow Two `RangeBounds` are "overlapping" if there exists a point that is
using [`range()`] for this purpose a newtype wrapper is wrapped contained within both `RangeBounds`.
around the [`start_bound()`]s so that we can apply our custom [`Ord`]
implementation onto all the [`start_bound()`]s. ### Touching
Two `RangeBounds` are "touching" if they do not overlap and
there exists no value between them. For example, `2..4` and
`4..6` are touching but `2..4` and `6..8` are not, neither are
`2..6` and `4..8`.
### Coalesce
When a `RangeBounds` "coalesces" other `RangeBounds` it absorbs them
to become larger.
# Improvements/Caveats # Improvements/Caveats
There are a few issues I can think of with this implementation,
each of them are documented as GitHub Issues. If you would like
any of these features added, drop a comment in a respective GitHub
Issue (or even open a new one) and I'd be happy to implement it.
To summarise:
- Some overly strict Trait-Bounds on some functions due to `impl`
level `Trait-Bounds` rather than specific `function` level
`Trait-Bounds`
- Missing some functions common to BTreeMap and BTreeSet like: - Missing some functions common to BTreeMap and BTreeSet like:
- `clear()` - `clear()`
- `is_subset()` - `is_subset()`
- etc... prob a bunch more - etc... prob a bunch more
- Sub-optimal use of unnecessary `cloned()` just to placate the borrow checker - Not particularly optimized, (which doesn't mean it's neccessarily slow)
- Lot's of optimisations available
- Can't use TryFrom<(Bound, Bound)> instead of [`TryFromBounds`] (relys on - Can't use TryFrom<(Bound, Bound)> instead of [`TryFromBounds`] (relys on
upstream to impl) upstream to impl, see [this thread](https://internals.rust-lang.org/t/range-should-impl-tryfrom-bound-bound))
- The data structures are lacking a lot of useful traits, such as:
- FromIterator
- IntoIterator
- Prob a bunch more
# Credit # Credit
I originally came up with the `StartBound`: [`Ord`] bodge on my I originally came up with the `StartBound`: [`Ord`] bodge on my own,
own, however, I later stumbled across [`rangemap`] which also used however, I later stumbled across [`rangemap`] which also used a
a `StartBound`: [`Ord`] bodge. [`rangemap`] then became my main `StartBound`: [`Ord`] bodge. [`rangemap`] then became my main source
source of inspiration. The aim for my library was to become a more of inspiration.
generic superset of [`rangemap`], following from
[this issue](https://github.com/jeffparsons/rangemap/issues/56) and The aim for my library was to become a more generic
[this pull request](https://github.com/jeffparsons/rangemap/pull/57) superset of [`rangemap`], following from [this
in which I changed [`rangemap`]'s [`RangeMap`] to use issue](https://github.com/jeffparsons/rangemap/issues/56) and [this
[`RangeBounds`]s as keys before I realized it might be easier and pull request](https://github.com/jeffparsons/rangemap/pull/57) in
simpler to just write it all from scratch. Which ended up working which I changed [`rangemap`]'s [`RangeMap`] to use [`RangeBounds`]s as
really well with some simplifications I made which ended up keys before I realized it might be easier and simpler to just write it
resulting in much less code (~600 lines over [`rangemap`]'s ~2700) all from scratch. Which ended up working really well with some
simplifications (BoundOrd) I made which made some of the code much
easier to work with.
# Similar Crates # Similar Crates
+5 -3
View File
@@ -4,16 +4,16 @@ Copyright 2022 James Forster
This file is part of range_bounds_map. This file is part of range_bounds_map.
range_bounds_map is free software: you can redistribute it and/or range_bounds_map is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
range_bounds_map is distributed in the hope that it will be useful, range_bounds_map is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. Affero General Public License for more details.
You should have received a copy of the GNU General Public License 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/>. along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -51,6 +51,7 @@ pub(crate) enum BoundOrd<T> {
} }
impl<T> BoundOrd<T> { impl<T> BoundOrd<T> {
#[trivial]
pub(crate) fn start(bound: Bound<T>) -> Self { pub(crate) fn start(bound: Bound<T>) -> Self {
match bound { match bound {
Bound::Included(point) => BoundOrd::Included(point), Bound::Included(point) => BoundOrd::Included(point),
@@ -58,6 +59,7 @@ impl<T> BoundOrd<T> {
Bound::Unbounded => BoundOrd::StartUnbounded, Bound::Unbounded => BoundOrd::StartUnbounded,
} }
} }
#[trivial]
pub(crate) fn end(bound: Bound<T>) -> Self { pub(crate) fn end(bound: Bound<T>) -> Self {
match bound { match bound {
Bound::Included(point) => BoundOrd::Included(point), Bound::Included(point) => BoundOrd::Included(point),
+178 -4
View File
@@ -4,20 +4,194 @@ Copyright 2022 James Forster
This file is part of range_bounds_map. This file is part of range_bounds_map.
range_bounds_map is free software: you can redistribute it and/or range_bounds_map is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
range_bounds_map is distributed in the hope that it will be useful, range_bounds_map is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. Affero General Public License for more details.
You should have received a copy of the GNU General Public License 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/>. along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
*/ */
//! todo //! This crate provides [`RangeBoundsMap`] and [`RangeBoundsSet`].
//!
//! [`RangeBoundsMap`] is an ordered map of non-overlapping [`RangeBounds`]
//! based on [`BTreeMap`].
//!
//! [`RangeBoundsSet`] is an ordered set of non-overlapping [`RangeBounds`]
//! based on [`RangeBoundsMap`].
//!
//! ## Example using [`Range`]s
//!
//! ```rust
//! use range_bounds_map::RangeBoundsMap;
//!
//! let mut range_bounds_map = RangeBoundsMap::new();
//!
//! range_bounds_map.insert_platonic(0..5, true);
//! range_bounds_map.insert_platonic(5..10, false);
//!
//! assert_eq!(range_bounds_map.overlaps(&(-2..12)), true);
//! assert_eq!(range_bounds_map.contains_point(&20), false);
//! assert_eq!(range_bounds_map.contains_point(&5), true);
//! ```
//!
//! ## Example using a custom [`RangeBounds`] type
//!
//! ```rust
//! use std::ops::{Bound, RangeBounds};
//!
//! use range_bounds_map::RangeBoundsMap;
//!
//! #[derive(Debug)]
//! enum Reservation {
//! // Start, End (Inclusive-Inclusive)
//! Finite(u8, u8),
//! // Start (Exclusive)
//! Infinite(u8),
//! }
//!
//! // First, we need to implement RangeBounds
//! impl RangeBounds<u8> for Reservation {
//! fn start_bound(&self) -> Bound<&u8> {
//! match self {
//! Reservation::Finite(start, _) => {
//! Bound::Included(start)
//! }
//! Reservation::Infinite(start) => {
//! Bound::Excluded(start)
//! }
//! }
//! }
//! fn end_bound(&self) -> Bound<&u8> {
//! match self {
//! Reservation::Finite(_, end) => Bound::Included(end),
//! Reservation::Infinite(_) => Bound::Unbounded,
//! }
//! }
//! }
//!
//! // Next we can create a custom typed RangeBoundsMap
//! let reservation_map = RangeBoundsMap::try_from([
//! (Reservation::Finite(10, 20), "Ferris".to_string()),
//! (Reservation::Infinite(20), "Corro".to_string()),
//! ])
//! .unwrap();
//!
//! for (reservation, name) in reservation_map.overlapping(&(16..17))
//! {
//! println!(
//! "{name} has reserved {reservation:?} inside the range 16..17"
//! );
//! }
//!
//! for (reservation, name) in reservation_map.iter() {
//! println!("{name} has reserved {reservation:?}");
//! }
//!
//! assert_eq!(
//! reservation_map.overlaps(&Reservation::Infinite(0)),
//! true
//! );
//! ```
//!
//! ## Key Definitions:
//!
//! ### Overlap
//!
//! Two `RangeBounds` are "overlapping" if there exists a point that is
//! contained within both `RangeBounds`.
//!
//! ### Touching
//!
//! Two `RangeBounds` are "touching" if they do not overlap and
//! there exists no value between them. For example, `2..4` and
//! `4..6` are touching but `2..4` and `6..8` are not, neither are
//! `2..6` and `4..8`.
//!
//! ### Coalesce
//!
//! When a `RangeBounds` "coalesces" other `RangeBounds` it absorbs them
//! to become larger.
//!
//! # How
//!
//! 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 is wrapped
//! around the [`start_bound()`]s so that we can apply our custom [`Ord`]
//! implementation onto all the [`start_bound()`]s.
//!
//! # Improvements/Caveats
//!
//! - Missing some functions common to BTreeMap and BTreeSet like:
//! - `clear()`
//! - `is_subset()`
//! - etc... prob a bunch more
//! - Not particularly optimized, (which doesn't mean it's neccessarily slow)
//! - Can't use TryFrom<(Bound, Bound)> instead of [`TryFromBounds`] (relys on
//! upstream to impl, see [this thread](https://internals.rust-lang.org/t/range-should-impl-tryfrom-bound-bound))
//!
//! # Credit
//!
//! I originally came up with the `StartBound`: [`Ord`] bodge on my own,
//! however, I later stumbled across [`rangemap`] which also used a
//! `StartBound`: [`Ord`] bodge. [`rangemap`] then became my main source
//! of inspiration. The aim for my library was to become a more generic
//! superset of [`rangemap`], following from [this
//! issue](https://github.com/jeffparsons/rangemap/issues/56) and [this
//! pull request](https://github.com/jeffparsons/rangemap/pull/57) in
//! which I changed [`rangemap`]'s [`RangeMap`] to use [`RangeBounds`]s as
//! keys before I realized it might be easier and simpler to just write it
//! all from scratch. Which ended up working really well with some
//! simplifications (BoundOrd) I made which made some of the code much
//! easier to work with.
//!
//! # Similar Crates
//!
//! Here are some relevant crates I found whilst searching around the
//! topic area:
//!
//! - <https://docs.rs/rangemap>
//! Very similar to this crate but can only use [`Range`]s and
//! [`RangeInclusive`]s as keys in it's `map` and `set` structs (separately).
//! - <https://docs.rs/ranges>
//! Cool library for fully-generic ranges (unlike std::ops ranges), along
//! with a `Ranges` datastructure for storing them (Vec-based
//! unfortunately)
//! - <https://docs.rs/intervaltree>
//! Allows overlapping intervals but is immutable unfortunately
//! - <https://docs.rs/nonoverlapping_interval_tree>
//! Very similar to rangemap except without a `gaps()` function and only
//! for [`Range`]s and not [`RangeInclusive`]s. And also no fancy coalescing
//! functions.
//! - <https://docs.rs/unbounded-interval-tree>
//! A data structure based off of a 2007 published paper! It supports any
//! RangeBounds as keys too, except it is implemented with a non-balancing
//! `Box<Node>` based tree, however it also supports overlapping
//! RangeBounds which my library does not.
//! - <https://docs.rs/rangetree>
//! I'm not entirely sure what this library is or isn't, but it looks like
//! a custom red-black tree/BTree implementation used specifically for a
//! Range Tree. Interesting but also quite old (5 years) and uses
//! unsafe.
//!
//! [`btreemap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html
//! [`btreeset`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html
//! [`rangebounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html
//! [`start_bound()`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html#tymethod.start_bound
//! [`end_bound()`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html#tymethod.end_bound
//! [`range`]: https://doc.rust-lang.org/std/ops/struct.Range.html
//! [`range()`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.range
//! [`rangemap`]: https://docs.rs/rangemap/latest/rangemap/
//! [`rangeinclusivemap`]: https://docs.rs/rangemap/latest/rangemap/inclusive_map/struct.RangeInclusiveMap.html#
//! [`rangeinclusive`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html
//! [`ord`]: https://doc.rust-lang.org/std/cmp/trait.Ord.html
#![feature(is_some_and)] #![feature(is_some_and)]
#![feature(let_chains)] #![feature(let_chains)]
+19 -14
View File
@@ -4,16 +4,16 @@ Copyright 2022 James Forster
This file is part of range_bounds_map. This file is part of range_bounds_map.
range_bounds_map is free software: you can redistribute it and/or range_bounds_map is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
range_bounds_map is distributed in the hope that it will be useful, range_bounds_map is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. Affero General Public License for more details.
You should have received a copy of the GNU General Public License 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/>. along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -25,7 +25,7 @@ use std::ops::{Bound, RangeBounds};
use either::Either; use either::Either;
use itertools::Itertools; use itertools::Itertools;
use labels::{tested, trivial}; use labels::{parent_tested, tested, trivial};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::bound_ord::BoundOrd; use crate::bound_ord::BoundOrd;
@@ -131,8 +131,8 @@ where
starts: BTreeMap<BoundOrd<I>, (K, V)>, starts: BTreeMap<BoundOrd<I>, (K, V)>,
} }
/// An error type to represent a `RangeBounds` overlapping another /// An error type to represent a [`RangeBounds`] overlapping another
/// `RangeBounds` when it should not have. /// [`RangeBounds`] when it should not have.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct OverlapError; pub struct OverlapError;
@@ -1112,6 +1112,7 @@ where
return Ok(&self.starts.get(&BoundOrd::start(start_bound)).unwrap().0); return Ok(&self.starts.get(&BoundOrd::start(start_bound)).unwrap().0);
} }
#[parent_tested]
fn touching_left(&self, range_bounds: &K) -> Option<&K> { fn touching_left(&self, range_bounds: &K) -> Option<&K> {
return self return self
.starts .starts
@@ -1125,6 +1126,7 @@ where
.map(|x| &x.1.0) .map(|x| &x.1.0)
.filter(|x| touches(range_bounds, *x)); .filter(|x| touches(range_bounds, *x));
} }
#[parent_tested]
fn touching_right(&self, range_bounds: &K) -> Option<&K> { fn touching_right(&self, range_bounds: &K) -> Option<&K> {
return self return self
.starts .starts
@@ -1212,6 +1214,7 @@ where
return Ok(&self.starts.get(&BoundOrd::start(start_bound)).unwrap().0); return Ok(&self.starts.get(&BoundOrd::start(start_bound)).unwrap().0);
} }
#[parent_tested]
fn overlapping_swell<'a>( fn overlapping_swell<'a>(
&'a self, &'a self,
range_bounds: &'a K, range_bounds: &'a K,
@@ -1467,7 +1470,7 @@ where
}; };
} }
} }
/// An owning iterator over the entries of a `RangeBoundsMap`. /// An owning iterator over the entries of a [`RangeBoundsMap`].
/// ///
/// This `struct` is created by the [`into_iter`] method on /// This `struct` is created by the [`into_iter`] method on
/// [`RangeBoundsMap`] (provided by the [`IntoIterator`] trait). See /// [`RangeBoundsMap`] (provided by the [`IntoIterator`] trait). See
@@ -1480,6 +1483,7 @@ pub struct IntoIter<I, K, V> {
} }
impl<I, K, V> Iterator for IntoIter<I, K, V> { impl<I, K, V> Iterator for IntoIter<I, K, V> {
type Item = (K, V); type Item = (K, V);
#[trivial]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.inner.next() self.inner.next()
} }
@@ -1674,7 +1678,6 @@ where
!matches!(sorted_config(a, b), SortedConfig::NonOverlapping(_, _)) !matches!(sorted_config(a, b), SortedConfig::NonOverlapping(_, _))
} }
#[rustfmt::skip]
#[tested] #[tested]
fn touches<I, A, B>(a: &A, b: &B) -> bool fn touches<I, A, B>(a: &A, b: &B) -> bool
where where
@@ -1683,13 +1686,15 @@ where
I: PartialOrd, I: PartialOrd,
{ {
match sorted_config(a, b) { match sorted_config(a, b) {
SortedConfig::NonOverlapping(a, b) => { SortedConfig::NonOverlapping(a, b) => match (a.1, b.0) {
match (a.1, b.0) { (Bound::Included(point1), Bound::Excluded(point2)) => {
(Bound::Included(point1), Bound::Excluded(point2)) => point1 == point2, point1 == point2
(Bound::Excluded(point1), Bound::Included(point2)) => point1 == point2,
_ => false,
} }
} (Bound::Excluded(point1), Bound::Included(point2)) => {
point1 == point2
}
_ => false,
},
_ => false, _ => false,
} }
} }
+15 -13
View File
@@ -4,23 +4,23 @@ Copyright 2022 James Forster
This file is part of range_bounds_map. This file is part of range_bounds_map.
range_bounds_map is free software: you can redistribute it and/or range_bounds_map is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
range_bounds_map is distributed in the hope that it will be useful, range_bounds_map is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. Affero General Public License for more details.
You should have received a copy of the GNU General Public License 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/>. along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
*/ */
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::{Bound, RangeBounds}; use std::ops::{Bound, RangeBounds};
use labels::{tested, trivial}; use labels::trivial;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::range_bounds_map::IntoIter as MapIntoIter; use crate::range_bounds_map::IntoIter as MapIntoIter;
@@ -191,7 +191,7 @@ where
/// ); /// );
/// assert_eq!(range_bounds_set.len(), 1); /// assert_eq!(range_bounds_set.len(), 1);
/// ``` /// ```
#[tested] #[trivial]
pub fn insert_platonic( pub fn insert_platonic(
&mut self, &mut self,
range_bounds: K, range_bounds: K,
@@ -241,7 +241,7 @@ where
/// [(&(1..4)), (&(4..8))] /// [(&(1..4)), (&(4..8))]
/// ); /// );
/// ``` /// ```
#[tested] #[trivial]
pub fn overlapping<Q>( pub fn overlapping<Q>(
&self, &self,
range_bounds: &Q, range_bounds: &Q,
@@ -331,7 +331,7 @@ where
/// [&(8..100)] /// [&(8..100)]
/// ); /// );
/// ``` /// ```
#[tested] #[trivial]
pub fn remove_overlapping<Q>( pub fn remove_overlapping<Q>(
&mut self, &mut self,
range_bounds: &Q, range_bounds: &Q,
@@ -375,7 +375,7 @@ where
/// assert_eq!(base, after_cut); /// assert_eq!(base, after_cut);
/// assert!(base.cut(&(60..=80)).is_err()); /// assert!(base.cut(&(60..=80)).is_err());
/// ``` /// ```
#[tested] #[trivial]
pub fn cut<Q>( pub fn cut<Q>(
&mut self, &mut self,
range_bounds: &Q, range_bounds: &Q,
@@ -455,7 +455,7 @@ where
/// ] /// ]
/// ); /// );
/// ``` /// ```
#[tested] #[trivial]
pub fn gaps<'a, Q>( pub fn gaps<'a, Q>(
&'a self, &'a self,
outer_range_bounds: &'a Q, outer_range_bounds: &'a Q,
@@ -571,7 +571,7 @@ where
/// [&(1..6), &(10..16)] /// [&(1..6), &(10..16)]
/// ); /// );
/// ``` /// ```
#[tested] #[trivial]
pub fn insert_coalesce_touching( pub fn insert_coalesce_touching(
&mut self, &mut self,
range_bounds: K, range_bounds: K,
@@ -622,7 +622,7 @@ where
/// [&(-4..1), &(1..8), &(10..16)] /// [&(-4..1), &(1..8), &(10..16)]
/// ); /// );
/// ``` /// ```
#[tested] #[trivial]
pub fn insert_coalesce_overlapping( pub fn insert_coalesce_overlapping(
&mut self, &mut self,
range_bounds: K, range_bounds: K,
@@ -676,7 +676,7 @@ where
/// [&(-4..8), &(10..16)] /// [&(-4..8), &(10..16)]
/// ); /// );
/// ``` /// ```
#[tested] #[trivial]
pub fn insert_coalesce_touching_or_overlapping( pub fn insert_coalesce_touching_or_overlapping(
&mut self, &mut self,
range_bounds: K, range_bounds: K,
@@ -817,7 +817,7 @@ where
}; };
} }
} }
/// An owning iterator over the entries of a `RangeBoundsSet`. /// An owning iterator over the entries of a [`RangeBoundsSet`].
/// ///
/// This `struct` is created by the [`into_iter`] method on /// This `struct` is created by the [`into_iter`] method on
/// [`RangeBoundsSet`] (provided by the [`IntoIterator`] trait). See /// [`RangeBoundsSet`] (provided by the [`IntoIterator`] trait). See
@@ -830,6 +830,7 @@ pub struct IntoIter<I, K> {
} }
impl<I, K> Iterator for IntoIter<I, K> { impl<I, K> Iterator for IntoIter<I, K> {
type Item = K; type Item = K;
#[trivial]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(first) self.inner.next().map(first)
} }
@@ -847,6 +848,7 @@ where
} }
} }
#[trivial]
fn first<A, B>((a, _): (A, B)) -> A { fn first<A, B>((a, _): (A, B)) -> A {
a a
} }
+3 -3
View File
@@ -4,16 +4,16 @@ Copyright 2022 James Forster
This file is part of range_bounds_map. This file is part of range_bounds_map.
range_bounds_map is free software: you can redistribute it and/or range_bounds_map is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
range_bounds_map is distributed in the hope that it will be useful, range_bounds_map is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. Affero General Public License for more details.
You should have received a copy of the GNU General Public License 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/>. along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
*/ */
+19 -35
View File
@@ -1,15 +1,18 @@
# refactor # refactor
- try to fix all the uses of cloned() in the library - try to remove unnecessary uses of cloned()
- make a StartBoundWrapper that uses StartBound to implement ord and - use expand, expand_cloned and cloned_bounds everywhere
use that instead of storing the startbound twice - replace instances of |(key, \_)| with fn first()
- make a range_bounds configuration: NonOverlapping, A contained in B,
A partial overlap B, with A before B. And use it to simplify all the
logic based RangeBounds functions
- make an expand function to go RangeBounds -> (Bound, Bound) rather
than doing it manually everywhere
- rename overwrite to insert_forceful - rename overwrite to insert_forceful
- replace instances of |(key, _)| with fn first() - make all iterators cutsom types as is standardised in libraries for
some reason(?)
- take a look around idiomatic rust for a bit
- review method parameter names for all public functions
# optimisations
- make a StartBoundWrapper that uses BoundOrd to implement ord and
use that instead of storing the startbound twice
# Documentation # Documentation
@@ -19,38 +22,19 @@
# features # features
- make specifc RangeMap, RangeSet, RangeInclusiveMap... types for signature - make specifc RangeMap, RangeSet, RangeInclusiveMap... types for signature
simplification simplification - alternatively add just the one generic SafeRangeBoundsMap + Set that
- alternatively add just the one generic SafeRangeBoundsMap + Set that
just add unwraps everywhere to simplify signatures on known-"Safe" just add unwraps everywhere to simplify signatures on known-"Safe"
symmetric types such as Range symmetric types such as Range
- add rangemap's insert function to finally make range_bounds_map a superset of rangemap
- make gaps() DoubleEndedIterator - add append() split_off() etc..
- make all iterators cutsom types as is standardised in libraries for
some reason
- add coalesce if same-value otherwise overwrite) function to make # open questions
finally make range_bounds_map a superset of rangemap
# time based - should we implement FromIterator? If so which insert should we use?
(At the moment we do implement it using insert_platonic())
- use it in robot_Sweet_graph for a bit before publishing #### PUBLISH
# final checks
- remove most rustfmt::skips and cargo fmt
- check toml meta-data, github meta-data and readme opener
- copy map to set again
- review todo.txt
- copy readme to lib.rs docs again
- take a look around idiomatic rust for a bit first
- run is_labelled again and check they are accurate
- review method parameter names for all public functions
- update lines of code figures on docs
- add issues to github for all the caveats
- review caveats again
- run and fix cargo clippy
- PUBLISH
# after publish tasks # after publish tasks