set version made and big progress on test generator
This commit is contained in:
parent
73559b0e86
commit
0aec96e84d
@ -7,3 +7,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
either = "1.8.0"
|
||||
pretty_trace = "0.5.23"
|
||||
color-backtrace = "0.5.1"
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::Bound;
|
||||
|
||||
pub enum StartBound<T> {
|
||||
Included(T),
|
||||
@ -36,12 +37,8 @@ where
|
||||
{
|
||||
pub fn cloned(&self) -> StartBound<T> {
|
||||
match self {
|
||||
StartBound::Included(point) => {
|
||||
StartBound::Included((*point).clone())
|
||||
}
|
||||
StartBound::Excluded(point) => {
|
||||
StartBound::Excluded((*point).clone())
|
||||
}
|
||||
StartBound::Included(point) => StartBound::Included((*point).clone()),
|
||||
StartBound::Excluded(point) => StartBound::Excluded((*point).clone()),
|
||||
StartBound::Unbounded => StartBound::Unbounded,
|
||||
}
|
||||
}
|
||||
@ -95,6 +92,24 @@ impl<T> From<EndBound<T>> for StartBound<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> From<Bound<T>> for StartBound<T> {
|
||||
fn from(bound: Bound<T>) -> Self {
|
||||
match bound {
|
||||
Bound::Included(point) => StartBound::Included(point),
|
||||
Bound::Excluded(point) => StartBound::Excluded(point),
|
||||
Bound::Unbounded => StartBound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> From<StartBound<T>> for Bound<T> {
|
||||
fn from(start_bound: StartBound<T>) -> Bound<T> {
|
||||
match start_bound {
|
||||
StartBound::Included(point) => Bound::Included(point),
|
||||
StartBound::Excluded(point) => Bound::Excluded(point),
|
||||
StartBound::Unbounded => Bound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum EndBound<T> {
|
||||
Included(T),
|
||||
@ -145,7 +160,7 @@ where
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.inner(), other.inner()) {
|
||||
(Some(start1), Some(start2)) => start1 == start2,
|
||||
(Some(end1), Some(end2)) => end1 == end2,
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
}
|
||||
@ -161,9 +176,9 @@ where
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
match (self.inner(), other.inner()) {
|
||||
//todo fix meh
|
||||
(Some(start1), Some(start2)) => start1.partial_cmp(start2),
|
||||
(None, Some(_)) => Some(Ordering::Less),
|
||||
(Some(_), None) => Some(Ordering::Greater),
|
||||
(Some(end1), Some(end2)) => end1.partial_cmp(end2),
|
||||
(None, Some(_)) => Some(Ordering::Greater),
|
||||
(Some(_), None) => Some(Ordering::Less),
|
||||
(None, None) => Some(Ordering::Equal),
|
||||
}
|
||||
}
|
||||
@ -179,11 +194,29 @@ where
|
||||
}
|
||||
|
||||
impl<T> From<StartBound<T>> for EndBound<T> {
|
||||
fn from(end_bound: StartBound<T>) -> Self {
|
||||
match end_bound {
|
||||
fn from(start_bound: StartBound<T>) -> Self {
|
||||
match start_bound {
|
||||
StartBound::Included(point) => EndBound::Included(point),
|
||||
StartBound::Excluded(point) => EndBound::Excluded(point),
|
||||
StartBound::Unbounded => EndBound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> From<Bound<T>> for EndBound<T> {
|
||||
fn from(bound: Bound<T>) -> Self {
|
||||
match bound {
|
||||
Bound::Included(point) => EndBound::Included(point),
|
||||
Bound::Excluded(point) => EndBound::Excluded(point),
|
||||
Bound::Unbounded => EndBound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> From<EndBound<T>> for Bound<T> {
|
||||
fn from(end_bound: EndBound<T>) -> Bound<T> {
|
||||
match end_bound {
|
||||
EndBound::Included(point) => Bound::Included(point),
|
||||
EndBound::Excluded(point) => Bound::Excluded(point),
|
||||
EndBound::Unbounded => Bound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
#![feature(is_some_and)]
|
||||
pub mod bounds;
|
||||
pub mod range_bounds;
|
||||
pub mod range_bounds_map;
|
||||
pub mod btree_ext;
|
||||
pub mod overlapping_tests;
|
||||
pub mod range_bounds;
|
||||
pub mod range_bounds_map;
|
||||
pub mod range_bounds_set;
|
||||
|
||||
pub use std::ops::RangeBounds as StdRangeBounds;
|
||||
pub use std::ops::Bound as StdBound;
|
||||
pub use crate::range_bounds_map::RangeBoundsMap;
|
||||
pub use crate::range_bounds_set::RangeBoundsSet;
|
||||
|
@ -1,28 +1,75 @@
|
||||
use std::ops::{Bound, Range};
|
||||
#![feature(let_chains)]
|
||||
|
||||
use range_bounds_set::{range_bounds_set::RangeBoundsSet, range_bounds_ext::RangeBoundsExt};
|
||||
use std::fmt::Display;
|
||||
use std::ops::Bound;
|
||||
|
||||
use range_bounds_set::range_bounds::RangeBounds;
|
||||
use range_bounds_set::RangeBoundsSet;
|
||||
|
||||
static NICE_NUMBERS: &'static [u8] = &[2, 4, 6, 8, 10];
|
||||
type Sim = (Bound<u8>, Bound<u8>);
|
||||
type TestBounds = (Bound<u8>, Bound<u8>);
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
//pretty_trace::PrettyTrace::new().on();
|
||||
color_backtrace::install();
|
||||
for test_case in generate_overlap_test_cases() {
|
||||
println!("{}", test_case);
|
||||
}
|
||||
}
|
||||
|
||||
struct OverlapTestCase {
|
||||
range_bounds_set: RangeBoundsSet<Sim, u8>,
|
||||
overlap_range: Sim,
|
||||
range_bounds_set: RangeBoundsSet<u8, TestBounds>,
|
||||
overlap_range: TestBounds,
|
||||
}
|
||||
|
||||
impl Display for OverlapTestCase {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let range_bounds_iterator = self.range_bounds_set.iter();
|
||||
|
||||
writeln!(f, "=== 1 2 3 4 5 6 7 8 9 10 ===")?;
|
||||
|
||||
for range_bounds in range_bounds_iterator {
|
||||
writeln!(f, "{}", display_test_bounds(range_bounds))?;
|
||||
}
|
||||
|
||||
writeln!(f)?;
|
||||
|
||||
writeln!(f, "Overlapping:")?;
|
||||
writeln!(f, "{}", display_test_bounds(&self.overlap_range))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn display_test_bounds(test_bounds: &TestBounds) -> String {
|
||||
let first_symbol_position = inner(&test_bounds.0).unwrap_or(&0);
|
||||
let second_symbol_position = inner(&test_bounds.1).unwrap_or(&16);
|
||||
format!(
|
||||
"{}{}{}{}",
|
||||
" ".repeat(*first_symbol_position as usize),
|
||||
bound_symbol(&test_bounds.0),
|
||||
"-".repeat(*second_symbol_position as usize),
|
||||
bound_symbol(&test_bounds.1)
|
||||
)
|
||||
}
|
||||
|
||||
fn bound_symbol(bound: &Bound<u8>) -> String {
|
||||
match bound {
|
||||
Bound::Included(_) => "⬤".to_string(),
|
||||
Bound::Excluded(_) => "○".to_string(),
|
||||
Bound::Unbounded => "∞".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
struct OverlapTestCaseWithAnswer {
|
||||
test_case: OverlapTestCase,
|
||||
answer: Vec<Sim>,
|
||||
answer: Vec<TestBounds>,
|
||||
}
|
||||
|
||||
fn generate_overlap_test_cases() -> Vec<OverlapTestCase> {
|
||||
let mut output = Vec::new();
|
||||
//case zero
|
||||
for overlap_range in all_sim() {
|
||||
for overlap_range in all_valid_test_bounds() {
|
||||
output.push(OverlapTestCase {
|
||||
range_bounds_set: RangeBoundsSet::new(),
|
||||
overlap_range,
|
||||
@ -30,10 +77,10 @@ fn generate_overlap_test_cases() -> Vec<OverlapTestCase> {
|
||||
}
|
||||
|
||||
//case one
|
||||
for overlap_range in all_sim() {
|
||||
for inside_range in all_sim() {
|
||||
let mut range_bounds_set = RangeBoundsSet::new();
|
||||
range_bounds_set.raw_insert(inside_range);
|
||||
for overlap_range in all_valid_test_bounds() {
|
||||
for inside_range in all_valid_test_bounds() {
|
||||
let mut range_bounds_set = range_bounds_set::RangeBoundsSet::new();
|
||||
range_bounds_set.insert(inside_range).unwrap();
|
||||
output.push(OverlapTestCase {
|
||||
range_bounds_set,
|
||||
overlap_range,
|
||||
@ -42,34 +89,43 @@ fn generate_overlap_test_cases() -> Vec<OverlapTestCase> {
|
||||
}
|
||||
|
||||
//case two
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
fn all_valid_sim_pairs() -> Vec<(Sim, Sim)> {
|
||||
let mut output = Vec::new();
|
||||
for sim1 in all_sim() {
|
||||
for sim2 in all_sim() {
|
||||
output.push((sim1, sim2));
|
||||
for overlap_range in all_valid_test_bounds() {
|
||||
for (test_bounds1, test_bounds2) in all_valid_test_bounds_pairs() {
|
||||
let mut range_bounds_set = range_bounds_set::RangeBoundsSet::new();
|
||||
range_bounds_set.insert(test_bounds1).unwrap();
|
||||
dbg!(test_bounds2);
|
||||
range_bounds_set.insert(test_bounds2).unwrap();
|
||||
output.push(OverlapTestCase {
|
||||
range_bounds_set,
|
||||
overlap_range,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
output.retain(is_valid_sim_pair);
|
||||
return output;
|
||||
}
|
||||
|
||||
fn all_valid_test_bounds_pairs() -> Vec<(TestBounds, TestBounds)> {
|
||||
let mut output = Vec::new();
|
||||
for test_bounds1 in all_valid_test_bounds() {
|
||||
for test_bounds2 in all_valid_test_bounds() {
|
||||
output.push((test_bounds1, test_bounds2));
|
||||
}
|
||||
}
|
||||
|
||||
output.retain(is_valid_test_bounds_pair);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
fn is_valid_sim_pair((sim1, sim2): &(Sim, Sim)) -> bool {
|
||||
//do they overlap?
|
||||
if sim1.overlaps(sim2) {
|
||||
return false;
|
||||
}
|
||||
if
|
||||
|
||||
//is it an exclusive-exclusive with start==end?
|
||||
fn is_valid_test_bounds_pair(
|
||||
(test_bounds1, test_bounds2): &(TestBounds, TestBounds),
|
||||
) -> bool {
|
||||
//do they overlap?
|
||||
!test_bounds1.overlaps(test_bounds2)
|
||||
}
|
||||
|
||||
fn all_sim() -> Vec<Sim> {
|
||||
fn all_valid_test_bounds() -> Vec<TestBounds> {
|
||||
let mut output = Vec::new();
|
||||
|
||||
//bounded-bounded
|
||||
@ -88,9 +144,33 @@ fn all_sim() -> Vec<Sim> {
|
||||
}
|
||||
//bounded-bounded
|
||||
output.push((Bound::Unbounded, Bound::Unbounded));
|
||||
|
||||
output.retain(is_valid_test_bounds);
|
||||
return output;
|
||||
}
|
||||
|
||||
fn is_valid_test_bounds(test_bounds: &TestBounds) -> bool {
|
||||
//the one exception for zero ranges
|
||||
if let Bound::Included(start) = test_bounds.0 && let Bound::Included(end) = test_bounds.1 && start==end {
|
||||
return true;
|
||||
}
|
||||
match inner(&test_bounds.0) {
|
||||
Some(start) => match inner(&test_bounds.1) {
|
||||
Some(end) => start < end,
|
||||
None => true,
|
||||
},
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn inner(bound: &Bound<u8>) -> Option<&u8> {
|
||||
match bound {
|
||||
Bound::Included(point) => Some(point),
|
||||
Bound::Excluded(point) => Some(point),
|
||||
Bound::Unbounded => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn all_finite_bounded() -> Vec<Bound<u8>> {
|
||||
let mut output = Vec::new();
|
||||
for i in 0..5 {
|
||||
|
@ -6,10 +6,11 @@ where
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&T>;
|
||||
fn end_bound(&self) -> EndBound<&T>;
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self;
|
||||
|
||||
fn get_pair(&self) -> (StartBound<&T>, EndBound<&T>) {
|
||||
(self.start_bound(), self.end_bound())
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self;
|
||||
fn contains(&self, item: &T) -> bool {
|
||||
(match self.start_bound() {
|
||||
StartBound::Included(start) => start <= item,
|
||||
@ -58,3 +59,165 @@ where
|
||||
|| same_exclusive
|
||||
}
|
||||
}
|
||||
|
||||
use std::ops::{
|
||||
Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo,
|
||||
RangeToInclusive,
|
||||
};
|
||||
|
||||
impl<T> RangeBounds<T> for (Bound<T>, Bound<T>)
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
//todo use Froms and AsRef stuff and functions to do this instead of bare
|
||||
//matching
|
||||
fn start_bound(&self) -> StartBound<&T> {
|
||||
match self.0 {
|
||||
Bound::Included(ref point) => StartBound::Included(point),
|
||||
Bound::Excluded(ref point) => StartBound::Excluded(point),
|
||||
Bound::Unbounded => StartBound::Unbounded,
|
||||
}
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&T> {
|
||||
match self.1 {
|
||||
Bound::Included(ref point) => EndBound::Included(point),
|
||||
Bound::Excluded(ref point) => EndBound::Excluded(point),
|
||||
Bound::Unbounded => EndBound::Unbounded,
|
||||
}
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self {
|
||||
(Bound::from(start_bound), Bound::from(end_bound))
|
||||
}
|
||||
}
|
||||
impl<T> RangeBounds<T> for Range<T>
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&T> {
|
||||
StartBound::Included(&self.start)
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&T> {
|
||||
EndBound::Excluded(&self.end)
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self {
|
||||
if let StartBound::Included(start) = start_bound {
|
||||
if let EndBound::Excluded(end) = end_bound {
|
||||
return Range { start, end };
|
||||
} else {
|
||||
panic!("The end of a Range must be Excluded(_)")
|
||||
}
|
||||
} else {
|
||||
panic!("The start of a Range must be Included(_)")
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> RangeBounds<T> for RangeFrom<T>
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&T> {
|
||||
StartBound::Included(&self.start)
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&T> {
|
||||
EndBound::Unbounded
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self {
|
||||
if let StartBound::Included(start) = start_bound {
|
||||
if let EndBound::Unbounded = end_bound {
|
||||
return RangeFrom { start };
|
||||
} else {
|
||||
panic!("The end of a RangeFrom must be Unbounded")
|
||||
}
|
||||
} else {
|
||||
panic!("The start of a RangeFrom must be Included(_)")
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> RangeBounds<T> for RangeFull
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&T> {
|
||||
StartBound::Unbounded
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&T> {
|
||||
EndBound::Unbounded
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self {
|
||||
if let StartBound::Unbounded = start_bound {
|
||||
if let EndBound::Unbounded = end_bound {
|
||||
return RangeFull {};
|
||||
} else {
|
||||
panic!("The end of a RangeFull must be Unbounded")
|
||||
}
|
||||
} else {
|
||||
panic!("The start of a RangeFull must be Unbounded")
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> RangeBounds<T> for RangeInclusive<T>
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&T> {
|
||||
StartBound::Included(self.start())
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&T> {
|
||||
EndBound::Included(self.end())
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self {
|
||||
if let StartBound::Included(start) = start_bound {
|
||||
if let EndBound::Included(end) = end_bound {
|
||||
return RangeInclusive::new(start, end);
|
||||
} else {
|
||||
panic!("The end of a RangeInclusive must be Included(_)")
|
||||
}
|
||||
} else {
|
||||
panic!("The start of a RangeInclusive must be Included(_)")
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> RangeBounds<T> for RangeTo<T>
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&T> {
|
||||
StartBound::Unbounded
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&T> {
|
||||
EndBound::Excluded(&self.end)
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self {
|
||||
if let StartBound::Unbounded = start_bound {
|
||||
if let EndBound::Excluded(end) = end_bound {
|
||||
return RangeTo { end };
|
||||
} else {
|
||||
panic!("The end of a RangeTo must be Excluded(_)")
|
||||
}
|
||||
} else {
|
||||
panic!("The start of a RangeTo must be Unbounded")
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> RangeBounds<T> for RangeToInclusive<T>
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn start_bound(&self) -> StartBound<&T> {
|
||||
StartBound::Unbounded
|
||||
}
|
||||
fn end_bound(&self) -> EndBound<&T> {
|
||||
EndBound::Included(&self.end)
|
||||
}
|
||||
fn dummy(start_bound: StartBound<T>, end_bound: EndBound<T>) -> Self {
|
||||
if let StartBound::Unbounded = start_bound {
|
||||
if let EndBound::Included(end) = end_bound {
|
||||
return RangeToInclusive { end };
|
||||
} else {
|
||||
panic!("The end of a RangeToInclusive must be Included(_)")
|
||||
}
|
||||
} else {
|
||||
panic!("The start of a RangeToInclusive must be Unbounded")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,13 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::iter::once;
|
||||
use std::ops::Bound;
|
||||
|
||||
use either::Either;
|
||||
|
||||
use crate::bounds::{EndBound, StartBound};
|
||||
use crate::btree_ext::BTreeMapExt;
|
||||
use crate::range_bounds::RangeBounds;
|
||||
use crate::StdBound;
|
||||
|
||||
//todo switch to slot map thingy
|
||||
#[derive(Default)]
|
||||
pub struct RangeBoundsMap<I, K, V> {
|
||||
starts: BTreeMap<StartBound<I>, (K, V)>,
|
||||
}
|
||||
@ -32,12 +30,18 @@ where
|
||||
return Err(());
|
||||
}
|
||||
|
||||
//todo panic on invalid inputs
|
||||
|
||||
self.starts
|
||||
.insert(range_bounds.start_bound().cloned(), (range_bounds, value));
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn contains_point(&self, point: &I) -> bool {
|
||||
self.get(point).is_some()
|
||||
}
|
||||
|
||||
pub fn overlaps(&self, search_range_bounds: &K) -> bool {
|
||||
self.overlapping(search_range_bounds).next().is_some()
|
||||
}
|
||||
@ -45,12 +49,11 @@ where
|
||||
pub fn overlapping(
|
||||
&self,
|
||||
search_range_bounds: &K,
|
||||
) -> Either<impl Iterator<Item = (&K, &V)>, impl Iterator<Item = (&K, &V)>>
|
||||
{
|
||||
) -> impl Iterator<Item = (&K, &V)> {
|
||||
let start_range_bounds = (
|
||||
//Included is lossless regarding meta-bounds searches
|
||||
StdBound::Included(search_range_bounds.start_bound().cloned()),
|
||||
StdBound::Included(StartBound::from(
|
||||
Bound::Included(search_range_bounds.start_bound().cloned()),
|
||||
Bound::Included(StartBound::from(
|
||||
search_range_bounds.end_bound().cloned(),
|
||||
)),
|
||||
);
|
||||
@ -62,7 +65,7 @@ where
|
||||
//Excluded is lossless regarding meta-bounds searches
|
||||
//because we don't want equal bound as they would have be
|
||||
//coverded in the previous step
|
||||
self.starts.next_below_upper_bound(StdBound::Excluded(
|
||||
self.starts.next_below_upper_bound(Bound::Excluded(
|
||||
//optimisation fix this without cloning
|
||||
&search_range_bounds.start_bound().cloned(),
|
||||
)) {
|
||||
@ -107,10 +110,6 @@ where
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn contains_point(&self, point: &I) -> bool {
|
||||
self.get(point).is_some()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
|
||||
self.starts.iter().map(|(_, (key, value))| (key, value))
|
||||
}
|
||||
|
49
range_bounds_set/src/range_bounds_set.rs
Normal file
49
range_bounds_set/src/range_bounds_set.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use crate::range_bounds::RangeBounds;
|
||||
use crate::range_bounds_map::RangeBoundsMap;
|
||||
|
||||
pub struct RangeBoundsSet<I, K> {
|
||||
map: RangeBoundsMap<I, K, ()>,
|
||||
}
|
||||
|
||||
impl<I, K> RangeBoundsSet<I, K>
|
||||
where
|
||||
K: RangeBounds<I>,
|
||||
I: Ord + Clone,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
RangeBoundsSet {
|
||||
map: RangeBoundsMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
//returns Err(()) if the given range overlaps another range
|
||||
//does not coalesce ranges if they touch
|
||||
pub fn insert(&mut self, range_bounds: K) -> Result<(), ()> {
|
||||
self.map.insert(range_bounds, ())
|
||||
}
|
||||
|
||||
pub fn overlaps(&self, search_range_bounds: &K) -> bool {
|
||||
self.map.overlaps(search_range_bounds)
|
||||
}
|
||||
|
||||
pub fn overlapping(
|
||||
&self,
|
||||
search_range_bounds: &K,
|
||||
) -> impl Iterator<Item = &K> {
|
||||
self.map
|
||||
.overlapping(search_range_bounds)
|
||||
.map(|(key, _)| key)
|
||||
}
|
||||
|
||||
pub fn get(&self, point: &I) -> Option<&K> {
|
||||
self.map.get_key_value(point).map(|(key, _)| key)
|
||||
}
|
||||
|
||||
pub fn contains_point(&self, point: &I) -> bool {
|
||||
self.map.contains_point(point)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &K> {
|
||||
self.map.iter().map(|(key, _)| key)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user