diff --git a/Cargo.lock b/Cargo.lock
index cbf74ae..a2d867a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8,6 +8,22 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+[[package]]
+name = "ctor"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "diff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
[[package]]
name = "either"
version = "1.8.0"
@@ -23,6 +39,14 @@ dependencies = [
"either",
]
+[[package]]
+name = "labels"
+version = "0.1.0"
+dependencies = [
+ "quote",
+ "syn",
+]
+
[[package]]
name = "num-traits"
version = "0.2.15"
@@ -41,6 +65,27 @@ dependencies = [
"num-traits",
]
+[[package]]
+name = "output_vt100"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "pretty_assertions"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
+dependencies = [
+ "ctor",
+ "diff",
+ "output_vt100",
+ "yansi",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.47"
@@ -65,7 +110,9 @@ version = "0.0.1"
dependencies = [
"either",
"itertools",
+ "labels",
"ordered-float",
+ "pretty_assertions",
"serde",
]
@@ -105,3 +152,31 @@ name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "yansi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
diff --git a/Cargo.toml b/Cargo.toml
index d026f6b..4c82c74 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,6 +27,8 @@ categories = ["data-structures"]
either = "1.8.0"
serde = {version = "1.0.148", features = ["derive"]}
itertools = "0.10.5"
+labels = {path = "../robot_sweet_shop/labels"}
+pretty_assertions = "1.3.0"
[dev-dependencies]
ordered-float = "3.4.0"
diff --git a/src/bounds.rs b/src/bounds.rs
index 5d182c4..867ca7e 100644
--- a/src/bounds.rs
+++ b/src/bounds.rs
@@ -20,6 +20,7 @@ along with range_bounds_map. If not, see .
use std::cmp::Ordering;
use std::ops::Bound;
+use labels::{parent_tested, tested, trivial};
use serde::{Deserialize, Serialize};
/// An Ord newtype of [`Bound`] specific to [`start_bound()`].
@@ -60,6 +61,7 @@ impl StartBound {
/// an [`end_bound()`] in a range search
///
/// [`end_bound()`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html#tymethod.end_bound
+ #[trivial]
pub(crate) fn into_end_bound(self) -> StartBound {
match self {
//flipping is unnecessary
@@ -83,6 +85,7 @@ impl PartialOrd for StartBound
where
T: PartialOrd,
{
+ #[tested]
fn partial_cmp(&self, other: &Self) -> Option {
match (self, other) {
(StartBound::Included(start1), StartBound::Included(start2)) => start1.partial_cmp(start2),
@@ -120,6 +123,7 @@ where
//if they are equal say the item with priority is larger
//where false means left has priority and true means right
+#[parent_tested]
fn partial_cmp_with_priority(
left: &T,
right: &T,
@@ -143,12 +147,14 @@ impl Ord for StartBound
where
T: PartialOrd,
{
+ #[trivial]
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
impl From> for StartBound {
+ #[trivial]
fn from(bound: Bound) -> Self {
match bound {
Bound::Included(point) => StartBound::Included(point),
@@ -158,6 +164,7 @@ impl From> for StartBound {
}
}
impl From> for Bound {
+ #[trivial]
fn from(start_bound: StartBound) -> Bound {
match start_bound {
StartBound::Included(point) => Bound::Included(point),
diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs
index d55ff2f..3fdd483 100644
--- a/src/range_bounds_map.rs
+++ b/src/range_bounds_map.rs
@@ -25,6 +25,7 @@ use std::ops::{Bound, RangeBounds};
use either::Either;
use itertools::Itertools;
+use labels::{tested, trivial, untested};
use serde::{Deserialize, Serialize};
use crate::bounds::StartBound;
@@ -274,6 +275,7 @@ where
/// let range_bounds_map: RangeBoundsMap, bool> =
/// RangeBoundsMap::new();
/// ```
+ #[trivial]
pub fn new() -> Self {
RangeBoundsMap {
starts: BTreeMap::new(),
@@ -292,6 +294,7 @@ where
/// range_bounds_map.insert_platonic(0..1, false).unwrap();
/// assert_eq!(range_bounds_map.len(), 1);
/// ```
+ #[trivial]
pub fn len(&self) -> usize {
self.starts.len()
}
@@ -316,6 +319,7 @@ where
/// );
/// assert_eq!(range_bounds_map.len(), 1);
/// ```
+ #[tested]
pub fn insert_platonic(
&mut self,
range_bounds: K,
@@ -358,6 +362,7 @@ where
/// assert_eq!(range_bounds_map.overlaps(&(4..=5)), true);
/// assert_eq!(range_bounds_map.overlaps(&(4..6)), true);
/// ```
+ #[trivial]
pub fn overlaps(&self, search_range_bounds: &Q) -> bool
where
Q: RangeBounds,
@@ -387,6 +392,7 @@ where
/// [(&(1..4), &false), (&(4..8), &true)]
/// );
/// ```
+ #[tested]
pub fn overlapping(
&self,
range_bounds: &Q,
@@ -459,6 +465,7 @@ where
/// assert_eq!(range_bounds_map.get_at_point(&4), Some(&true));
/// assert_eq!(range_bounds_map.get_at_point(&101), None);
/// ```
+ #[trivial]
pub fn get_at_point(&self, point: &I) -> Option<&V> {
self.get_entry_at_point(point).map(|(_, value)| value)
}
@@ -481,6 +488,7 @@ where
/// assert_eq!(range_bounds_map.contains_point(&4), true);
/// assert_eq!(range_bounds_map.contains_point(&101), false);
/// ```
+ #[trivial]
pub fn contains_point(&self, point: &I) -> bool {
self.get_at_point(point).is_some()
}
@@ -501,6 +509,7 @@ where
///
/// assert_eq!(range_bounds_map.get_at_point(&1), Some(&true));
/// ```
+ #[tested]
pub fn get_at_point_mut(&mut self, point: &I) -> Option<&mut V> {
if let Some(overlapping_start_bound) = self
.get_entry_at_point(point)
@@ -538,6 +547,7 @@ where
/// );
/// assert_eq!(range_bounds_map.get_entry_at_point(&101), None);
/// ```
+ #[trivial]
pub fn get_entry_at_point(&self, point: &I) -> Option<(&K, &V)> {
//a zero-range included-included range is equivalent to a point
return self
@@ -569,6 +579,7 @@ where
/// assert_eq!(iter.next(), Some((&(8..100), &false)));
/// assert_eq!(iter.next(), None);
/// ```
+ #[trivial]
pub fn iter(&self) -> impl DoubleEndedIterator- {
self.starts.iter().map(|(_, (key, value))| (key, value))
}
@@ -600,6 +611,7 @@ where
/// [(&(8..100), &false)]
/// );
/// ```
+ #[tested]
pub fn remove_overlapping
(
&mut self,
range_bounds: &Q,
@@ -654,6 +666,7 @@ where
/// assert_eq!(base, after_cut);
/// assert_eq!(base.cut(&(60..=80)), Err(TryFromBoundsError));
/// ```
+ #[tested]
pub fn cut(&mut self, range_bounds: &Q) -> Result<(), TryFromBoundsError>
where
Q: RangeBounds,
@@ -753,6 +766,7 @@ where
/// ]
/// );
/// ```
+ #[tested]
pub fn gaps<'a, Q>(
&'a self,
outer_range_bounds: &'a Q,
@@ -780,8 +794,6 @@ where
.chain(inners)
.chain(once(artificial_end));
- eprintln!("\nnew:");
-
return artificials
.tuple_windows()
.map(|((_, first_end), (second_start, _))| {
@@ -814,6 +826,7 @@ where
/// true
/// );
/// ```
+ #[trivial]
pub fn contains_range_bounds(&self, range_bounds: &Q) -> bool
where
Q: RangeBounds,
@@ -872,6 +885,7 @@ where
/// [(&(1..6), &true), (&(10..16), &false),]
/// );
/// ```
+ #[tested]
pub fn insert_coalesce_touching(
&mut self,
range_bounds: K,
@@ -977,6 +991,7 @@ where
/// [(&(-4..1), &true), (&(1..8), &true), (&(10..16), &false)]
/// );
/// ```
+ #[tested]
pub fn insert_coalesce_overlapping(
&mut self,
range_bounds: K,
@@ -1063,6 +1078,7 @@ where
/// [(&(-4..8), &true), (&(10..16), &false)]
/// );
/// ```
+ #[tested]
pub fn insert_coalesce_touching_or_overlapping(
&mut self,
range_bounds: K,
@@ -1121,6 +1137,7 @@ where
/// [(&(2..4), &false), (&(4..6), &true), (&(6..8), &false)]
/// );
/// ```
+ #[trivial]
pub fn overwrite(
&mut self,
range_bounds: K,
@@ -1143,6 +1160,7 @@ where
I: Ord + Clone,
{
type Error = OverlapError;
+ #[trivial]
fn try_from(pairs: [(K, V); N]) -> Result {
let mut range_bounds_map = RangeBoundsMap::new();
for (range_bounds, value) in pairs {
@@ -1152,11 +1170,28 @@ where
return Ok(range_bounds_map);
}
}
+impl TryFrom> for RangeBoundsMap
+where
+ K: RangeBounds,
+ I: Ord + Clone,
+{
+ type Error = OverlapError;
+ #[trivial]
+ fn try_from(pairs: Vec<(K, V)>) -> Result {
+ let mut range_bounds_map = RangeBoundsMap::new();
+ for (range_bounds, value) in pairs {
+ range_bounds_map.insert_platonic(range_bounds, value)?;
+ }
+
+ return Ok(range_bounds_map);
+ }
+}
impl Default for RangeBoundsMap
where
I: PartialOrd,
{
+ #[trivial]
fn default() -> Self {
RangeBoundsMap {
starts: BTreeMap::default(),
@@ -1171,6 +1206,7 @@ enum CutResult {
Double((Bound, Bound), (Bound, Bound)),
}
+#[tested]
fn cut_range_bounds(
base_range_bounds: &B,
cut_range_bounds: &C,
@@ -1222,6 +1258,7 @@ where
}
}
+#[trivial]
fn is_valid_range_bounds(range_bounds: &Q) -> bool
where
Q: RangeBounds,
@@ -1236,6 +1273,7 @@ where
}
}
+#[tested]
fn overlaps(a: &A, b: &B) -> bool
where
A: RangeBounds,
@@ -1269,6 +1307,7 @@ where
}
}
+#[untested]
fn touches(a: &A, b: &B) -> bool
where
A: RangeBounds,
@@ -1296,6 +1335,7 @@ where
}
}
+#[trivial]
fn flip_bound(bound: Bound<&I>) -> Bound<&I> {
match bound {
Bound::Included(point) => Bound::Excluded(point),
@@ -1308,6 +1348,8 @@ fn flip_bound(bound: Bound<&I>) -> Bound<&I> {
mod tests {
use std::ops::{Bound, Range, RangeBounds};
+ use pretty_assertions::assert_eq;
+
use super::*;
use crate::bounds::StartBound;
@@ -1320,28 +1362,44 @@ mod tests {
pub(crate) const NUMBERS_DOMAIN: &'static [u8] =
&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
+ #[rustfmt::skip]
#[test]
- fn mass_overlaps_test() {
- for range_bounds1 in all_valid_test_bounds() {
- for range_bounds2 in all_valid_test_bounds() {
- let our_answer = overlaps(&range_bounds1, &range_bounds2);
-
- let mathematical_definition_of_overlap =
- NUMBERS_DOMAIN.iter().any(|x| {
- range_bounds1.contains(x) && range_bounds2.contains(x)
- });
-
- if our_answer != mathematical_definition_of_overlap {
- dbg!(range_bounds1, range_bounds2);
- dbg!(mathematical_definition_of_overlap, our_answer);
- panic!("Discrepency in .overlaps() detected!");
- }
+ fn insert_platonic_tests() {
+ assert_insert_platonic::<0>(basic(), (ii(0, 4), false), Err(OverlapError), None);
+ assert_insert_platonic::<0>(basic(), (ii(5, 6), false), Err(OverlapError), None);
+ assert_insert_platonic(basic(), (ee(6, 7), false), Ok(()), Some([
+ (ui(4), false),
+ (ee(5, 6), true),
+ (ii(6, 6), false),
+ (ee(6, 7), false),
+ ]));
+ assert_insert_platonic::<0>(basic(), (ii(4, 5), true), Err(OverlapError), None);
+ assert_insert_platonic(basic(), (ei(4, 5), true), Ok(()), Some([
+ (ui(4), false),
+ (ei(4, 5), true),
+ (ee(5, 6), true),
+ (ii(6, 6), false),
+ (ee(6, 7), false),
+ ]));
+ }
+ fn assert_insert_platonic(
+ mut before: RangeBoundsMap,
+ to_insert: (TestBounds, bool),
+ result: Result<(), OverlapError>,
+ after: Option<[(TestBounds, bool); N]>,
+ ) {
+ let clone = before.clone();
+ assert_eq!(before.insert_platonic(to_insert.0, to_insert.1), result);
+ match after {
+ Some(after) => {
+ assert_eq!(before, RangeBoundsMap::try_from(after).unwrap())
}
+ None => assert_eq!(before, clone),
}
}
#[test]
- fn mass_overlapping_test() {
+ fn overlapping_tests() {
//case zero
for overlap_range in all_valid_test_bounds() {
//you can't overlap nothing
@@ -1423,23 +1481,291 @@ mod tests {
}
}
- impl CutResult {
- fn contains(&self, point: &I) -> bool
- where
- I: PartialOrd,
- {
- match self {
- CutResult::Nothing => false,
- CutResult::Single(range_bounds) => range_bounds.contains(point),
- CutResult::Double(first_range_bounds, second_range_bounds) => {
- first_range_bounds.contains(point)
- || second_range_bounds.contains(point)
+ #[rustfmt::skip]
+ #[test]
+ fn remove_overlapping_tests() {
+ assert_remove_overlapping::<0, 0>(basic(), ii(5, 5), [], None);
+ assert_remove_overlapping(basic(), uu(), [
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ii(7, 7), false),
+ (ie(14, 16), true),
+ ], Some([]));
+ assert_remove_overlapping(basic(), ii(6, 7), [
+ (ee(5, 7), true),
+ (ii(7, 7), false),
+ ], Some([
+ (ui(4), false), (ie(14, 16), true)
+ ]));
+ assert_remove_overlapping(basic(), iu(6), [
+ (ee(5, 7), true),
+ (ii(7, 7), false),
+ (ie(14, 16), true),
+ ], Some([
+ (ui(4), false),
+ ]));
+ }
+ fn assert_remove_overlapping(
+ mut before: RangeBoundsMap,
+ to_remove: TestBounds,
+ result: [(TestBounds, bool); N],
+ after: Option<[(TestBounds, bool); Y]>,
+ ) {
+ let clone = before.clone();
+ assert_eq!(before.remove_overlapping(&to_remove).collect_vec(), result);
+ match after {
+ Some(after) => {
+ assert_eq!(before, RangeBoundsMap::try_from(after).unwrap())
+ }
+ None => assert_eq!(before, clone),
+ }
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn cut_tests() {
+ assert_cut::<0>(basic(), ii(50, 60), Ok(()), None);
+ assert_cut(basic(), uu(), Ok(()), Some([]));
+ assert_cut(basic(), ui(6), Ok(()), Some([
+ (ee(6, 7), true),
+ (ii(7, 7), false),
+ (ie(14, 16), true),
+ ]));
+ assert_cut(basic(), iu(6), Ok(()), Some([
+ (ui(4), false),
+ (ee(5, 6), true),
+ ]));
+ }
+ fn assert_cut(
+ mut before: RangeBoundsMap,
+ to_cut: TestBounds,
+ result: Result<(), TryFromBoundsError>,
+ after: Option<[(TestBounds, bool); N]>,
+ ) {
+ let clone = before.clone();
+ assert_eq!(before.cut(&to_cut), result);
+ match after {
+ Some(after) => {
+ assert_eq!(before, RangeBoundsMap::try_from(after).unwrap())
+ }
+ None => assert_eq!(before, clone),
+ }
+ }
+
+ fn basic() -> RangeBoundsMap {
+ RangeBoundsMap::try_from([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ii(7, 7), false),
+ (ie(14, 16), true),
+ ])
+ .unwrap()
+ }
+
+ #[test]
+ fn gaps_tests() {
+ assert_gaps(basic(), ii(50, 60), [ii(50, 60)]);
+ assert_gaps(basic(), iu(50), [iu(50)]);
+ assert_gaps(basic(), ee(3, 16), [ei(4, 5), ee(7, 14)]);
+ assert_gaps(basic(), ei(3, 16), [ei(4, 5), ee(7, 14), ii(16, 16)]);
+ assert_gaps(basic(), ue(5), [ee(4, 5)]);
+ assert_gaps(basic(), ui(3), []);
+ assert_gaps(basic(), ii(5, 5), [ii(5, 5)]);
+ assert_gaps(basic(), ii(6, 6), []);
+ assert_gaps(basic(), ii(7, 7), []);
+ assert_gaps(basic(), ii(8, 8), [ii(8, 8)]);
+ }
+ fn assert_gaps(
+ range_bounds_map: RangeBoundsMap,
+ outer_range_bounds: TestBounds,
+ result: [TestBounds; N],
+ ) {
+ assert_eq!(
+ range_bounds_map
+ .gaps(&outer_range_bounds)
+ .map(|(start, end)| (start.cloned(), end.cloned()))
+ .collect_vec(),
+ result
+ );
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn insert_coalesce_touching_tests() {
+ assert_insert_coalesce_touching::<0>(basic(), (ii(0, 4), false), Err(OverlapOrTryFromBoundsError::Overlap(OverlapError)), None);
+ assert_insert_coalesce_touching::<4>(basic(), (ee(7, 10), false), Ok(&ee(7, 10)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 10), false),
+ (ie(14, 16), true),
+ ]));
+ assert_insert_coalesce_touching::<4>(basic(), (ee(7, 11), true), Ok(&ie(7, 11)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 11), true),
+ (ie(14, 16), true),
+ ]));
+ assert_insert_coalesce_touching::<5>(basic(), (ee(13, 14), true), Ok(&ee(13, 14)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 7), false),
+ (ee(13, 14), true),
+ (ie(14, 16), true),
+ ]));
+ assert_insert_coalesce_touching::<4>(basic(), (ei(13, 14), false), Ok(&ee(13, 16)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 7), false),
+ (ee(13, 16), false),
+ ]));
+ assert_insert_coalesce_touching::<3>(basic(), (ii(7, 13), false), Ok(&ie(7, 16)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 16), false),
+ ]));
+ }
+ fn assert_insert_coalesce_touching(
+ mut before: RangeBoundsMap,
+ to_insert: (TestBounds, bool),
+ result: Result<&TestBounds, OverlapOrTryFromBoundsError>,
+ after: Option<[(TestBounds, bool); N]>,
+ ) {
+ let clone = before.clone();
+ assert_eq!(
+ before.insert_coalesce_touching(to_insert.0, to_insert.1),
+ result
+ );
+ match after {
+ Some(after) => {
+ assert_eq!(before, RangeBoundsMap::try_from(after).unwrap())
+ }
+ None => assert_eq!(before, clone),
+ }
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn insert_coalesce_overlapping_tests() {
+ assert_insert_coalesce_overlapping::<4>(basic(), (ii(0, 2), true), Ok(&(ui(4))), Some([
+ (ui(4), true),
+ (ee(5, 7), true),
+ (ii(7, 7), false),
+ (ie(14, 16), true),
+ ]));
+ assert_insert_coalesce_overlapping::<4>(basic(), (ie(14, 16), false), Ok(&ie(14, 16)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 10), false),
+ (ie(14, 16), false),
+ ]));
+ assert_insert_coalesce_overlapping::<3>(basic(), (ii(7, 11), false), Ok(&ei(5, 11)), Some([
+ (ui(4), false),
+ (ei(5, 11), false),
+ (ie(14, 16), true),
+ ]));
+ assert_insert_coalesce_overlapping::<4>(basic(), (ii(15, 18), true), Ok(&ii(14, 18)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 7), false),
+ (ii(14, 18), true),
+ ]));
+ assert_insert_coalesce_overlapping::<1>(basic(), (uu(), false), Ok(&uu()), Some([
+ (uu(), false),
+ ]));
+ }
+ fn assert_insert_coalesce_overlapping(
+ mut before: RangeBoundsMap,
+ to_insert: (TestBounds, bool),
+ result: Result<&TestBounds, TryFromBoundsError>,
+ after: Option<[(TestBounds, bool); N]>,
+ ) {
+ let clone = before.clone();
+ assert_eq!(
+ before.insert_coalesce_overlapping(to_insert.0, to_insert.1),
+ result
+ );
+ match after {
+ Some(after) => {
+ assert_eq!(before, RangeBoundsMap::try_from(after).unwrap())
+ }
+ None => assert_eq!(before, clone),
+ }
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn insert_coalesce_touching_or_overlapping_tests() {
+ assert_insert_coalesce_touching_or_overlapping::<4>(basic(), (ii(0, 2), true), Ok(&(ui(4))), Some([
+ (ui(4), true),
+ (ee(5, 7), true),
+ (ii(7, 7), false),
+ (ie(14, 16), true),
+ ]));
+ assert_insert_coalesce_touching_or_overlapping::<4>(basic(), (ie(14, 16), false), Ok(&ie(14, 16)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 10), false),
+ (ie(14, 16), false),
+ ]));
+ assert_insert_coalesce_touching_or_overlapping::<4>(basic(), (ii(15, 18), true), Ok(&ii(14, 18)), Some([
+ (ui(4), false),
+ (ee(5, 7), true),
+ (ie(7, 7), false),
+ (ii(14, 18), true),
+ ]));
+ assert_insert_coalesce_touching_or_overlapping::<1>(basic(), (uu(), false), Ok(&uu()), Some([
+ (uu(), false),
+ ]));
+ //the only difference from the insert_coalesce_overlapping
+ assert_insert_coalesce_touching_or_overlapping::<2>(basic(), (ii(7, 11), false), Ok(&ee(5, 16)), Some([
+ (ui(4), false),
+ (ee(5, 16), false),
+ ]));
+ }
+ fn assert_insert_coalesce_touching_or_overlapping(
+ mut before: RangeBoundsMap,
+ to_insert: (TestBounds, bool),
+ result: Result<&TestBounds, TryFromBoundsError>,
+ after: Option<[(TestBounds, bool); N]>,
+ ) {
+ let clone = before.clone();
+ assert_eq!(
+ before.insert_coalesce_touching_or_overlapping(
+ to_insert.0,
+ to_insert.1
+ ),
+ result
+ );
+ match after {
+ Some(after) => {
+ assert_eq!(before, RangeBoundsMap::try_from(after).unwrap())
+ }
+ None => assert_eq!(before, clone),
+ }
+ }
+
+ #[test]
+ fn overlaps_tests() {
+ for range_bounds1 in all_valid_test_bounds() {
+ for range_bounds2 in all_valid_test_bounds() {
+ let our_answer = overlaps(&range_bounds1, &range_bounds2);
+
+ let mathematical_definition_of_overlap =
+ NUMBERS_DOMAIN.iter().any(|x| {
+ range_bounds1.contains(x) && range_bounds2.contains(x)
+ });
+
+ if our_answer != mathematical_definition_of_overlap {
+ dbg!(range_bounds1, range_bounds2);
+ dbg!(mathematical_definition_of_overlap, our_answer);
+ panic!("Discrepency in .overlaps() detected!");
}
}
}
}
+
#[test]
- fn mass_cut_range_bounds_tests() {
+ fn cut_range_bounds_tests() {
for base in all_valid_test_bounds() {
for cut in all_valid_test_bounds() {
let cut_result = cut_range_bounds(&base, &cut);
@@ -1470,7 +1796,24 @@ mod tests {
}
}
}
+ impl CutResult {
+ fn contains(&self, point: &I) -> bool
+ where
+ I: PartialOrd,
+ {
+ match self {
+ CutResult::Nothing => false,
+ CutResult::Single(range_bounds) => range_bounds.contains(point),
+ CutResult::Double(first_range_bounds, second_range_bounds) => {
+ first_range_bounds.contains(point)
+ || second_range_bounds.contains(point)
+ }
+ }
+ }
+ }
+ // Test Helper Functions
+ //======================
fn all_non_overlapping_test_bound_pairs() -> Vec<(TestBounds, TestBounds)> {
let mut output = Vec::new();
for test_bounds1 in all_valid_test_bounds() {
@@ -1491,14 +1834,14 @@ mod tests {
output.append(&mut all_finite_bounded_pairs());
//bounded-unbounded
for start_bound in all_finite_bounded() {
- output.push((start_bound, Bound::Unbounded));
+ output.push((start_bound, u()));
}
//unbounded-bounded
for end_bound in all_finite_bounded() {
- output.push((Bound::Unbounded, end_bound));
+ output.push((u(), end_bound));
}
//unbounded-unbounded
- output.push((Bound::Unbounded, Bound::Unbounded));
+ output.push(uu());
return output;
}
@@ -1538,4 +1881,35 @@ mod tests {
true => Bound::Excluded(x),
}
}
+
+ fn uu() -> TestBounds {
+ (Bound::Unbounded, Bound::Unbounded)
+ }
+ fn ui(x: u8) -> TestBounds {
+ (Bound::Unbounded, Bound::Included(x))
+ }
+ fn ue(x: u8) -> TestBounds {
+ (Bound::Unbounded, Bound::Excluded(x))
+ }
+ fn iu(x: u8) -> TestBounds {
+ (Bound::Included(x), Bound::Unbounded)
+ }
+ //fn eu(x: u8) -> TestBounds {
+ //(Bound::Excluded(x), Bound::Unbounded)
+ //}
+ fn ii(x1: u8, x2: u8) -> TestBounds {
+ (Bound::Included(x1), Bound::Included(x2))
+ }
+ fn ie(x1: u8, x2: u8) -> TestBounds {
+ (Bound::Included(x1), Bound::Excluded(x2))
+ }
+ fn ei(x1: u8, x2: u8) -> TestBounds {
+ (Bound::Excluded(x1), Bound::Included(x2))
+ }
+ fn ee(x1: u8, x2: u8) -> TestBounds {
+ (Bound::Excluded(x1), Bound::Excluded(x2))
+ }
+ fn u() -> Bound {
+ Bound::Unbounded
+ }
}
diff --git a/src/try_from_bounds.rs b/src/try_from_bounds.rs
index ed79769..43f1153 100644
--- a/src/try_from_bounds.rs
+++ b/src/try_from_bounds.rs
@@ -22,6 +22,8 @@ use std::ops::{
RangeToInclusive,
};
+use labels::{not_a_fn, trivial};
+
/// A "newtype" trait to copy [`TryFrom`].
///
/// I am forced to use this "newtype" instead of [`TryFrom`] because
@@ -35,6 +37,7 @@ use std::ops::{
/// [`TryFrom`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html
/// [`Range`]: https://doc.rust-lang.org/std/ops/struct.Range.html
pub trait TryFromBounds {
+ #[not_a_fn]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
@@ -44,6 +47,7 @@ pub trait TryFromBounds {
}
impl TryFromBounds for (Bound, Bound) {
+ #[trivial]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
@@ -53,6 +57,7 @@ impl TryFromBounds for (Bound, Bound) {
}
impl TryFromBounds for Range {
+ #[trivial]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
@@ -65,6 +70,7 @@ impl TryFromBounds for Range {
}
impl TryFromBounds for RangeInclusive {
+ #[trivial]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
@@ -77,6 +83,7 @@ impl TryFromBounds for RangeInclusive {
}
impl TryFromBounds for RangeFrom {
+ #[trivial]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
@@ -89,6 +96,7 @@ impl TryFromBounds for RangeFrom {
}
impl TryFromBounds for RangeTo {
+ #[trivial]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
@@ -101,6 +109,7 @@ impl TryFromBounds for RangeTo {
}
impl TryFromBounds for RangeToInclusive {
+ #[trivial]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
@@ -113,6 +122,7 @@ impl TryFromBounds for RangeToInclusive {
}
impl TryFromBounds for RangeFull {
+ #[trivial]
fn try_from_bounds(
start_bound: Bound,
end_bound: Bound,
diff --git a/todo.txt b/todo.txt
index 61a5281..07020b9 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,10 @@
# testing
-- apply labels to crate and test #[untested]'s
-- test for atomnicity, if it fails it shouldn't affect the map
+- test #[untested]'s
+- add tests for TryFromBounds fails for those that produce them with
+ atomnicity tests
+
+# features
+- RangeMap, RangeSet, RangeInclusiveMap...
# docs
- write something somewhere about wrapper types for RangeBoundsMap
@@ -13,6 +17,7 @@
- use it in robot_Sweet_graph for a bit before publishing
# final checks
+- check toml meta-data, github meta-data and readme opener
- copy map to set again
- copy readme to lib.rs docs again
- take a look around idiomatic rust for a bit first