From 11c81d7c203dc014491c77bd1ec4f0d335495b16 Mon Sep 17 00:00:00 2001 From: Robert Durfee Date: Wed, 12 Aug 2020 19:33:29 -0500 Subject: [PATCH] better traits for convenience constructors --- Cargo.toml | 7 ++-- src/bounded.rs | 79 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 +++ src/next.rs | 51 ++++++++++++++++++++++++++ src/segment.rs | 76 +++++++++++++++++++++------------------ src/segment_map.rs | 22 +++++++++--- src/segment_map_node.rs | 47 +++++++++++++----------- 7 files changed, 224 insertions(+), 62 deletions(-) create mode 100644 src/bounded.rs create mode 100644 src/next.rs diff --git a/Cargo.toml b/Cargo.toml index 9e7fa79..753aaaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,13 @@ [package] name = "segment-map" -version = "0.1.0" +version = "0.1.1" authors = ["Robert Durfee "] description = "A self-balancing binary search tree for mapping discrete, disjoint segments to values." -license-file = "LICENSE" -repository = "https://github.com/RobertDurfee/SegmentMap" +license = "MIT" +repository = "https://github.com/RobertDurfee/SegmentMap/tree/v0.1.1" readme = "README.md" keywords = ["segment-map", "interval-map", "segment", "interval", "map"] categories = ["data-structures"] edition = "2018" [dependencies] -num = "0.3" diff --git a/src/bounded.rs b/src/bounded.rs new file mode 100644 index 0000000..5613de0 --- /dev/null +++ b/src/bounded.rs @@ -0,0 +1,79 @@ +use std::{ + usize, + u8, + u16, + u32, + u64, + u128, + isize, + i8, + i16, + i32, + i64, + i128 +}; + +pub trait Bounded { + fn min() -> Self; + fn max() -> Self; +} + +impl Bounded for usize { + fn min() -> usize { usize::MIN } + fn max() -> usize { usize::MAX } +} + +impl Bounded for u8 { + fn min() -> u8 { u8::MIN } + fn max() -> u8 { u8::MAX } +} + +impl Bounded for u16 { + fn min() -> u16 { u16::MIN } + fn max() -> u16 { u16::MAX } +} + +impl Bounded for u32 { + fn min() -> u32 { u32::MIN } + fn max() -> u32 { u32::MAX } +} + +impl Bounded for u64 { + fn min() -> u64 { u64::MIN } + fn max() -> u64 { u64::MAX } +} + +impl Bounded for u128 { + fn min() -> u128 { u128::MIN } + fn max() -> u128 { u128::MAX } +} + +impl Bounded for isize { + fn min() -> isize { isize::MIN } + fn max() -> isize { isize::MAX } +} + +impl Bounded for i8 { + fn min() -> i8 { i8::MIN } + fn max() -> i8 { i8::MAX } +} + +impl Bounded for i16 { + fn min() -> i16 { i16::MIN } + fn max() -> i16 { i16::MAX } +} + +impl Bounded for i32 { + fn min() -> i32 { i32::MIN } + fn max() -> i32 { i32::MAX } +} + +impl Bounded for i64 { + fn min() -> i64 { i64::MIN } + fn max() -> i64 { i64::MAX } +} + +impl Bounded for i128 { + fn min() -> i128 { i128::MIN } + fn max() -> i128 { i128::MAX } +} diff --git a/src/lib.rs b/src/lib.rs index d99165d..20f8077 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,10 @@ mod segment; mod segment_map_node; mod segment_map; +mod bounded; +mod next; pub use crate::segment_map::SegmentMap; pub use crate::segment::Segment; +pub use crate::bounded::Bounded; +pub use crate::next::Next; diff --git a/src/next.rs b/src/next.rs new file mode 100644 index 0000000..d0459d4 --- /dev/null +++ b/src/next.rs @@ -0,0 +1,51 @@ +pub trait Next: Clone + PartialOrd { + fn next(&self) -> Self; +} + +impl Next for usize { + fn next(&self) -> usize { self.checked_add(1).expect("integer overflow") } +} + +impl Next for u8 { + fn next(&self) -> u8 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for u16 { + fn next(&self) -> u16 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for u32 { + fn next(&self) -> u32 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for u64 { + fn next(&self) -> u64 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for u128 { + fn next(&self) -> u128 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for isize { + fn next(&self) -> isize { self.checked_add(1).expect("integer overflow") } +} + +impl Next for i8 { + fn next(&self) -> i8 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for i16 { + fn next(&self) -> i16 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for i32 { + fn next(&self) -> i32 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for i64 { + fn next(&self) -> i64 { self.checked_add(1).expect("integer overflow") } +} + +impl Next for i128 { + fn next(&self) -> i128 { self.checked_add(1).expect("integer overflow") } +} diff --git a/src/segment.rs b/src/segment.rs index d84b0fe..7df5cd4 100644 --- a/src/segment.rs +++ b/src/segment.rs @@ -1,8 +1,6 @@ -use std::ops::Add; -use num::{ +use crate::{ Bounded, - Zero, - One, + Next, }; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -11,11 +9,18 @@ pub struct Segment { upper: K, } -impl Segment { +impl Segment +where + K: PartialOrd +{ pub fn new(lower: K, upper: K) -> Segment { Segment { lower, upper } } + pub fn closed_open(lower: K, upper: K) -> Segment { + Segment { lower, upper } + } + pub fn contains(&self, value: &K) -> bool { (&self.lower <= value) && (value < &self.upper) } @@ -41,7 +46,10 @@ impl Segment { } } -impl Segment { +impl Segment +where + K: Clone + PartialOrd +{ pub fn intersection(&self, other: &Segment) -> Option> { if self.is_connected(other) { Some(Segment { @@ -59,63 +67,63 @@ impl Segment { } } -impl Segment { +impl Segment +where + K: PartialOrd + Default +{ pub fn empty() -> Segment { - Segment { lower: K::zero(), upper: K::zero() } + Segment { lower: K::default(), upper: K::default() } } } -impl + Clone + One + PartialOrd> Segment { +impl Segment +where + K: PartialOrd + Next +{ pub fn singleton(value: K) -> Segment { - Segment { lower: value.clone(), upper: value + K::one() } + Segment { lower: value.clone(), upper: value.next() } } -} -impl + One + PartialOrd> Segment { pub fn open(lower: K, upper: K) -> Segment { - Segment { lower: lower + K::one(), upper } + Segment { lower: lower.next(), upper } } pub fn closed(lower: K, upper: K) -> Segment { - Segment { lower, upper: upper + K::one() } + Segment { lower, upper: upper.next() } } pub fn open_closed(lower: K, upper: K) -> Segment { - Segment { lower: lower + K::one(), upper: upper + K::one() } + Segment { lower: lower.next(), upper: upper.next() } } } -impl Segment { - pub fn closed_open(lower: K, upper: K) -> Segment { - Segment { lower, upper } +impl Segment +where + K: Bounded + PartialOrd + Next +{ + pub fn at_most(value: K) -> Segment { + Segment { lower: K::min(), upper: value.next() } } -} -impl + Bounded + One + PartialOrd> Segment { - pub fn at_most(value: K) -> Segment { - Segment { lower: K::min_value(), upper: value + K::one() } + pub fn greater_than(value: K) -> Segment { + Segment { lower: value.next(), upper: K::max() } } } -impl Segment { +impl Segment +where + K: Bounded + PartialOrd +{ pub fn at_least(value: K) -> Segment { - Segment { lower: value, upper: K::max_value() } + Segment { lower: value, upper: K::max() } } pub fn less_than(value: K) -> Segment { - Segment { lower: K::min_value(), upper: value } - } -} - -impl + Bounded + One + PartialOrd> Segment { - pub fn greater_than(value: K) -> Segment { - Segment { lower: value + K::one(), upper: K::max_value() } + Segment { lower: K::min(), upper: value } } -} -impl Segment { pub fn all() -> Segment { - Segment { lower: K::min_value(), upper: K::max_value() } + Segment { lower: K::min(), upper: K::max() } } } diff --git a/src/segment_map.rs b/src/segment_map.rs index ed8bd6e..c79d6a4 100644 --- a/src/segment_map.rs +++ b/src/segment_map.rs @@ -8,7 +8,10 @@ pub struct SegmentMap { root: Option>, } -impl SegmentMap { +impl SegmentMap +where + K: PartialOrd +{ pub fn new() -> SegmentMap { SegmentMap { root: None } } @@ -72,7 +75,11 @@ impl SegmentMap { } } -impl SegmentMap { +impl SegmentMap +where + K: Clone + PartialOrd, + V: Clone, +{ pub fn remove(&mut self, segment: &Segment) { if let Some(root) = self.root.take() { self.root = root.remove(segment); @@ -178,8 +185,15 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { } } -impl Extend<(Segment, V)> for SegmentMap { - fn extend, V)>>(&mut self, iter: I) { +impl Extend<(Segment, V)> for SegmentMap +where + K: Clone + PartialOrd, + V: Clone, +{ + fn extend(&mut self, iter: I) + where + I: IntoIterator, V)> + { for (segment, value) in iter { self.insert(segment, value); } diff --git a/src/segment_map_node.rs b/src/segment_map_node.rs index 9cb7cb1..2cf2e44 100644 --- a/src/segment_map_node.rs +++ b/src/segment_map_node.rs @@ -1,15 +1,18 @@ use crate::Segment; #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub(crate) struct SegmentMapNode { - pub(crate) segment: Segment, - pub(crate) value: V, - pub(crate) left: Box>>, - pub(crate) right: Box>> +pub struct SegmentMapNode { + pub segment: Segment, + pub value: V, + pub left: Box>>, + pub right: Box>> } -impl SegmentMapNode { - pub(crate) fn new(segment: Segment, value: V, left: Option>, right: Option>) -> SegmentMapNode { +impl SegmentMapNode +where + K: PartialOrd +{ + pub fn new(segment: Segment, value: V, left: Option>, right: Option>) -> SegmentMapNode { SegmentMapNode { segment, value, @@ -18,11 +21,11 @@ impl SegmentMapNode { } } - pub(crate) fn min_key(&self) -> &K { + pub fn min_key(&self) -> &K { self.min_node().segment.lower() } - pub(crate) fn min_node(&self) -> &SegmentMapNode { + pub fn min_node(&self) -> &SegmentMapNode { // if left exists, recurse if let Some(left) = self.left.as_ref() { left.min_node() @@ -30,7 +33,7 @@ impl SegmentMapNode { } else { self } } - pub(crate) fn remove_min_node(mut self) -> (Option>, SegmentMapNode) { + pub fn remove_min_node(mut self) -> (Option>, SegmentMapNode) { // if left exists, recurse if let Some(left) = self.left.take() { let (left, min_node) = left.remove_min_node(); @@ -40,11 +43,11 @@ impl SegmentMapNode { } else { (None, self) } } - pub(crate) fn max_key(&self) -> &K { + pub fn max_key(&self) -> &K { self.max_node().segment.upper() } - pub(crate) fn max_node(&self) -> &SegmentMapNode { + pub fn max_node(&self) -> &SegmentMapNode { // if right exists, recurse if let Some(right) = self.right.as_ref() { right.max_node() @@ -52,15 +55,15 @@ impl SegmentMapNode { } else { self } } - pub(crate) fn span(&self) -> Segment<&K> { + pub fn span(&self) -> Segment<&K> { Segment::new(self.min_key(), self.max_key()) } - pub(crate) fn get(&self, key: &K) -> Option<&V> { + pub fn get(&self, key: &K) -> Option<&V> { self.get_entry(key).map(|(_, v)| v) } - pub(crate) fn get_entry(&self, key: &K) -> Option<(&Segment, &V)> { + pub fn get_entry(&self, key: &K) -> Option<(&Segment, &V)> { // if self segment contains key if self.segment.contains(key) { Some((&self.segment, &self.value)) @@ -81,7 +84,7 @@ impl SegmentMapNode { } } - pub(crate) fn insert(&mut self, segment: Segment, value: V) { + pub fn insert(&mut self, segment: Segment, value: V) { // if the segments perfectly overlap (this prevents inserting duplicate empty segments) if (segment.lower() == self.segment.lower()) && (segment.upper() == self.segment.upper()) { panic!("segments must not overlap"); @@ -110,8 +113,12 @@ impl SegmentMapNode { } } -impl SegmentMapNode { - pub(crate) fn remove(mut self, segment: &Segment) -> Option> { +impl SegmentMapNode +where + K: Clone + PartialOrd, + V: Clone, +{ + pub fn remove(mut self, segment: &Segment) -> Option> { // empty segments can be removed if segment.is_empty() { // if empty segment is enclosed by self segment, (potentially) split the segment @@ -296,14 +303,14 @@ impl SegmentMapNode { } } - pub(crate) fn update(self, segment: &Segment, value: F) -> Option> + pub fn update(self, segment: &Segment, value: F) -> Option> where F: Fn(Option) -> Option + Clone { self.update_entry(segment, |_, v| value(v)) } - pub(crate) fn update_entry(mut self, segment: &Segment, value: F) -> Option> + pub fn update_entry(mut self, segment: &Segment, value: F) -> Option> where F: Fn(&Segment, Option) -> Option + Clone {