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