extern crate num_traits;
#[cfg(feature = "derive_serdes")]
extern crate serde;
extern crate smallvec;
pub mod range_compare;
pub use range_compare::{
RangeCompare, RangeDisjoint, RangeIntersect, range_compare, intersection
};
use std::ops::RangeInclusive;
use num_traits::PrimInt;
use smallvec::SmallVec;
#[derive(Clone, Debug, Eq)]
pub struct RangeSet <A> where
A : smallvec::Array + Eq + std::fmt::Debug,
A::Item : Clone + Eq + std::fmt::Debug
{
ranges : SmallVec <A>
}
pub struct Iter <'a, A, T> where
A : 'a + smallvec::Array <Item=RangeInclusive <T>> + Eq + std::fmt::Debug,
T : 'a + PrimInt + std::fmt::Debug
{
range_set : &'a RangeSet <A>,
range_index : usize,
range : RangeInclusive <T>
}
pub fn valid_range_slice <T, V> (ranges : V) -> bool where
T : PartialOrd + PrimInt,
V : AsRef <[RangeInclusive <T>]>
{
let ranges = ranges.as_ref();
if !ranges.is_empty() {
for i in 0..ranges.len()-1 { let this = &ranges[i];
let next = &ranges[i+1]; if this.is_empty() || next.is_empty() {
return false
}
if *next.start() <= this.end().saturating_add (T::one()) {
return false
}
}
}
true
}
pub fn report_sizes() {
use std::mem::size_of;
println!("RangeSet report sizes...");
println!(" size of RangeSet <[RangeInclusive <u32>; 1]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 1]>: {}",
size_of::<RangeSet <[RangeInclusive <u16>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 1]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 1]>: {}",
size_of::<RangeSet <[RangeInclusive <u64>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 1]>: {}",
size_of::<RangeSet <[RangeInclusive <usize>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 2]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 2]>: {}",
size_of::<RangeSet <[RangeInclusive <u16>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 2]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 2]>: {}",
size_of::<RangeSet <[RangeInclusive <u64>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 2]>: {}",
size_of::<RangeSet <[RangeInclusive <usize>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 4]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 4]>: {}",
size_of::<RangeSet <[RangeInclusive <u16>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 4]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 4]>: {}",
size_of::<RangeSet <[RangeInclusive <u64>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 4]>: {}",
size_of::<RangeSet <[RangeInclusive <usize>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 8]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 8]>: {}",
size_of::<RangeSet <[RangeInclusive <u16>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 8]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 8]>: {}",
size_of::<RangeSet <[RangeInclusive <u64>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 8]>: {}",
size_of::<RangeSet <[RangeInclusive <usize>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 16]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 16]>: {}",
size_of::<RangeSet <[RangeInclusive <u16>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 16]>: {}",
size_of::<RangeSet <[RangeInclusive <u32>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 16]>: {}",
size_of::<RangeSet <[RangeInclusive <u64>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 16]>: {}",
size_of::<RangeSet <[RangeInclusive <usize>; 16]>>());
println!("...RangeSet report sizes");
}
impl<A, T> Default for RangeSet <A>
where
A : smallvec::Array <Item=RangeInclusive <T>> + Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug
{
fn default() -> Self {
Self::new()
}
}
impl <A, T> RangeSet <A> where
A : smallvec::Array <Item=RangeInclusive <T>> + Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug
{
#[inline]
pub fn new() -> Self {
RangeSet {
ranges: SmallVec::new()
}
}
#[inline]
pub fn with_capacity (capacity : usize) -> Self {
RangeSet {
ranges: SmallVec::with_capacity (capacity)
}
}
pub fn from_smallvec (ranges : SmallVec <A>) -> Option <Self> {
if valid_range_slice (ranges.as_slice()) {
Some (RangeSet { ranges })
} else {
None
}
}
pub unsafe fn from_raw_parts (ranges : SmallVec <A>) -> Self {
debug_assert!(valid_range_slice (ranges.as_slice()));
RangeSet { ranges }
}
pub fn from_valid_ranges <V : AsRef <[RangeInclusive <T>]>> (ranges : V)
-> Option <Self>
{
if valid_range_slice (&ranges) {
let ranges = SmallVec::from (ranges.as_ref());
Some (RangeSet { ranges })
} else {
None
}
}
pub fn from_ranges <V : AsRef <[RangeInclusive <T>]>> (ranges : V) -> Self {
let mut ret = Self::new();
for range in ranges.as_ref() {
ret.insert_range_optimistic(range.clone());
}
ret
}
pub fn from_elements <V : AsRef <[T]>> (elements : V) -> Self {
let mut current_range : Option<(T, T)> = None;
let mut set = Self::new();
for &element in elements.as_ref() {
current_range = if let Some((start, end)) = current_range {
if element == end.saturating_add (T::one()) {
Some((start, element))
} else {
set.insert_range_optimistic(start..=end);
Some((element, element))
}
} else {
Some((element, element))
};
}
if let Some((start, end)) = current_range {
set.insert_range_optimistic(start..=end);
}
set
}
#[inline]
pub fn is_empty (&self) -> bool {
self.ranges.is_empty()
}
#[inline]
pub fn len (&self) -> usize where T : num_traits::AsPrimitive <usize> {
self.ranges.iter().map (|r| r.end().as_() - r.start().as_() + 1).sum()
}
#[inline]
pub fn clear (&mut self) {
self.ranges.clear()
}
#[inline]
pub fn into_smallvec (self) -> SmallVec <A> {
self.ranges
}
pub fn contains (&self, element : T) -> bool {
self.contains_range(element..=element)
}
pub fn contains_range (&self, range : A::Item) -> bool {
self.contains_range_ref(&range)
}
pub fn is_superset (&self, other : &Self) -> bool {
other.is_subset(self)
}
pub fn is_subset (&self, other : &Self) -> bool {
self.ranges.iter().all(|range| other.contains_range_ref (range))
}
pub fn max (&self) -> Option <T> {
self.ranges.last().map(|r| *r.end())
}
pub fn min (&self) -> Option <T> {
self.ranges.first().map(|r| *r.start())
}
pub fn insert (&mut self, element : T) -> bool {
self.insert_range (element..=element).is_none()
}
pub fn remove (&mut self, element : T) -> bool {
self.remove_range (element..=element).is_some()
}
pub fn insert_range (&mut self, range : A::Item) -> Option <Self> {
if range.is_empty () { return None
}
if self.ranges.is_empty() { self.ranges.push (range);
return None
}
let before = Self::binary_search_before_proper (self, &range);
let after = Self::binary_search_after_proper (self, &range);
match (before, after) {
(None, None) => {
let isect = self.range_intersection (&range, 0..self.ranges.len());
let new_range =
std::cmp::min (*range.start(), *self.ranges[0].start())..=
std::cmp::max (*range.end(), *self.ranges[self.ranges.len()-1].end());
self.ranges.clear();
self.ranges.push (new_range);
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
(Some (before), None) => {
if before+1 == self.ranges.len() { self.ranges.push (range);
None
} else { let isect
= self.range_intersection (&range, before+1..self.ranges.len());
self.ranges[before+1] =
std::cmp::min (*range.start(), *self.ranges[before+1].start())..=
std::cmp::max (*range.end(), *self.ranges[self.ranges.len()-1].end());
self.ranges.truncate (before+2);
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
}
(None, Some (after)) => {
if after == 0 { self.ranges.insert (0, range);
None
} else { let isect = self.range_intersection (&range, 0..after);
self.ranges[0] =
std::cmp::min (*range.start(), *self.ranges[0].start())..=
std::cmp::max (*range.end(), *self.ranges[after - 1].end());
self.ranges.as_mut_slice()[1..].rotate_left(after - 1);
let new_len = self.ranges.len() - after + 1;
self.ranges.truncate (new_len);
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
}
(Some (before), Some (after)) => {
if before+1 == after { self.ranges.insert (before+1, range);
None
} else { let isect = self.range_intersection (&range, before+1..after);
self.ranges[before+1] =
std::cmp::min (*range.start(), *self.ranges[before+1].start())..=
std::cmp::max (*range.end(), *self.ranges[after-1].end());
if 1 < after - before - 1 {
self.ranges.as_mut_slice()[(before + 2)..]
.rotate_left (after - before - 2);
let new_len = self.ranges.len() - (after - before - 2);
self.ranges.truncate (new_len);
}
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
}
}
}
fn insert_range_optimistic (&mut self, range : A::Item) {
if let Some(last) = self.ranges.last() {
if last.end().saturating_add (T::one()) < *range.start() {
self.ranges.push(range);
} else {
self.insert_range(range);
}
} else {
self.ranges.push(range);
}
}
pub fn remove_range (&mut self, range : A::Item) -> Option <Self> {
if self.ranges.is_empty() || range.is_empty() { return None
}
let before = Self::binary_search_before (self, &range);
let after = Self::binary_search_after (self, &range);
let (isect_first, isect_last) = match (before, after) {
(None, None) => (0, self.ranges.len()),
(Some (before), None) => (before+1, self.ranges.len()),
(None, Some (after)) => (0, after),
(Some (before), Some (after)) => (before+1, after)
};
let isect = self.range_intersection (&range, isect_first..isect_last);
if isect.is_empty() {
return None
}
if isect_last - isect_first == 1 {
let single_range = self.ranges[isect_first].clone();
if single_range.start() < range.start() &&
range.end() < single_range.end()
{
let left = *single_range.start()..=*range.start() - T::one();
let right = *range.end() + T::one()..=*single_range.end();
self.ranges[isect_first] = right;
self.ranges.insert (isect_first, left);
return Some (isect)
}
}
let first = self.ranges[isect_first].clone();
let last = self.ranges[isect_last-1].clone();
let (remove_first, remove_last) = if
range.start() <= first.start() && last.end() <= range.end()
{
(isect_first, isect_last)
} else if first.start() < range.start() && last.end() <= range.end() {
self.ranges[isect_first] =
*self.ranges[isect_first].start()..=*range.start() - T::one();
(isect_first+1, isect_last)
} else if range.start() <= first.start() && range.end() < last.end() {
self.ranges[isect_last-1] =
*range.end() + T::one()..=*self.ranges[isect_last-1].end();
(isect_first, isect_last-1)
} else {
debug_assert!(first.start() < range.start() && range.end() < last.end());
self.ranges[isect_first] =
*self.ranges[isect_first].start()..=*range.start() - T::one();
self.ranges[isect_last-1] =
*range.end() + T::one()..=*self.ranges[isect_last-1].end();
(isect_first+1, isect_last-1)
};
for (i, index) in (remove_last..self.ranges.len()).enumerate() {
self.ranges[remove_first+i] = self.ranges[index].clone();
}
let new_len = self.ranges.len() - (remove_last - remove_first);
self.ranges.truncate (new_len);
debug_assert!(self.is_valid());
Some (isect)
}
pub fn union (&self, other : &Self) -> Self where A : Clone {
let mut new = (*self).clone();
other.ranges.iter().cloned().for_each (|r| { new.insert_range (r); });
new
}
#[allow(mismatched_lifetime_syntaxes)]
pub fn iter (&self) -> Iter <A, T> {
Iter {
range_set: self,
range_index: 0,
range: T::one()..=T::zero()
}
}
#[inline]
pub fn spilled (&self) -> bool {
self.ranges.spilled()
}
#[inline]
pub fn shrink_to_fit (&mut self) {
self.ranges.shrink_to_fit()
}
fn binary_search_before (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if self.ranges[i].end() < range.start() {
found = true;
before = i;
if before == last {
break
}
} else {
after = i
}
}
if found {
Some (before)
} else {
None
}
}
fn binary_search_after (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if range.end() < self.ranges[i].start() {
found = true;
after = i;
} else {
before = i;
if before == last {
break
}
}
}
if found {
Some (after)
} else {
None
}
}
fn binary_search_before_proper (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if self.ranges[i].end().saturating_add (T::one()) < *range.start() {
found = true;
before = i;
if before == last {
break
}
} else {
after = i
}
}
if found {
Some (before)
} else {
None
}
}
fn binary_search_after_proper (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if range.end().saturating_add (T::one()) < *self.ranges[i].start() {
found = true;
after = i;
} else {
before = i;
if before == last {
break
}
}
}
if found {
Some (after)
} else {
None
}
}
fn contains_range_ref (&self, range : &A::Item) -> bool {
if range.is_empty() {
return true;
}
if self.ranges.is_empty() {
return false;
}
let test_range = if let Some(before) = self.binary_search_before(range) {
if let Some(next) = self.ranges.get(before + 1) {
next
} else {
return false;
}
} else {
&self.ranges[0]
};
test_range.contains(range.start()) && test_range.contains(range.end())
}
fn range_intersection (&self,
range : &A::Item, range_range : std::ops::Range <usize>
) -> Self {
let mut isect = RangeSet::new();
for i in range_range {
let r = &self.ranges[i];
let rsect = intersection (range, r);
if !rsect.is_empty() {
isect.ranges.push (rsect);
}
}
debug_assert!(isect.is_valid());
isect
}
#[inline]
fn is_valid (&self) -> bool {
valid_range_slice (&self.ranges)
}
}
impl <A, T> From <RangeInclusive <T>> for RangeSet <A> where
A : smallvec::Array <Item=RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug
{
fn from (range : RangeInclusive <T>) -> Self {
let ranges = {
let mut v = SmallVec::new();
v.push (range);
v
};
RangeSet { ranges }
}
}
impl <A, T> AsRef <SmallVec <A>> for RangeSet <A> where
A : smallvec::Array <Item=RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug
{
fn as_ref (&self) -> &SmallVec <A> {
&self.ranges
}
}
impl<A, B> PartialEq<RangeSet<B>> for RangeSet<A> where
A : smallvec::Array + Eq + std::fmt::Debug,
A::Item : Clone + Eq + std::fmt::Debug,
B : smallvec::Array<Item = A::Item> + Eq + std::fmt::Debug
{
fn eq(&self, other : &RangeSet<B>) -> bool {
self.ranges.eq(&other.ranges)
}
}
impl <'a, A, T> Iterator for Iter <'a, A, T> where
A : smallvec::Array <Item=RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug,
RangeInclusive <T> : Clone + Iterator <Item=T>
{
type Item = T;
fn next (&mut self) -> Option <Self::Item> {
if let Some (t) = self.range.next() {
Some (t)
} else if self.range_index < self.range_set.ranges.len() {
self.range = self.range_set.ranges[self.range_index].clone();
debug_assert!(!self.range.is_empty());
self.range_index += 1;
self.range.next()
} else {
None
}
}
}
#[cfg(feature = "derive_serdes")]
impl<A, T> serde::Serialize for RangeSet<A> where
A : smallvec::Array <Item=RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug + serde::Serialize,
{
fn serialize<S: serde::Serializer>(&self, serializer: S)
-> Result<S::Ok, S::Error>
{
self.ranges.serialize(serializer)
}
}
#[cfg(feature = "derive_serdes")]
impl<'de, A, T> serde::Deserialize<'de> for RangeSet<A> where
A : smallvec::Array <Item=RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug + serde::Deserialize<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D)
-> Result<Self, D::Error>
{
let ranges = SmallVec::deserialize(deserializer)?;
Ok(Self {
ranges
})
}
}
pub const DEFAULT_RANGE_COUNT: usize = 4;
#[macro_export]
macro_rules! range_set {
() => {
$crate::RangeSet::<[core::ops::RangeInclusive<_>; $crate::DEFAULT_RANGE_COUNT]>::new()
};
( ; $len:expr ) => {
$crate::RangeSet::<[core::ops::RangeInclusive<_>; $len]>::new()
};
( $( $num:tt ),+ ) => {
$crate::range_set![ $( $num ),+ ; $crate::DEFAULT_RANGE_COUNT ]
};
( $( $num:tt ),+ ; $len:expr ) => {
$crate::RangeSet::<[core::ops::RangeInclusive<_>; $len]>::from_elements([ $( $num ),+ ])
};
( $( $start:tt $( ..= $end:tt )? $( as $range_keyword:tt )? ),+ ) => {
$crate::range_set![ $( $start $(..= $end )? ),+ ; $crate::DEFAULT_RANGE_COUNT ]
};
( $( $start:tt $( ..= $end:tt )? $( as $range_keyword:tt )? ),+ ; $len:expr ) => {
$crate::RangeSet::<[core::ops::RangeInclusive<_>; $len]>::from_ranges([ $( $crate::__range_set_helper!($start $( ..= $end )? $( as $range_keyword )? ) ),+ ])
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __range_set_helper {
( $num:tt ) => { { let val = $num; val ..= val } };
( $start:tt ..= $end:tt ) => ( $start ..= $end );
( $range_expr:tt as range) => ( $range_expr );
}
#[cfg(test)]
mod tests {
use std::ops::RangeInclusive;
use crate::RangeSet;
#[test]
fn merge_multiple() {
let mut range_set: RangeSet<[RangeInclusive<u32>; 2]> = RangeSet::new();
range_set.insert_range(3..=3);
range_set.insert_range(5..=5);
range_set.insert_range(7..=7);
assert_eq!(
range_set.insert_range(1..=9),
{
let mut r = RangeSet::from(3..=3);
r.insert_range(5..=5);
r.insert_range(7..=7);
Some(r)
}
);
assert_eq!(range_set.ranges.into_vec(), vec!(1..=9));
}
#[test]
fn merge_multiple_then_gap() {
let mut range_set: RangeSet<[RangeInclusive<u32>; 2]> = RangeSet::new();
range_set.insert_range(3..=3);
range_set.insert_range(5..=5);
range_set.insert_range(9..=9);
assert_eq!(
range_set.insert_range(1..=7),
{
let mut r = RangeSet::from(3..=3);
r.insert_range(5..=5);
Some(r)
}
);
assert_eq!(range_set.ranges.into_vec(), vec!(1..=7, 9..=9));
}
#[test]
fn gap_then_merge_multiple() {
let mut range_set: RangeSet<[RangeInclusive<u32>; 2]> = RangeSet::new();
range_set.insert_range(1..=1);
range_set.insert_range(5..=5);
range_set.insert_range(7..=7);
assert_eq!(
range_set.insert_range(3..=9),
{
let mut r = RangeSet::from(5..=5);
r.insert_range(7..=7);
Some(r)
}
);
assert_eq!(range_set.ranges.into_vec(), vec!(1..=1, 3..=9));
}
#[test]
fn gap_then_merge_multiple_then_gap() {
let mut range_set: RangeSet<[RangeInclusive<u32>; 2]> = RangeSet::new();
range_set.insert_range(1..=1);
range_set.insert_range(3..=3);
range_set.insert_range(5..=5);
range_set.insert_range(7..=7);
range_set.insert_range(9..=9);
assert_eq!(
range_set.insert_range(3..=7),
{
let mut r = RangeSet::from(3..=3);
r.insert_range(5..=5);
r.insert_range(7..=7);
Some(r)
}
);
assert_eq!(range_set.ranges.into_vec(), vec!(1..=1, 3..=7, 9..=9));
}
#[test]
fn test_range_set_macro_empty() {
assert_eq!(range_set![; 3], RangeSet::<[RangeInclusive<u8>; 3]>::new());
assert_eq!(range_set![], RangeSet::<[RangeInclusive<u8>; 4]>::new());
}
#[allow(unused_parens)]
#[test]
fn test_range_set_macro_nums() {
let case1 = RangeSet::<[RangeInclusive<u8>; 3]>::from_valid_ranges (
[0..=0, 2..=5]
).unwrap();
let case2 = RangeSet::<[RangeInclusive<u8>; 4]>::from_valid_ranges (
[1..=3, 6..=6, 8..=10]
).unwrap();
const SOME_CONST: u8 = 5;
let not_token_tree = |x: u8| x;
assert_eq!(range_set![0, 2, 3, 4, 5; 3], case1);
assert_eq!(range_set![0, 2, (1 + 2), 4, SOME_CONST; 3], case1);
assert_eq!(range_set![0, 2, (not_token_tree(3)), 4, 5; 3], case1);
assert_eq!(range_set![1, 2, 3, 6, 8, 9, 10; 4], case2);
assert_eq!(range_set![1, 2, 3, (3 * 2), 8, 9, 10], case2);
let mut counter = 0;
let mut call_only_once = |x: u8| { counter += 1; x };
assert_eq!(range_set![0, 2, (call_only_once(3)), 4, 5; 3], case1);
assert_eq!(counter, 1);
}
#[allow(unused_parens)]
#[test]
fn test_range_set_macro_mixed() {
let case1 = RangeSet::<[RangeInclusive<u8>; 3]>::from_valid_ranges (
[0..=0, 2..=5]
).unwrap();
let case2 = RangeSet::<[RangeInclusive<u8>; 4]>::from_valid_ranges (
[1..=3, 6..=15, 40..=40, 42..=50]
).unwrap();
const SOME_CONST: u8 = 40;
let not_token_tree = |x: u8| x;
assert_eq!(range_set![0, 2..=5; 3], case1);
assert_eq!(range_set![0, (not_token_tree(2))..=5; 3], case1);
assert_eq!(range_set![1..=3, 6..=15, 40, 42..=50; 4], case2);
assert_eq!(range_set![1, 2, 3, 6..=15, 40, 42..=50], case2);
assert_eq!(range_set![1..=3, (3+3)..=15, SOME_CONST, 42..=50; 4], case2);
assert_eq!(range_set![1..=3, 6..=15, 40..=40, (not_token_tree(42))..=50; 4], case2);
let mut counter = 0;
let mut call_only_once = |x: u8| { counter += 1; x };
assert_eq!(range_set![1..=3, 6..=15, (call_only_once(40)), 42..=50; 4], case2);
assert_eq!(counter, 1);
assert_eq!(range_set![0, 2, 3, 5; 8],
RangeSet::<[RangeInclusive<u8>; 8]>::from_valid_ranges (
[0..=0, 2..=3, 5..=5]
).unwrap());
assert_eq!(range_set![0..=0, 2..=2, (not_token_tree(4) + 1)..=5],
RangeSet::<[RangeInclusive<u8>; 4]>::from_valid_ranges (
[0..=0, 2..=2, 5..=5]
).unwrap());
}
#[test]
fn test_max() {
let mut set = RangeSet::<[RangeInclusive <u32>; 2]>::new();
assert_eq!(set.max(), None);
set.insert_range(4..=5);
assert_eq!(set.max(), Some(5));
set.insert(21);
assert_eq!(set.max(), Some(21));
set.insert_range(6..=13);
assert_eq!(set.max(), Some(21));
set.remove(21);
assert_eq!(set.max(), Some(13));
}
#[test]
fn test_min() {
let mut set = RangeSet::<[RangeInclusive <u32>; 2]>::new();
assert_eq!(set.min(), None);
set.insert_range(4..=5);
assert_eq!(set.min(), Some(4));
set.insert(2);
assert_eq!(set.min(), Some(2));
set.insert_range(6..=13);
assert_eq!(set.min(), Some(2));
set.remove_range(2..=4);
assert_eq!(set.min(), Some(5));
}
#[test]
fn test_random() {
use rand::{Rng, SeedableRng};
let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
let mut s = RangeSet::<[RangeInclusive <u8>; 4]>::new();
for _ in 0..10000 {
s.insert_range (rng.random()..=rng.random());
s.insert (rng.random());
s.remove_range (rng.random()..=rng.random());
s.remove (rng.random());
}
println!("s: {:?}", s);
}
}