switch to APL
This commit is contained in:
Generated
+4
-4
@@ -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
@@ -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"]
|
||||||
|
|
||||||
|
|||||||
@@ -2,41 +2,19 @@
|
|||||||
|
|
||||||
[](https://crates.io/crates/range_bounds_set)
|
[](https://crates.io/crates/range_bounds_set)
|
||||||
[](https://docs.rs/range_bounds_set)
|
[](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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user