diff --git a/src/nodit/map.rs b/src/nodit/map.rs index 30d0951..ad02c58 100644 --- a/src/nodit/map.rs +++ b/src/nodit/map.rs @@ -35,8 +35,8 @@ use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::utils::{ - cut_interval, starts_comp, invalid_interval_panic, overlapping_comp, - overlaps, touching_end_comp, touching_start_comp, + cut_interval, invalid_interval_panic, overlapping_comp, overlaps, + starts_comp, touching_end_comp, touching_start_comp, }; use crate::{DiscreteFinite, InclusiveInterval, Interval}; @@ -187,14 +187,12 @@ where { invalid_interval_panic(interval); - let start_comp = overlapping_comp(interval.start()); - let end_comp = overlapping_comp(interval.end()); - - let start_bound = SearchBoundCustom::Included; - let end_bound = SearchBoundCustom::Included; - - self.inner - .range(start_comp, start_bound, end_comp, end_bound) + self.inner.range( + overlapping_comp(interval.start()), + SearchBoundCustom::Included, + overlapping_comp(interval.end()), + SearchBoundCustom::Included, + ) } /// Returns an mutable iterator over every entry in the map that @@ -235,14 +233,12 @@ where { invalid_interval_panic(interval); - let start_comp = overlapping_comp(interval.start()); - let end_comp = overlapping_comp(interval.end()); - - let start_bound = SearchBoundCustom::Included; - let end_bound = SearchBoundCustom::Included; - - self.inner - .range_mut(start_comp, start_bound, end_comp, end_bound) + self.inner.range_mut( + overlapping_comp(interval.start()), + SearchBoundCustom::Included, + overlapping_comp(interval.end()), + SearchBoundCustom::Included, + ) } /// Returns a reference to the value corresponding to the interval in @@ -265,7 +261,9 @@ where /// assert_eq!(map.get_at_point(101), None); /// ``` pub fn get_at_point(&self, point: I) -> Option<&V> { - self.get_key_value_at_point(point).map(|(_, value)| value).ok() + self.get_key_value_at_point(point) + .map(|(_, value)| value) + .ok() } /// Returns a mutable reference to the value corresponding to the @@ -329,7 +327,10 @@ where /// ]) /// .unwrap(); /// - /// assert_eq!(map.get_key_value_at_point(3), Ok((&ie(1, 4), &false))); + /// assert_eq!( + /// map.get_key_value_at_point(3), + /// Ok((&ie(1, 4), &false)) + /// ); /// assert_eq!(map.get_key_value_at_point(5), Ok((&ie(4, 6), &true))); /// assert_eq!(map.get_key_value_at_point(7), Err(ie(6, 8))); /// assert_eq!(map.get_key_value_at_point(101), Err(iu(100))); @@ -416,8 +417,8 @@ where return result.into_iter(); } - /// Cuts a given interval out of the map and returns an iterator of the full or - /// partial intervals with their values that were cut in ascending order. + /// Cuts a given interval out of the map and returns an iterator of the full or + /// partial intervals with their values that were cut in ascending order. /// /// `V` must implement `Clone` as if you try to cut out the center /// of a interval in the map it will split into two different entries @@ -461,17 +462,14 @@ where { invalid_interval_panic(interval); - let start_comp = overlapping_comp(interval.start()); - let end_comp = overlapping_comp(interval.end()); - let left_overlapping = self .inner - .get_key_value(start_comp) + .get_key_value(overlapping_comp(interval.start())) .map(|(key, _)| key) .copied(); let right_overlapping = self .inner - .get_key_value(end_comp) + .get_key_value(overlapping_comp(interval.end())) .map(|(key, _)| key) .copied(); @@ -1339,7 +1337,7 @@ where pub fn from_slice_strict( slice: [(K, V); N], ) -> Result, OverlapError> { - NoditMap::from_iter_strict(slice.into_iter()) + NoditMap::from_iter_strict(slice.into_iter()) } /// Collects a `NoditMap` from an iterator of (interval, diff --git a/src/zosdit/map.rs b/src/zosdit/map.rs index 80a67d7..10b010d 100644 --- a/src/zosdit/map.rs +++ b/src/zosdit/map.rs @@ -1,11 +1,16 @@ //! A module containing [`ZosditMap`]. +//todo remove the inner Nodit since I't/don use it +//todo make nodit use the more robust comparators in general and refactor them to remove all the +//temporary variables before the comp calls +//remove overlapping_mut and replace with overlapping_start_comp and overlapping_end_comp use alloc::boxed::Box; use core::cmp::Ordering; use core::fmt; use core::marker::PhantomData; use btree_monstrousity::btree_map::SearchBoundCustom; +use btree_monstrousity::BTreeMap; use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -14,11 +19,11 @@ use smallvec::SmallVec; use crate::utils::{ exclusive_comp_generator, inclusive_comp_generator, invalid_interval_panic, }; -use crate::{IntervalType, NoditMap, PointType}; +use crate::{IntervalType, PointType}; type ValueStore = SmallVec<[V; 2]>; -/// A Zero Overlap Sequential Discrete Interval Tree Map Data-Structure based off [`NoditMap`] and +/// A Zero Overlap Sequential Discrete Interval Tree Map Data-Structure based off [`BTreeMap`] and /// [`SmallVec`] /// /// `I` is the generic type parameter for the [`Ord`] type the `K` @@ -52,7 +57,11 @@ type ValueStore = SmallVec<[V; 2]>; /// ``` #[derive(Debug, Clone, PartialEq, Eq)] pub struct ZosditMap { - nodit_map: NoditMap>, + //we can't use the btreemaps's len + //since we can have multiples values per key + len: usize, + inner: BTreeMap>, + phantom: PhantomData, } /// The error returned when inserting a interval that non-zero-overlaps another interval when it @@ -77,18 +86,16 @@ where /// let map: ZosditMap, bool> = ZosditMap::new(); /// ``` pub fn new() -> Self { - ZosditMap { - nodit_map: NoditMap::new(), - } + ZosditMap::default() } /// See [`NoditMap::len()`] for more details. pub fn len(&self) -> usize { - self.nodit_map.len() + self.len } /// See [`NoditMap::is_empty()`] for more details. pub fn is_empty(&self) -> bool { - self.nodit_map.is_empty() + self.len == 0 } /// Returns the first key-value pair in the map. @@ -110,7 +117,7 @@ where /// Some((&ii(0, 4), &-2)) /// ); pub fn first_key_value(&self) -> Option<(&K, &V)> { - let (key, value_store) = self.nodit_map.first_key_value()?; + let (key, value_store) = self.inner.first_key_value()?; let first_value = value_store.first()?; @@ -136,7 +143,7 @@ where /// Some((&ii(4, 4), &-8)) /// ); pub fn last_key_value(&self) -> Option<(&K, &V)> { - let (key, value_store) = self.nodit_map.last_key_value()?; + let (key, value_store) = self.inner.last_key_value()?; let last_value = value_store.last()?; @@ -164,8 +171,7 @@ where /// assert_eq!(map.get_last_value_at_point(10), None); /// ``` pub fn get_last_value_at_point(&self, point: I) -> Option<&V> { - self.nodit_map - .inner + self.inner .lower_bound( exclusive_comp_generator(point, Ordering::Greater), SearchBoundCustom::Included, @@ -215,8 +221,7 @@ where if !self.is_zero_overlap(interval) { Err(NonZeroOverlapError { value }) } else { - self.nodit_map - .inner + self.inner .entry(interval, |inner_interval, new_interval| { let start_result = exclusive_comp_generator( new_interval.start(), @@ -246,6 +251,8 @@ where .or_default() .push(value); + self.len += 1; + Ok(()) } } @@ -289,8 +296,7 @@ where //this elegant solution, there are a surprising amount of different scenarios when you //start considering zero-sized intervals and things - self.nodit_map - .inner + self.inner .range( exclusive_comp_generator(interval.start(), Ordering::Greater), SearchBoundCustom::Included, @@ -349,11 +355,9 @@ where { invalid_interval_panic(interval); - let cut = self.nodit_map.cut(interval); + todo!(); - cut.flat_map(|(interval, value_store)| { - value_store.into_iter().map(move |value| (interval, value)) - }) + [].into_iter() } /// The same as [`NoditMap::overlapping()`] except it flattens the `SmallVec`s of values into @@ -397,7 +401,7 @@ where { invalid_interval_panic(interval); - let overlapping = self.nodit_map.inner.range( + let overlapping = self.inner.range( inclusive_comp_generator(interval.start(), Ordering::Less), SearchBoundCustom::Included, inclusive_comp_generator(interval.end(), Ordering::Greater), @@ -432,7 +436,7 @@ where /// assert_eq!(iter.next(), None); /// ``` pub fn iter(&self) -> impl DoubleEndedIterator { - self.nodit_map.iter().flat_map(|(interval, value_store)| { + self.inner.iter().flat_map(|(interval, value_store)| { value_store.iter().map(move |value| (interval, value)) }) } @@ -507,7 +511,9 @@ where impl Default for ZosditMap { fn default() -> Self { ZosditMap { - nodit_map: NoditMap::default(), + len: 0, + inner: BTreeMap::new(), + phantom: PhantomData, } } } @@ -522,11 +528,9 @@ where type IntoIter = Box>; fn into_iter(self) -> Self::IntoIter { - Box::new(self.nodit_map.into_iter().flat_map( - |(interval, value_store)| { - value_store.into_iter().map(move |value| (interval, value)) - }, - )) + Box::new(self.inner.into_iter().flat_map(|(interval, value_store)| { + value_store.into_iter().map(move |value| (interval, value)) + })) } } @@ -600,6 +604,8 @@ where #[cfg(test)] mod tests { + use pretty_assertions::assert_eq; + use super::*; use crate::interval::ii; @@ -644,4 +650,45 @@ mod tests { } } } + + #[test] + fn insert_strict_back_tests() { + let mut map = ZosditMap::new(); + assert_eq!(map.len(), 0); + + map.insert_strict_back(ii(0_u8, 0), -8_i8).unwrap(); + assert_eq!(map.len(), 1); + + map.insert_strict_back(ii(0_u8, u8::MAX), -4_i8).unwrap(); + assert_eq!(map.len(), 2); + + let _ = map.insert_strict_back(ii(9_u8, 10), -4_i8); + assert_eq!(map.len(), 2); + } + + #[test] + fn cut_tests() { + let mut map = ZosditMap::new(); + + map.insert_strict_back(ii(0_u8, 0), -8_i8).unwrap(); + map.insert_strict_back(ii(0_u8, u8::MAX), -4_i8).unwrap(); + + assert_eq!( + map.iter().collect::>(), + vec![(&ii(0, 0), &-8), (&ii(0, u8::MAX), &-4)] + ); + + let cut = map.cut(ii(0, u8::MAX)); + + assert_eq!( + map.iter().collect::>(), + vec![], + "invalid map after cut" + ); + assert_eq!( + cut.collect::>(), + vec![(ii(0, 0), -8), (ii(0, u8::MAX), -4)], + "invalid cut" + ); + } }