diff --git a/Cargo.lock b/Cargo.lock index 74cf022..750e286 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,7 +26,7 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "discrete_range_map" -version = "0.6.0" +version = "0.6.1" dependencies = [ "btree_monstrousity", "either", diff --git a/Cargo.toml b/Cargo.toml index a4b06ee..65ba1ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,6 @@ itertools = { version = "0.12.0", default-features = false } [dev-dependencies] pretty_assertions = "1.4.0" + +[lints.rust] +missing_docs = "deny" diff --git a/src/discrete_finite.rs b/src/discrete_finite.rs index 309be75..821db3d 100644 --- a/src/discrete_finite.rs +++ b/src/discrete_finite.rs @@ -17,13 +17,23 @@ You should have received a copy of the GNU Affero General Public License along with discrete_range_map. If not, see . */ +//! A module containing the [`DiscreteFinite`] trait and trait impls for the +//! primitive integer datatypes. + +/// A trait for things which are both discrete and finite datatypes. See the +/// top-level module documentation for more detailed descriptions on +/// discrete-ness and finite-ness. pub trait DiscreteFinite { + /// The minimum value of the type. const MIN: Self; + /// The maximum value of the type. const MAX: Self; + /// The smallest value greater than `self` if one exists. fn up(self) -> Option where Self: Sized; + /// The greatest value smaller than `self` if one exists. fn down(self) -> Option where Self: Sized; diff --git a/src/discrete_range_map.rs b/src/discrete_range_map.rs index 852dd37..5033ef4 100644 --- a/src/discrete_range_map.rs +++ b/src/discrete_range_map.rs @@ -17,11 +17,14 @@ You should have received a copy of the GNU Affero General Public License along with discrete_range_map. If not, see . */ +//! The module containing [`DiscreteRangeMap`] and related types. + use alloc::vec::Vec; use core::cmp::Ordering; use core::fmt::{self, Debug}; use core::iter::once; use core::marker::PhantomData; +use core::ops::{Bound, RangeBounds}; use btree_monstrousity::btree_map::{ IntoIter as BTreeMapIntoIter, SearchBoundCustom, @@ -33,9 +36,8 @@ use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::discrete_finite::DiscreteFinite; -use crate::interval::InclusiveInterval; use crate::utils::{cmp_point_with_range, cut_range, is_valid_range, overlaps}; +use crate::DiscreteFinite; /// An ordered map of non-overlapping ranges based on [`BTreeMap`]. /// @@ -88,10 +90,45 @@ pub struct DiscreteRangeMap { #[derive(PartialEq, Debug)] pub struct OverlapError; +/// A compatibility type used in [`RangeType`] for allowing the library to +/// create the custom K type used in the map when necessary. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct InclusiveInterval { + /// The start of the interval, inclusive. + pub start: I, + /// The end of the interval, inclusive. + pub end: I, +} +impl RangeBounds for InclusiveInterval +where + I: PointType, +{ + fn start_bound(&self) -> Bound<&I> { + Bound::Included(&self.start) + } + + fn end_bound(&self) -> Bound<&I> { + Bound::Included(&self.end) + } +} +impl InclusiveRange for InclusiveInterval +where + I: PointType, +{ + fn start(&self) -> I { + self.start + } + + fn end(&self) -> I { + self.end + } +} + /// 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: @@ -1469,9 +1506,12 @@ where /// A range that has **Inclusive** end-points. pub trait InclusiveRange { + /// The start of the range, inclusive. fn start(&self) -> I; + /// The end of the range, inclusive. fn end(&self) -> I; + /// Does the range contain the given point? fn contains(&self, point: I) -> bool where I: PointType, @@ -1479,6 +1519,8 @@ pub trait InclusiveRange { point >= self.start() && point <= self.end() } + /// Is the range is valid, which according to this crate means `start()` + /// <= `end()` fn is_valid(&self) -> bool where I: PointType, @@ -1486,7 +1528,7 @@ pub trait InclusiveRange { self.start() <= self.end() } - /// requires that self comes before other and they don't overlap + /// Requires that self comes before other and they don't overlap fn touches_ordered(&self, other: &Self) -> bool where I: PointType, @@ -1494,7 +1536,7 @@ pub trait InclusiveRange { self.end() == other.start().down().unwrap() } - /// requires that self comes before other + /// Requires that self comes before other fn overlaps_ordered(&self, other: &Self) -> bool where I: PointType, @@ -1542,7 +1584,7 @@ pub trait InclusiveRange { (self.end() - self.start()).up().unwrap() } - /// requires that self comes before other + /// Requires that self comes before other fn merge_ordered(&self, other: &Self) -> Self where Self: From>, @@ -1770,7 +1812,7 @@ mod tests { dbg!(overlap_range, inside_range); dbg!(overlapping, expected_overlapping); panic!( - "Discrepency in .overlapping() with single inside range detected!" + "Discrepancy in .overlapping() with single inside range detected!" ); } } @@ -1810,7 +1852,7 @@ mod tests { dbg!(overlap_range, inside_range1, inside_range2); dbg!(overlapping, expected_overlapping); panic!( - "Discrepency in .overlapping() with two inside ranges detected!" + "Discrepancy in .overlapping() with two inside ranges detected!" ); } } @@ -2224,7 +2266,7 @@ mod tests { if our_answer != mathematical_definition_of_overlap { dbg!(range1, range2); dbg!(mathematical_definition_of_overlap, our_answer); - panic!("Discrepency in overlaps() detected!"); + panic!("Discrepancy in overlaps() detected!"); } } } diff --git a/src/discrete_range_set.rs b/src/discrete_range_set.rs index 4b02c38..ea98880 100644 --- a/src/discrete_range_set.rs +++ b/src/discrete_range_set.rs @@ -1,3 +1,27 @@ +/* +Copyright 2022,2023 James Forster + +This file is part of discrete_range_map. + +discrete_range_map is free software: you can redistribute it and/or +modify it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +discrete_range_map is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with discrete_range_map. If not, see . +*/ + +//! The module containing [`DiscreteRangeSet`] and related types. Since +//! [`DiscreteRangeSet`] is just a wrapper around [`DiscreteRangeMap`], most of +//! the methods' docs will point towards the equivalent method's docs on +//! [`DiscreteRangeMap`] to prevent inconsistency. + use core::fmt; use core::marker::PhantomData; @@ -5,10 +29,8 @@ use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::discrete_range_map::{ - IntoIter as DiscreteRangeMapIntoIter, PointType, RangeType, -}; -use crate::{DiscreteRangeMap, OverlapError}; +use crate::discrete_range_map::IntoIter as DiscreteRangeMapIntoIter; +use crate::{DiscreteRangeMap, OverlapError, PointType, RangeType}; /// An ordered set of non-overlapping ranges based on [`DiscreteRangeMap`]. /// diff --git a/src/interval.rs b/src/interval.rs deleted file mode 100644 index 6952343..0000000 --- a/src/interval.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2022,2023 James Forster - -This file is part of discrete_range_map. - -discrete_range_map is free software: you can redistribute it and/or -modify it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. - -discrete_range_map is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with discrete_range_map. If not, see . -*/ - -use core::ops::{Bound, RangeBounds}; - -use serde::{Deserialize, Serialize}; - -use crate::discrete_range_map::{InclusiveRange, PointType}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct InclusiveInterval { - pub start: I, - pub end: I, -} - -impl InclusiveInterval where I: PointType {} - -impl RangeBounds for InclusiveInterval -where - I: PointType, -{ - fn start_bound(&self) -> Bound<&I> { - Bound::Included(&self.start) - } - - fn end_bound(&self) -> Bound<&I> { - Bound::Included(&self.end) - } -} - -impl InclusiveRange for InclusiveInterval -where - I: PointType, -{ - fn start(&self) -> I { - self.start - } - - fn end(&self) -> I { - self.end - } -} diff --git a/src/lib.rs b/src/lib.rs index 7360eb3..ee2ceb6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,7 +127,7 @@ along with discrete_range_map. If not, see . //! `String` is a `Continuous` if you try to parse it as a decimal value. //! //! The reason for this is that common [`interval-Mathematics`] operations -//! differ depending on wether the underlying type is `Discrete` or +//! differ depending on whether the underlying type is `Discrete` or //! `Continuous`. For example `5..=6` touches `7..=8` since integers are //! `Discrete` but `5.0..=6.0` does **not** touch `7.0..=8.0` since the //! value `6.5` exists. @@ -165,7 +165,7 @@ along with discrete_range_map. If not, see . //! | 0..0 | NO | //! | 0..1 | YES | //! | 9..8 | NO | -//! | (Bound::Exluded(3), Bound::Exluded(4)) | NO | +//! | (Bound::Excluded(3), Bound::Excluded(4)) | NO | //! | 400..=400 | YES | //! //! ### Overlap @@ -275,18 +275,16 @@ along with discrete_range_map. If not, see . extern crate alloc; -pub mod test_ranges; pub(crate) mod utils; pub mod discrete_finite; -pub mod interval; - pub mod discrete_range_map; pub mod discrete_range_set; +pub mod test_ranges; pub use crate::discrete_finite::DiscreteFinite; pub use crate::discrete_range_map::{ - DiscreteRangeMap, InclusiveRange, OverlapError, PointType, RangeType, + DiscreteRangeMap, InclusiveInterval, InclusiveRange, OverlapError, + PointType, RangeType, }; pub use crate::discrete_range_set::DiscreteRangeSet; -pub use crate::interval::InclusiveInterval; diff --git a/src/test_ranges.rs b/src/test_ranges.rs index 57ffef2..fa85bbc 100644 --- a/src/test_ranges.rs +++ b/src/test_ranges.rs @@ -1,48 +1,81 @@ -use crate::discrete_finite::DiscreteFinite; -use crate::interval::InclusiveInterval; +/* +Copyright 2022,2023 James Forster +This file is part of discrete_range_map. + +discrete_range_map is free software: you can redistribute it and/or +modify it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +discrete_range_map is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with discrete_range_map. If not, see . +*/ + +//! A collection of helper functions for making [`InclusiveInterval`]s from `i8`'s used for testing +//! and example purposes. + +use crate::{DiscreteFinite, InclusiveInterval}; + +/// An unbounded-unbounded interval pub fn uu() -> InclusiveInterval { InclusiveInterval { start: i8::MIN, end: i8::MAX, } } +/// An unbounded-included interval pub fn ui(x: i8) -> InclusiveInterval { InclusiveInterval { start: i8::MIN, end: x, } } +/// An unbounded-excluded interval pub fn ue(x: i8) -> InclusiveInterval { InclusiveInterval { start: i8::MIN, end: x.down().unwrap(), } } +/// An included-unbounded interval pub fn iu(x: i8) -> InclusiveInterval { InclusiveInterval { start: x, end: i8::MAX, } } -//fn eu(x: i8) -> TestBounds { -//(Bound::Excluded(x), Bound::Unbounded) -//} +/// An excluded-unbounded interval +pub fn eu(x: i8) -> InclusiveInterval { + InclusiveInterval { + start: x.up().unwrap(), + end: i8::MAX, + } +} +/// An included-included interval pub fn ii(x1: i8, x2: i8) -> InclusiveInterval { InclusiveInterval { start: x1, end: x2 } } +/// An included-excluded interval pub fn ie(x1: i8, x2: i8) -> InclusiveInterval { InclusiveInterval { start: x1, end: x2.down().unwrap(), } } +/// An excluded-included interval pub fn ei(x1: i8, x2: i8) -> InclusiveInterval { InclusiveInterval { start: x1.up().unwrap(), end: x2, } } +/// An excluded-excluded interval pub fn ee(x1: i8, x2: i8) -> InclusiveInterval { InclusiveInterval { start: x1.up().unwrap(), diff --git a/src/utils.rs b/src/utils.rs index 9c5383c..f7d1d6c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,8 +19,7 @@ along with discrete_range_map. If not, see . use core::cmp::Ordering; -use crate::discrete_range_map::{PointType, RangeType}; -use crate::interval::InclusiveInterval; +use crate::{InclusiveInterval, PointType, RangeType}; pub(crate) fn cmp_point_with_range(point: I, range: K) -> Ordering where