diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c97a395 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,128 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "btree_monstrousity" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4d0977e9c15f276380f16f2e9594257c258172b23af39ffd2e4cf5971cb38c7" +dependencies = [ + "cfg-if", + "rustversion", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "discrete_range_map" +version = "0.5.2" +dependencies = [ + "btree_monstrousity", + "either", + "itertools", + "pretty_assertions", + "serde", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[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 3a00472..87e42ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,17 @@ keywords = ["data-structures", "map", "data", "library"] categories = ["data-structures"] [dependencies] -serde = {version = "1.0.188", features = ["derive"]} -btree_monstrousity = {version ="0.0.4", features = ["btree_drain_filter", "btree_cursors"]} -either = "1.9.0" -itertools = "0.11.0" +serde = { version = "1.0.193", features = ["derive"], default-features = false } +btree_monstrousity = { version = "0.0.4", features = [ + "btree_drain_filter", + "btree_cursors", +], default-features = false } +either = { version = "1.9.0", default-features = false } +itertools = { version = "0.12.0", default-features = false } [dev-dependencies] pretty_assertions = "1.3.0" + +[features] +default = ["std"] +std = ["either/use_std", "itertools/use_std", "serde/std"] diff --git a/src/discrete_range_map.rs b/src/discrete_range_map.rs index 8e9a165..9cac238 100644 --- a/src/discrete_range_map.rs +++ b/src/discrete_range_map.rs @@ -87,10 +87,27 @@ pub struct DiscreteRangeMap { #[derive(PartialEq, Debug)] pub struct OverlapError; +/// The marker trait for valid point types, a blanket implementation is provided for all types +/// which implement this traits' super-traits so you shouln't need to implement this yourself. +pub trait PointType: Ord + Copy + DiscreteFinite {} +impl PointType for I where I: Ord + Copy + DiscreteFinite {} +/// The marker trait for valid range types, a blanket implementation is provided for all types +/// which implement this traits' super-traits so you shouln't need to implement this yourself. +pub trait RangeType: + InclusiveRange + Copy + From> +{ +} +impl RangeType for K +where + I: PointType, + K: InclusiveRange + Copy + From>, +{ +} + impl DiscreteRangeMap where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange + Copy + From>, + I: PointType, + K: RangeType, { /// Returns `true` if the given range overlaps any of the /// other ranges in the map, and `false` if not. @@ -118,7 +135,7 @@ where /// ``` pub fn overlaps(&self, range: Q) -> bool where - Q: InclusiveRange + Copy, + Q: RangeType, { invalid_range_panic(range); @@ -158,7 +175,7 @@ where range: Q, ) -> impl DoubleEndedIterator where - Q: InclusiveRange + Copy, + Q: RangeType, { invalid_range_panic(range); @@ -206,7 +223,7 @@ where range: Q, ) -> impl DoubleEndedIterator where - Q: InclusiveRange + Copy, + Q: RangeType, { invalid_range_panic(range); @@ -371,7 +388,7 @@ where range: Q, ) -> impl Iterator + '_ where - Q: InclusiveRange + Copy + 'a, + Q: RangeType + 'a, { invalid_range_panic(range); @@ -435,7 +452,7 @@ where range: Q, ) -> impl Iterator + '_ where - Q: InclusiveRange + Copy + 'a, + Q: RangeType + 'a, V: Clone, { invalid_range_panic(range); @@ -454,11 +471,18 @@ where .map(|(key, _)| key) .copied(); - if let Some(left) = left_overlapping && let Some(right) = right_overlapping && left.start() == right.start() { - Either::Left(self.cut_single_overlapping(range, left)) - } else { - Either::Right(self.cut_non_single_overlapping(range, left_overlapping, right_overlapping)) - } + if let Some(left) = left_overlapping + && let Some(right) = right_overlapping + && left.start() == right.start() + { + Either::Left(self.cut_single_overlapping(range, left)) + } else { + Either::Right(self.cut_non_single_overlapping( + range, + left_overlapping, + right_overlapping, + )) + } } fn cut_single_overlapping( &mut self, @@ -466,7 +490,7 @@ where single_overlapping_range: K, ) -> impl Iterator where - Q: InclusiveRange + Copy, + Q: RangeType, V: Clone, { invalid_range_panic(range); @@ -494,7 +518,7 @@ where right_overlapping: Option, ) -> impl Iterator + '_ where - Q: InclusiveRange + Copy + 'a, + Q: RangeType + 'a, V: Clone, { invalid_range_panic(range); @@ -554,7 +578,7 @@ where value, ) })) - .chain(keeping_after_entry.into_iter()); + .chain(keeping_after_entry); } /// Returns an iterator of ranges over all the maximally-sized @@ -587,7 +611,7 @@ where /// ``` pub fn gaps<'a, Q>(&'a self, outer_range: Q) -> impl Iterator + '_ where - Q: InclusiveRange + Copy + 'a, + Q: RangeType + 'a, { invalid_range_panic(outer_range); @@ -648,7 +672,7 @@ where .map(K::from) .into_iter() .chain(inner_gaps) - .chain(trimmed_end_gap.map(K::from).into_iter()); + .chain(trimmed_end_gap.map(K::from)); } /// Returns `true` if the map covers every point in the given @@ -678,7 +702,7 @@ where /// ``` pub fn contains_range(&self, range: Q) -> bool where - Q: InclusiveRange + Copy, + Q: RangeType, { invalid_range_panic(range); @@ -1397,8 +1421,8 @@ impl DiscreteRangeMap { fn invalid_range_panic(range: Q) where - Q: InclusiveRange, - I: Ord, + I: PointType, + Q: RangeType, { if !is_valid_range(range) { panic!( @@ -1409,22 +1433,22 @@ where fn double_comp() -> impl FnMut(&K, &K) -> Ordering where - K: InclusiveRange, - I: Ord + DiscreteFinite, + I: PointType, + K: RangeType, { |inner_range: &K, new_range: &K| new_range.start().cmp(&inner_range.start()) } fn overlapping_comp(point: I) -> impl FnMut(&K) -> Ordering where - I: Ord + Copy, - K: InclusiveRange + Copy, + I: PointType, + K: RangeType, { move |inner_range: &K| cmp_point_with_range(point, *inner_range) } fn touching_start_comp(start: I) -> impl FnMut(&K) -> Ordering where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange, + I: PointType, + K: RangeType, { move |inner_range: &K| match inner_range.end().up() { Some(touching_position) => start.cmp(&touching_position), @@ -1433,8 +1457,8 @@ where } fn touching_end_comp(end: I) -> impl FnMut(&K) -> Ordering where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange, + I: PointType, + K: RangeType, { move |inner_range: &K| match inner_range.start().down() { Some(touching_position) => end.cmp(&touching_position), @@ -1449,14 +1473,14 @@ pub trait InclusiveRange { fn contains(&self, point: I) -> bool where - I: Ord, + I: PointType, { point >= self.start() && point <= self.end() } fn is_valid(&self) -> bool where - I: Ord, + I: PointType, { self.start() <= self.end() } @@ -1464,7 +1488,7 @@ pub trait InclusiveRange { ///requires that self comes before other and they don't overlap fn touches_ordered(&self, other: &Self) -> bool where - I: DiscreteFinite + Ord, + I: PointType, { self.end() == other.start().down().unwrap() } @@ -1472,7 +1496,7 @@ pub trait InclusiveRange { ///requires that self comes before other fn overlaps_ordered(&self, other: &Self) -> bool where - I: DiscreteFinite + Ord, + I: PointType, { self.contains(other.start()) || self.contains(other.end()) } @@ -1548,8 +1572,8 @@ where impl<'de, I, K, V> Deserialize<'de> for DiscreteRangeMap where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange + Copy + From> + Deserialize<'de>, + I: PointType, + K: RangeType + Deserialize<'de>, V: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result @@ -1572,8 +1596,8 @@ struct DiscreteRangeMapVisitor { impl<'de, I, K, V> Visitor<'de> for DiscreteRangeMapVisitor where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange + Copy + From> + Deserialize<'de>, + I: PointType, + K: RangeType + Deserialize<'de>, V: Deserialize<'de>, { type Value = DiscreteRangeMap; @@ -1605,9 +1629,9 @@ mod tests { //only every other number to allow mathematical_overlapping_definition //to test between bounds in finite using smaller intervalled finite - pub(crate) const NUMBERS: &'static [i8] = &[2, 4, 6, 8, 10]; + pub(crate) const NUMBERS: &[i8] = &[2, 4, 6, 8, 10]; //go a bit around on either side to compensate for Unbounded - pub(crate) const NUMBERS_DOMAIN: &'static [i8] = + pub(crate) const NUMBERS_DOMAIN: &[i8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; fn basic() -> DiscreteRangeMap, bool> { @@ -1728,12 +1752,11 @@ mod tests { expected_overlapping.push(inside_range2); } //make our expected_overlapping the correct order - if expected_overlapping.len() > 1 { - if expected_overlapping[0].start() + if expected_overlapping.len() > 1 + && expected_overlapping[0].start() > expected_overlapping[1].start() - { - expected_overlapping.swap(0, 1); - } + { + expected_overlapping.swap(0, 1); } let overlapping = map diff --git a/src/discrete_range_set.rs b/src/discrete_range_set.rs index 9183a48..9619737 100644 --- a/src/discrete_range_set.rs +++ b/src/discrete_range_set.rs @@ -5,11 +5,9 @@ use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::discrete_finite::DiscreteFinite; use crate::discrete_range_map::{ - InclusiveRange, IntoIter as DiscreteRangeMapIntoIter, + IntoIter as DiscreteRangeMapIntoIter, PointType, RangeType, }; -use crate::interval::InclusiveInterval; use crate::{DiscreteRangeMap, OverlapError}; /// An ordered set of non-overlapping ranges based on [`DiscreteRangeMap`]. @@ -30,13 +28,13 @@ pub struct DiscreteRangeSet { impl DiscreteRangeSet where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange + Copy + From>, + I: PointType, + K: RangeType, { /// See [`DiscreteRangeMap::overlaps()`] for more details. pub fn overlaps(&self, range: Q) -> bool where - Q: InclusiveRange + Copy, + Q: RangeType, { self.inner.overlaps(range) } @@ -46,7 +44,7 @@ where range: Q, ) -> impl DoubleEndedIterator where - Q: InclusiveRange + Copy, + Q: RangeType, { self.inner.overlapping(range).map(first) } @@ -64,28 +62,28 @@ where range: Q, ) -> impl Iterator + '_ where - Q: InclusiveRange + Copy + 'a, + Q: RangeType + 'a, { self.inner.remove_overlapping(range).map(first) } /// See [`DiscreteRangeMap::cut()`] for more details. pub fn cut<'a, Q>(&'a mut self, range: Q) -> impl Iterator + '_ where - Q: InclusiveRange + Copy + 'a, + Q: RangeType + 'a, { self.inner.cut(range).map(first) } /// See [`DiscreteRangeMap::gaps()`] for more details. pub fn gaps<'a, Q>(&'a self, range: Q) -> impl Iterator + '_ where - Q: InclusiveRange + Copy + 'a, + Q: RangeType + 'a, { self.inner.gaps(range) } /// See [`DiscreteRangeMap::contains_range()`] for more details. pub fn contains_range(&self, range: Q) -> bool where - Q: InclusiveRange + Copy, + Q: RangeType, { self.inner.contains_range(range) } @@ -200,7 +198,7 @@ impl Iterator for IntoIter { impl Default for DiscreteRangeSet where - I: PartialOrd, + I: PointType, { fn default() -> Self { DiscreteRangeSet { @@ -227,8 +225,8 @@ where impl<'de, I, K> Deserialize<'de> for DiscreteRangeSet where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange + Copy + From> + Deserialize<'de>, + I: PointType, + K: RangeType + Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where @@ -248,8 +246,8 @@ struct DiscreteRangeSetVisitor { impl<'de, I, K> Visitor<'de> for DiscreteRangeSetVisitor where - I: Ord + Copy + DiscreteFinite, - K: InclusiveRange + Copy + From> + Deserialize<'de>, + I: PointType, + K: RangeType + Deserialize<'de>, { type Value = DiscreteRangeSet;