From 78dff0d99e2d82af79c2dac0f3ffbd5bf3592c0a Mon Sep 17 00:00:00 2001 From: ripytide Date: Wed, 30 Nov 2022 16:25:17 +0000 Subject: [PATCH] added range_bound_map.rs main examples and documentation --- README.md | 10 +---- rustfmt.toml | 3 ++ src/lib.rs | 49 +++++++++++----------- src/range_bounds_map.rs | 91 +++++++++++++++++++++++++++++++++++++++-- src/range_bounds_set.rs | 48 ++++++++++++---------- 5 files changed, 143 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index e707779..a433ae1 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,6 @@ - add examples for all functions in rust doc comments and test them with cargo doc-test -- add some actual rust example files in an example folder - -- convert README to cool format using links to docs - - add github badges including lib.rs - make logo @@ -19,14 +15,12 @@ - use it in robot_Sweet_graph for a bit before publishing +- copy docs from set to map and update appropriately + - update lines of code figures on docs - make all functions' trait bounds specific instead of at impl level -- convert all examples not using `from` to use `from`, and tests - -- turn overlaps back into a trait to make it public, mabye - - review caveats again - run cargo fmt diff --git a/rustfmt.toml b/rustfmt.toml index f71dad7..2d2ebf9 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -4,3 +4,6 @@ hard_tabs=true imports_granularity="Module" group_imports="StdExternalCrate" max_width=80 +format_code_in_doc_comments=true +doc_comment_code_block_width=70 +unstable_features = true diff --git a/src/lib.rs b/src/lib.rs index 7706a4c..e6385f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,53 +45,52 @@ along with range_bounds_map. If not, see . //! //! # Example using a custom [`RangeBounds`] type //! ``` -//! use std::ops::RangeBounds; -//! use std::ops::Bound; +//! 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) +//! // Start, End (Inclusive-Inclusive) +//! Finite(u8, u8), +//! // Start (Exclusive) +//! Infinite(u8), //! } //! //! // First, we need to implement RangeBounds //! impl RangeBounds 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, -//! } -//! } +//! 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(); +//! (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"); +//! println!("{name} has reserved {reservation:?} inside the range 16..17"); //! } //! //! for (reservation, name) in reservation_map.iter() { -//! println!("{name} has reserved {reservation:?}"); +//! println!("{name} has reserved {reservation:?}"); //! } //! //! assert_eq!(reservation_map.overlaps(&Reservation::Infinite(0)), true); //! ``` //! -//! //! # How //! //! Most of the [`RangeBounds`]-specific methods on [`RangeBoundsMap`] @@ -173,7 +172,7 @@ along with range_bounds_map. If not, see . //! //! [`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/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 diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs index 369aaff..4062b52 100644 --- a/src/range_bounds_map.rs +++ b/src/range_bounds_map.rs @@ -26,6 +26,91 @@ use either::Either; use crate::bounds::StartBound; +/// An ordered map of [`RangeBounds`] based on [`BTreeMap`] +/// +/// # Examples +/// ``` +/// use range_bounds_map::RangeBoundsMap; +/// +/// // Make a map of ranges to booleans +/// let mut map = RangeBoundsMap::try_from([ +/// (4..8, false), +/// (8..18, true), +/// (20..100, false), +/// ]) +/// .unwrap(); +/// +/// // Change a value in the map +/// *map.get_at_point_mut(&(7)).unwrap() = true; +/// +/// // Get a value in the map +/// if map.contains_point(&99) { +/// println!("Map contains value at 99 :)"); +/// } +/// +/// // Iterate over the entries in the map +/// for (range, value) in map.iter() { +/// println!("{range:?}, {value:?}"); +/// } +/// ``` +/// Example using a custom [`RangeBounds`] type: +/// ``` +/// use std::ops::{Bound, RangeBounds}; +/// +/// use ordered_float::NotNan; +/// use range_bounds_map::RangeBoundsMap; +/// +/// // An Exlusive-Exlusive range of [`f32`]s not provided by any +/// // std::ops ranges +/// // We use [`ordered_float::NotNan`]s as the inner type must be Ord +/// // similar to a normal [`BTreeSet`] +/// #[derive(Debug, PartialEq)] +/// struct ExEx { +/// start: NotNan, +/// end: NotNan, +/// } +/// # impl ExEx { +/// # fn new(start: f32, end: f32) -> ExEx { +/// # ExEx { +/// # start: NotNan::new(start).unwrap(), +/// # end: NotNan::new(end).unwrap(), +/// # } +/// # } +/// # } +/// +/// // Implement RangeBounds on our new type +/// impl RangeBounds> for ExEx { +/// fn start_bound(&self) -> Bound<&NotNan> { +/// Bound::Excluded(&self.start) +/// } +/// fn end_bound(&self) -> Bound<&NotNan> { +/// Bound::Excluded(&self.end) +/// } +/// } +/// +/// // Now we can make a [`RangeBoundsMap`] of [`ExEx`]s to `u8` +/// let mut map = RangeBoundsMap::new(); +/// +/// map.insert(ExEx::new(0.0, 5.0), 8).unwrap(); +/// map.insert(ExEx::new(5.0, 7.5), 32).unwrap(); +/// +/// assert_eq!(map.contains_point(&NotNan::new(5.0).unwrap()), false); +/// +/// assert_eq!(map.get_at_point(&NotNan::new(9.0).unwrap()), None); +/// assert_eq!( +/// map.get_at_point(&NotNan::new(7.0).unwrap()), +/// Some(&32) +/// ); +/// +/// assert_eq!( +/// map.get_key_value_at_point(&NotNan::new(2.0).unwrap()), +/// Some((&ExEx::new(0.0, 5.0), &8)) +/// ); +/// ``` +/// +/// [`RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html +/// [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html +#[derive(Debug)] pub struct RangeBoundsMap { starts: BTreeMap, (K, V)>, } @@ -41,9 +126,9 @@ where } } - pub fn len(&self) -> usize { - self.starts.len() - } + pub fn len(&self) -> usize { + self.starts.len() + } //returns Err(()) if the given range overlaps another range //does not coalesce ranges if they touch diff --git a/src/range_bounds_set.rs b/src/range_bounds_set.rs index acf62a6..bdde7ee 100644 --- a/src/range_bounds_set.rs +++ b/src/range_bounds_set.rs @@ -31,21 +31,20 @@ use crate::range_bounds_map::RangeBoundsMap; /// let visits = RangeBoundsSet::try_from([4..8, 8..18, 20..100]).unwrap(); /// /// // Check if a point is contained in the set -/// if visits.contains_point(&0) { -/// println!("No visit at the beginning ;("); +/// if !visits.contains_point(&0) { +/// println!("No visit at the beginning ;("); /// } /// /// // Iterate over the ranges overlapping another range /// for visit in visits.overlapping(&(2..=8)) { -/// println!("{visit:?}"); +/// println!("{visit:?}"); /// } /// ``` /// Example using a custom [`RangeBounds`] type: /// ``` -/// use std::ops::Bound; -/// use std::ops::RangeBounds; -/// use ordered_float::NotNan; +/// use std::ops::{Bound, RangeBounds}; /// +/// use ordered_float::NotNan; /// use range_bounds_map::RangeBoundsSet; /// /// // An Exlusive-Exlusive range of [`f32`]s not provided by any @@ -53,8 +52,8 @@ use crate::range_bounds_map::RangeBoundsMap; /// // We use [`ordered_float::NotNan`]s as the inner type must be Ord /// // similar to a normal [`BTreeSet`] /// struct ExEx { -/// start: NotNan, -/// end: NotNan, +/// start: NotNan, +/// end: NotNan, /// } /// # impl ExEx { /// # fn new(start: f32, end: f32) -> ExEx { @@ -67,12 +66,12 @@ use crate::range_bounds_map::RangeBoundsMap; /// /// // Implement RangeBounds on our new type /// impl RangeBounds> for ExEx { -/// fn start_bound(&self) -> Bound<&NotNan> { -/// Bound::Excluded(&self.start) -/// } -/// fn end_bound(&self) -> Bound<&NotNan> { -/// Bound::Excluded(&self.end) -/// } +/// fn start_bound(&self) -> Bound<&NotNan> { +/// Bound::Excluded(&self.start) +/// } +/// fn end_bound(&self) -> Bound<&NotNan> { +/// Bound::Excluded(&self.end) +/// } /// } /// /// // Now we can make a [`RangeBoundsSet`] of [`ExEx`]s @@ -81,12 +80,12 @@ use crate::range_bounds_map::RangeBoundsMap; /// set.insert(ExEx::new(0.0, 5.0)).unwrap(); /// set.insert(ExEx::new(5.0, 7.5)).unwrap(); /// -/// assert_eq!(set.contains_point(&(NotNan::new(5.0).unwrap())), false); -/// assert_eq!(set.contains_point(&(NotNan::new(7.0).unwrap())), true); -/// assert_eq!(set.contains_point(&(NotNan::new(7.5).unwrap())), false); +/// assert_eq!(set.contains_point(&NotNan::new(5.0).unwrap()), false); +/// assert_eq!(set.contains_point(&NotNan::new(7.0).unwrap()), true); +/// assert_eq!(set.contains_point(&NotNan::new(7.5).unwrap()), false); /// ``` /// -/// [`RangeBounds`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html +/// [`RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html /// [`BTreeSet`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html pub struct RangeBoundsSet { map: RangeBoundsMap, @@ -102,6 +101,7 @@ where /// # Examples /// ``` /// use std::ops::Range; + /// /// use range_bounds_map::RangeBoundsSet; /// /// let range_bounds_set: RangeBoundsSet> = RangeBoundsSet::new(); @@ -179,7 +179,8 @@ where /// ``` /// use range_bounds_map::RangeBoundsSet; /// - /// let range_bounds_set = RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); + /// let range_bounds_set = + /// RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); /// /// let mut overlapping = range_bounds_set.overlapping(&(2..8)); /// @@ -206,7 +207,8 @@ where /// ``` /// use range_bounds_map::RangeBoundsSet; /// - /// let range_bounds_set = RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); + /// let range_bounds_set = + /// RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); /// /// assert_eq!(range_bounds_set.get_at_point(&3), Some(&(1..4))); /// assert_eq!(range_bounds_set.get_at_point(&4), Some(&(4..8))); @@ -223,7 +225,8 @@ where /// ``` /// use range_bounds_map::RangeBoundsSet; /// - /// let range_bounds_set = RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); + /// let range_bounds_set = + /// RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); /// /// assert_eq!(range_bounds_set.contains_point(&3), true); /// assert_eq!(range_bounds_set.contains_point(&4), true); @@ -240,7 +243,8 @@ where /// ``` /// use range_bounds_map::RangeBoundsSet; /// - /// let range_bounds_set = RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); + /// let range_bounds_set = + /// RangeBoundsSet::try_from([1..4, 4..8, 8..100]).unwrap(); /// /// let mut iter = range_bounds_set.overlapping(&(2..8)); ///