#![feature(btree_cursors)]
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::similar_names)]
use std::{
collections::BTreeMap,
fmt::{self, Debug, Display},
ops::{self, BitOr, BitOrAssign, Bound, Deref, Not, Sub, SubAssign},
};
use thiserror::Error;
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Hash, Debug)]
pub struct Range {
start: usize,
last: usize,
}
impl Range {
#[must_use]
#[inline]
pub fn new(start: usize, last: usize) -> Self {
assert!(last < usize::MAX, "last must be less than usize::MAX");
assert!(start <= last, "start must be less than or equal to last");
Self { start, last }
}
#[must_use]
#[inline]
pub const unsafe fn new_unchecked(start: usize, last: usize) -> Self {
debug_assert!(last < usize::MAX, "last must be less than usize::MAX");
debug_assert!(start <= last, "start must be less than or equal to last");
Self { start, last }
}
#[inline]
#[must_use]
pub const fn start(&self) -> usize { self.start }
#[inline]
#[must_use]
pub const fn last(&self) -> usize { self.last }
#[inline]
#[must_use]
pub fn len(&self) -> usize {
debug_assert!(self.start <= self.last);
debug_assert!(self.last < usize::MAX);
self.last - self.start + 1
}
#[must_use]
#[inline]
pub const fn is_empty(&self) -> bool { false }
#[inline]
#[must_use]
pub const fn contains_n(&self, n: usize) -> bool { self.start <= n && n <= self.last }
#[inline]
#[must_use]
pub const fn contains(&self, other: &Self) -> bool { self.start <= other.start && self.last >= other.last }
#[inline]
#[must_use]
pub const fn intersects(&self, other: &Self) -> bool { self.start <= other.last && self.last >= other.start }
#[inline]
#[must_use]
const fn intersects_or_adjacent(&self, other: &Self) -> bool {
self.start.saturating_sub(1) <= other.last && other.start.saturating_sub(1) <= self.last
}
#[inline]
#[must_use]
pub const fn is_adjacent(&self, other: &Self) -> bool {
(self.last < usize::MAX && self.last + 1 == other.start)
|| (other.last < usize::MAX && other.last + 1 == self.start)
}
#[inline]
#[must_use]
pub const fn midpoint(&self) -> usize { self.start + (self.last - self.start) / 2 }
#[inline]
#[must_use]
pub fn intersection(&self, other: &Self) -> Option<Self> {
self.intersects(other).then(|| {
let start = self.start.max(other.start);
let last = self.last.min(other.last);
Self::new(start, last)
})
}
#[inline]
#[must_use]
pub fn difference(&self, other: &Self) -> (Option<Self>, Option<Self>) {
if !self.intersects(other) {
return (Some(*self), None);
}
let left = (self.start < other.start && other.start > 0).then(|| Self::new(self.start, other.start - 1));
let right = (self.last > other.last && other.last < usize::MAX).then(|| Self::new(other.last + 1, self.last));
(left, right)
}
#[inline]
#[must_use]
pub fn union(&self, other: &Self) -> Option<Self> {
self.intersects_or_adjacent(other).then_some({
let start = self.start.min(other.start);
let last = self.last.max(other.last);
Self::new(start, last)
})
}
}
#[cfg(feature = "http")]
impl Range {
#[inline]
#[must_use]
pub fn to_http_range_header(&self) -> String { format!("{}-{}", self.start, self.last) }
}
impl TryFrom<&ops::Range<usize>> for Range {
type Error = Error;
#[inline]
fn try_from(rng: &ops::Range<usize>) -> Result<Self, Self::Error> {
let start = rng.start;
let last = rng.end.checked_sub(1).ok_or(Error::IndexOverflow)?;
Ok(Self::new(start, last))
}
}
impl From<&ops::RangeInclusive<usize>> for Range {
#[inline]
fn from(rng: &ops::RangeInclusive<usize>) -> Self { Self { start: *rng.start(), last: *rng.end() } }
}
impl From<(usize, usize)> for Range {
#[inline]
fn from((start, last): (usize, usize)) -> Self { Self::new(start, last) }
}
impl PartialEq<Range> for RangeSet {
#[inline]
fn eq(&self, other: &Range) -> bool {
if self.ranges_count() != 1 {
return false;
}
let (&start, &last) = unsafe { self.0.first_key_value().unwrap_unchecked() };
start == other.start() && last == other.last()
}
}
impl PartialEq<RangeSet> for Range {
#[inline]
fn eq(&self, other: &RangeSet) -> bool { other.eq(self) }
}
impl From<Range> for RangeSet {
#[inline]
fn from(rng: Range) -> Self { Self(BTreeMap::from([(rng.start, rng.last)])) }
}
#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RangeSet(BTreeMap<usize, usize>);
impl Debug for RangeSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "RangeSet ")?;
let mut set = f.debug_set();
for (&start, &last) in &self.0 {
set.entry(&format_args!("{start}..={last}"));
}
set.finish()
}
}
impl RangeSet {
#[must_use]
pub fn new() -> Self { Self::default() }
#[inline]
#[must_use]
pub fn len(&self) -> usize { self.0.iter().map(|(start, last)| last - start + 1).sum() }
#[inline]
#[must_use]
pub fn ranges_count(&self) -> usize { self.0.len() }
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool { self.0.is_empty() }
#[inline]
#[must_use]
pub fn start(&self) -> Option<usize> { self.0.first_key_value().map(|(start, _)| *start) }
#[inline]
#[must_use]
pub fn last(&self) -> Option<usize> { self.0.last_key_value().map(|(_, last)| *last) }
#[inline]
#[must_use]
pub fn contains_n(&self, n: usize) -> bool {
if let Some((_, last)) = self.0.range(..=n).next_back() {
return n <= *last;
}
false
}
#[inline]
#[must_use]
pub fn contains(&self, rng: &Range) -> bool {
if let Some((_, last)) = self.0.range(..=rng.start).next_back() {
return rng.last <= *last;
}
false
}
#[inline]
pub fn ranges(&self) -> impl Iterator<Item = Range> {
self.0.iter().map(|(start, end)| Range::from((*start, *end)))
}
pub fn insert_range(&mut self, rng: &Range) -> bool {
let mut cursor = self.0.upper_bound_mut(Bound::Included(&rng.start));
if let Some(prev) = cursor.peek_prev().map(|(start, last)| Range::from((*start, *last)))
&& prev.intersects_or_adjacent(rng)
{
cursor.prev();
}
if let Some(next) = cursor.peek_next().map(|(start, last)| Range::from((*start, *last)))
&& next.contains(rng)
{
return false;
}
let mut merged_rng = *rng;
unsafe {
while cursor
.peek_next()
.map(|(start, last)| Range::new(*start, *last))
.is_some_and(|next| merged_rng.intersects_or_adjacent(&next))
{
let rng_to_merge: Range = cursor.remove_next().unwrap_unchecked().into();
merged_rng = merged_rng.union(&rng_to_merge).unwrap_unchecked();
}
cursor.insert_after(merged_rng.start, merged_rng.last).unwrap_unchecked();
};
true
}
pub fn insert_n_at(&mut self, n: usize, at: usize) {
if n == 0 {
return;
}
assert!(at.checked_add(n) < Some(usize::MAX));
let rng = unsafe { Range::new_unchecked(at, at + n - 1) };
self.insert_range(&rng);
}
pub unsafe fn insert_n_at_unchecked(&mut self, n: usize, at: usize) {
if n == 0 {
return;
}
debug_assert!(at.checked_add(n) < Some(usize::MAX));
let rng = unsafe { Range::new_unchecked(at, at + n - 1) };
self.insert_range(&rng);
}
#[must_use]
pub fn union_merge(&self, other: &Self) -> Self {
let mut result = BTreeMap::new();
let mut self_it = self.0.iter().peekable();
let mut other_it = other.0.iter().peekable();
let mut cur_merged: Option<Range> = None;
loop {
let next_rng_tuple = unsafe {
match (self_it.peek(), other_it.peek()) {
(Some((ls, _)), Some((rs, _))) => {
if ls <= rs {
self_it.next().unwrap_unchecked() } else {
other_it.next().unwrap_unchecked()
}
}
(Some(_), None) => self_it.next().unwrap_unchecked(),
(None, Some(_)) => other_it.next().unwrap_unchecked(),
(None, None) => break,
}
};
let next_rng = Range::new(*next_rng_tuple.0, *next_rng_tuple.1);
match cur_merged.as_mut() {
None => {
cur_merged = Some(next_rng);
}
Some(merged) if merged.intersects_or_adjacent(&next_rng) => {
merged.last = merged.last.max(next_rng.last);
}
Some(merged) => {
result.insert(merged.start, merged.last);
*merged = next_rng;
}
}
}
if let Some(last_rng) = cur_merged {
result.insert(last_rng.start, last_rng.last);
}
Self(result)
}
#[must_use]
#[inline]
pub fn union(&self, other: &Self) -> Self {
if self.is_empty() {
return other.clone();
}
if other.is_empty() {
return self.clone();
}
let self_rng_count = self.ranges_count();
let other_rng_count = other.ranges_count();
let insert_cost_estimate = other_rng_count * self_rng_count.ilog2() as usize;
let merge_cost_estimate = self_rng_count + other_rng_count;
if insert_cost_estimate < merge_cost_estimate && other_rng_count < self_rng_count {
let mut result = self.clone();
for (&start, &last) in &other.0 {
result.insert_range(&Range::new(start, last));
}
result
} else {
self.union_merge(other)
}
}
#[inline]
fn union_assign(&mut self, other: &Self) {
if self.0.is_empty() {
self.0 = other.0.clone();
}
if other.0.is_empty() {
return;
}
let self_rng_count = self.ranges_count();
let other_rng_count = other.ranges_count();
let insert_cost_estimate = other_rng_count * self_rng_count.ilog2() as usize;
let merge_cost_estimate = self_rng_count + other_rng_count;
if insert_cost_estimate < merge_cost_estimate && other_rng_count < self_rng_count {
for (&start, &last) in &other.0 {
self.insert_range(&Range::new(start, last));
}
} else {
*self = self.union_merge(other);
}
}
#[must_use]
pub fn difference(&self, other: &Self) -> Self {
if self.is_empty() || other.is_empty() {
return self.clone();
}
let mut result = Self::new();
let mut a_it = self.0.iter();
let mut b_it = other.0.iter().peekable();
let mut cur_a = unsafe {
let (&start, &last) = a_it.next().unwrap_unchecked();
Range::new(start, last)
};
loop {
if let Some(&(&b_start, &b_last)) = b_it.peek() {
let b_range = Range::new(b_start, b_last);
if b_range.last() < cur_a.start() {
b_it.next(); continue;
}
if b_range.start() > cur_a.last() {
result.insert_range(&cur_a);
if let Some((&s, &l)) = a_it.next() {
cur_a = Range::new(s, l);
continue;
}
break;
}
if b_range.start() > cur_a.start() {
let prefix = Range::new(cur_a.start(), b_range.start() - 1);
result.insert_range(&prefix);
}
if let Some(new_start) = b_range.last().checked_add(1) {
if new_start > cur_a.last() {
cur_a = match a_it.next() {
Some((&s, &l)) => Range::new(s, l),
None => break, };
} else {
cur_a = Range::new(new_start, cur_a.last());
}
} else {
cur_a = match a_it.next() {
Some((&s, &l)) => Range::new(s, l),
None => break, };
}
} else {
result.insert_range(&cur_a);
for (&start, &last) in a_it {
result.insert_range(&Range::new(start, last));
}
break; }
}
result
}
#[inline]
pub fn difference_assign(&mut self, other: &Self) {
if self.0.is_empty() || other.0.is_empty() {
return;
}
*self = self.difference(other);
}
#[must_use]
#[inline]
pub fn union_frozen(&self, other: &FrozenRangeSet) -> Self {
if self.0.is_empty() {
return other.clone().into();
}
if other.is_empty() {
return self.clone();
}
let mut result = self.clone();
for range in other.iter() {
result.insert_range(range);
}
result
}
#[inline]
pub fn union_assign_frozen(&mut self, other: &FrozenRangeSet) {
if self.0.is_empty() {
*self = other.clone().into();
return;
}
if other.is_empty() {
return;
}
for range in other.iter() {
self.insert_range(range);
}
}
#[must_use]
#[inline]
pub fn difference_frozen(&self, other: &FrozenRangeSet) -> Self {
if self.0.is_empty() || other.is_empty() {
return self.clone();
}
let other_set: Self = other.clone().into();
self.difference(&other_set)
}
#[inline]
pub fn difference_assign_frozen(&mut self, other: &FrozenRangeSet) {
if self.0.is_empty() || other.is_empty() {
return;
}
let other_set: Self = other.clone().into();
self.difference_assign(&other_set);
}
}
impl RangeSet {
#[must_use]
pub fn freeze(&self) -> FrozenRangeSet {
let ranges = self.0.iter().map(|(&start, &last)| Range::new(start, last)).collect::<Box<[_]>>();
FrozenRangeSet(ranges)
}
pub fn into_chunks(&mut self, block_size: usize) -> ChunkedMutIter<'_> {
debug_assert!(block_size > 0, "block_size must be greater than 0");
ChunkedMutIter { inner: self, block_size }
}
}
impl BitOrAssign<&Self> for RangeSet {
#[inline]
fn bitor_assign(&mut self, rhs: &Self) { self.union_assign(rhs); }
}
impl BitOr<Self> for &RangeSet {
type Output = RangeSet;
#[inline]
fn bitor(self, rhs: Self) -> Self::Output { self.union(rhs) }
}
impl SubAssign<&Self> for RangeSet {
#[inline]
fn sub_assign(&mut self, rhs: &Self) { self.difference_assign(rhs); }
}
impl Sub<Self> for &RangeSet {
type Output = RangeSet;
#[inline]
fn sub(self, rhs: Self) -> Self::Output { self.difference(rhs) }
}
pub struct ChunkedMutIter<'a> {
inner: &'a mut RangeSet,
block_size: usize,
}
impl Iterator for ChunkedMutIter<'_> {
type Item = FrozenRangeSet;
fn next(&mut self) -> Option<Self::Item> {
if self.inner.is_empty() {
return None;
}
let mut chunk_rngs = Vec::with_capacity(1);
let mut remaining_size = self.block_size;
while remaining_size > 0 {
let Some((&start, &last)) = self.inner.0.first_key_value() else {
break;
};
let cur_rng_len = last - start + 1;
if cur_rng_len <= remaining_size {
self.inner.0.pop_first();
chunk_rngs.push(Range::new(start, last));
remaining_size -= cur_rng_len;
} else {
debug_assert!(start.checked_add(remaining_size) < Some(usize::MAX));
let chunk_last = start + remaining_size - 1;
chunk_rngs.push(Range::new(start, chunk_last));
let original_last = self.inner.0.pop_first().unwrap().1;
debug_assert!(chunk_last < usize::MAX);
self.inner.0.insert(chunk_last + 1, original_last);
remaining_size = 0;
}
}
chunk_rngs.is_empty().not().then(|| FrozenRangeSet(chunk_rngs.into_boxed_slice()))
}
}
impl<T: Into<Range>> FromIterator<T> for RangeSet {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut set = Self::new();
for item in iter {
set.insert_range(&item.into());
}
set
}
}
#[derive(Debug, Error, PartialEq, Eq)]
pub enum Error {
#[cfg(feature = "http")]
#[error(transparent)]
Header(#[from] http_range_header::RangeUnsatisfiableError),
#[error("invalid range unit")]
Invalid,
#[error("index overflow")]
IndexOverflow,
#[error("empty ranges")]
Empty,
}
#[cfg(feature = "http")]
impl RangeSet {
pub fn parse_ranges_headers(header_content: &str, total_size: usize) -> Result<Self, Error> {
use http_range_header::{EndPosition, StartPosition};
if total_size == 0 {
return Err(Error::Empty);
}
let mut set = Self::new();
let rngs = http_range_header::parse_range_header(header_content)?.ranges;
for item in rngs {
let (start, last) = match (item.start, item.end) {
(StartPosition::Index(s), EndPosition::Index(l)) => (s as usize, l as usize),
(StartPosition::Index(s), EndPosition::LastByte) => {
let start = s as usize;
if start >= total_size {
return Err(Error::Invalid);
}
(start, total_size - 1)
}
(StartPosition::FromLast(c), EndPosition::LastByte) => {
if c == 0 {
return Err(Error::Empty);
}
let s = total_size.saturating_sub(c as usize);
(s, total_size - 1)
}
(StartPosition::FromLast(_), EndPosition::Index(_)) => return Err(Error::Invalid),
};
if start > last {
return Err(Error::Invalid);
}
if start >= total_size {
return Err(Error::Invalid);
}
let last_clamped: usize = last.min(total_size - 1);
set.insert_range(&Range::new(start, last_clamped));
}
if set.is_empty() {
return Err(Error::Empty);
}
Ok(set)
}
#[inline]
#[must_use]
pub fn to_http_range_header(&self) -> Option<Box<str>> {
if self.0.is_empty() {
return None;
}
let parts: Box<[String]> = self.0.iter().map(|(&start, &last)| format!("{start}-{last}")).collect();
Some(format!("bytes={}", parts.join(",")).into_boxed_str())
}
}
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct FrozenRangeSet(Box<[Range]>);
impl Deref for FrozenRangeSet {
type Target = [Range];
#[inline]
fn deref(&self) -> &Self::Target { &self.0 }
}
impl FrozenRangeSet {
#[inline]
#[must_use]
pub fn start(&self) -> Option<usize> { self.0.first().map(Range::start) }
#[inline]
#[must_use]
pub fn last(&self) -> Option<usize> { self.0.last().map(Range::last) }
#[inline]
#[must_use]
pub fn ranges_count(&self) -> usize { self.0.len() }
#[inline]
#[must_use]
pub fn contains_n(&self, n: usize) -> bool {
let partition_idx = self.0.partition_point(|rng| rng.start() <= n);
if partition_idx == 0 {
return false;
}
let candidate_rng = unsafe { self.0.get_unchecked(partition_idx - 1) };
n <= candidate_rng.last()
}
#[inline]
#[must_use]
pub fn contains(&self, rng: &Range) -> bool {
let partition_idx = self.0.partition_point(|r| r.start() <= rng.start());
if partition_idx == 0 {
return false;
}
let candidate_rng = unsafe { self.0.get_unchecked(partition_idx - 1) };
candidate_rng.contains(rng)
}
}
impl BitOr<&FrozenRangeSet> for &RangeSet {
type Output = RangeSet;
#[inline]
fn bitor(self, rhs: &FrozenRangeSet) -> Self::Output { self.union_frozen(rhs) }
}
impl Sub<&FrozenRangeSet> for &RangeSet {
type Output = RangeSet;
#[inline]
fn sub(self, rhs: &FrozenRangeSet) -> Self::Output { self.difference_frozen(rhs) }
}
impl BitOrAssign<&FrozenRangeSet> for RangeSet {
#[inline]
fn bitor_assign(&mut self, rhs: &FrozenRangeSet) { self.union_assign_frozen(rhs); }
}
impl SubAssign<&FrozenRangeSet> for RangeSet {
#[inline]
fn sub_assign(&mut self, rhs: &FrozenRangeSet) { self.difference_assign_frozen(rhs); }
}
#[cfg(feature = "http")]
impl FrozenRangeSet {
#[inline]
#[must_use]
pub fn to_http_range_header(&self) -> Option<Box<str>> {
if self.is_empty() {
return None;
}
let parts: Box<[String]> = self.iter().map(|range| format!("{}-{}", range.start(), range.last())).collect();
Some(format!("bytes={}", parts.join(",")).into_boxed_str())
}
}
impl From<RangeSet> for FrozenRangeSet {
#[inline]
fn from(set: RangeSet) -> Self {
let ranges = set.0.into_iter().map(Into::into).collect::<Box<[_]>>();
Self(ranges)
}
}
impl From<FrozenRangeSet> for RangeSet {
#[inline]
fn from(frozen: FrozenRangeSet) -> Self {
let map = frozen.0.into_iter().map(|Range { start, last }| (start, last)).collect::<BTreeMap<_, _>>();
Self(map)
}
}
impl PartialEq<FrozenRangeSet> for RangeSet {
#[inline]
fn eq(&self, other: &FrozenRangeSet) -> bool {
self.ranges_count() == other.ranges_count() && self.ranges().eq(other.iter().copied())
}
}
impl PartialEq<RangeSet> for FrozenRangeSet {
#[inline]
fn eq(&self, other: &RangeSet) -> bool { other.eq(self) }
}
impl PartialEq<Range> for FrozenRangeSet {
#[inline]
fn eq(&self, other: &Range) -> bool { self.0.len() == 1 && *unsafe { self.0.first().unwrap_unchecked() } == *other }
}
impl PartialEq<FrozenRangeSet> for Range {
#[inline]
fn eq(&self, other: &FrozenRangeSet) -> bool { other.eq(self) }
}
const BINARY_BASE: usize = 1024;
const BINARY_UNIT_TABLE: [(usize, &str); 7] = [
(1, "B"),
(BINARY_BASE, "KiB"),
(BINARY_BASE.pow(2), "MiB"),
(BINARY_BASE.pow(3), "GiB"),
(BINARY_BASE.pow(4), "TiB"),
(BINARY_BASE.pow(5), "PiB"),
(BINARY_BASE.pow(6), "EiB"),
];
const SI_BASE: usize = 1000;
const SI_UNIT_TABLE: [(usize, &str); 7] = [
(1, "B"),
(SI_BASE, "KB"),
(SI_BASE.pow(2), "MB"),
(SI_BASE.pow(3), "GB"),
(SI_BASE.pow(4), "TB"),
(SI_BASE.pow(5), "PB"),
(SI_BASE.pow(6), "EB"),
];
fn analyze_bytes(size: usize, use_binary: bool) -> (f64, &'static str, usize) {
if size == 0 {
return (0., "B", 1);
}
let (base, unit_table) = if use_binary {
(BINARY_BASE as f64, &BINARY_UNIT_TABLE)
} else {
(SI_BASE as f64, &SI_UNIT_TABLE)
};
let exp = if size > 0 {
(size as f64).log(base).floor() as usize
} else {
0
};
let idx = exp.min(unit_table.len() - 1);
let (unit_base, unit_name) = unit_table[idx];
let val = size as f64 / unit_base as f64;
(val, unit_name, unit_base)
}
impl Display for Range {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let use_binary = !f.alternate();
let (_last_val_temp, common_unit, unit_base) = analyze_bytes(self.last, use_binary);
let unit_base_f64 = unit_base as f64;
let format_num = |val: f64| -> String {
if (val.fract()).abs() < 1e-9 {
format!("{val:.0}")
} else {
format!("{val:.2}")
}
};
let start_val = self.start as f64 / unit_base_f64;
let last_val = self.last as f64 / unit_base_f64;
if self.start == self.last {
write!(f, "{} {}", format_num(start_val), common_unit)
} else {
write!(f, "{} ~ {} {}", format_num(start_val), format_num(last_val), common_unit)
}
}
}
impl Display for RangeSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
for (&start, &last) in &self.0 {
if !first {
f.write_str(", ")?;
}
write!(f, "{:?}", Range::new(start, last))?;
first = false;
}
Ok(())
}
}
impl Debug for FrozenRangeSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
for rng in &self.0 {
if !first {
f.write_str(", ")?;
}
write!(f, "{rng:?}")?;
first = false;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::{Error, FrozenRangeSet, Range, RangeSet};
fn make_set(ranges: &[(usize, usize)]) -> RangeSet {
let mut set = RangeSet::new();
for &(start, last) in ranges {
set.insert_range(&Range::new(start, last));
}
set
}
fn check_ranges(set: &RangeSet, expected: &[(usize, usize)]) {
let ranges: Vec<(usize, usize)> = set.ranges().map(|r| (r.start(), r.last())).collect();
assert_eq!(ranges, expected, "RangeSet ranges do not match expected");
}
#[test]
fn test_range_new_valid() {
let r = Range::new(10, 20);
assert_eq!(r.start(), 10);
assert_eq!(r.last(), 20);
assert_eq!(r.len(), 11);
assert!(!r.is_empty());
}
#[test]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_range_new_panic_order() { let _ = Range::new(20, 10); }
#[test]
#[should_panic(expected = "last must be less than usize::MAX")]
fn test_range_new_panic_max() { let _ = Range::new(0, usize::MAX); }
#[test]
fn test_range_edge_cases() {
let r = Range::new(5, 5);
assert_eq!(r.len(), 1);
let r = Range::new(0, usize::MAX - 1);
assert_eq!(r.len(), usize::MAX);
let r = Range::new(usize::MAX - 2, usize::MAX - 1);
assert_eq!(r.len(), 2);
}
#[test]
fn test_range_contains_n() {
let r = Range::new(10, 20);
assert!(r.contains_n(10));
assert!(r.contains_n(15));
assert!(r.contains_n(20));
assert!(!r.contains_n(9));
assert!(!r.contains_n(21));
}
#[test]
fn test_range_contains_range() {
let r = Range::new(10, 30);
assert!(r.contains(&Range::new(10, 30))); assert!(r.contains(&Range::new(15, 25))); assert!(r.contains(&Range::new(10, 15))); assert!(r.contains(&Range::new(25, 30)));
assert!(!r.contains(&Range::new(9, 30))); assert!(!r.contains(&Range::new(10, 31))); assert!(!r.contains(&Range::new(5, 40))); assert!(!r.contains(&Range::new(40, 50))); }
#[test]
fn test_range_intersects() {
let r = Range::new(10, 20);
assert!(r.intersects(&Range::new(5, 15)));
assert!(r.intersects(&Range::new(15, 25)));
assert!(r.intersects(&Range::new(12, 18)));
assert!(r.intersects(&Range::new(5, 25)));
assert!(r.intersects(&Range::new(0, 10)));
assert!(r.intersects(&Range::new(20, 30)));
assert!(!r.intersects(&Range::new(0, 9)));
assert!(!r.intersects(&Range::new(21, 30)));
}
#[test]
fn test_range_adjacency() {
let r = Range::new(10, 20);
assert!(r.is_adjacent(&Range::new(5, 9)));
assert!(r.is_adjacent(&Range::new(21, 25)));
assert!(!r.is_adjacent(&Range::new(5, 10)));
assert!(!r.is_adjacent(&Range::new(0, 8)));
assert!(!r.is_adjacent(&Range::new(22, 30)));
}
#[test]
fn test_range_operations() {
let r = Range::new(10, 20);
assert_eq!(r.midpoint(), 15);
assert_eq!(Range::new(10, 11).midpoint(), 10);
assert_eq!(r.intersection(&Range::new(15, 25)), Some(Range::new(15, 20)));
assert_eq!(r.intersection(&Range::new(21, 30)), None);
assert_eq!(r.union(&Range::new(15, 25)), Some(Range::new(10, 25))); assert_eq!(r.union(&Range::new(21, 25)), Some(Range::new(10, 25))); assert_eq!(r.union(&Range::new(22, 25)), None);
assert_eq!(r.difference(&Range::new(12, 18)), (Some(Range::new(10, 11)), Some(Range::new(19, 20))));
assert_eq!(r.difference(&Range::new(5, 15)), (None, Some(Range::new(16, 20))));
assert_eq!(r.difference(&Range::new(15, 25)), (Some(Range::new(10, 14)), None));
assert_eq!(r.difference(&Range::new(0, 50)), (None, None));
assert_eq!(r.difference(&Range::new(30, 40)), (Some(r), None));
}
#[test]
fn test_range_conversions() {
let std_range = 10..20;
let range = Range::try_from(&std_range).unwrap();
assert_eq!(range.start(), 10);
assert_eq!(range.last(), 19);
let empty_range = 0..0;
assert!(Range::try_from(&empty_range).is_err());
let inclusive_range = 10..=20;
let range = Range::from(&inclusive_range);
assert_eq!(range.start(), 10);
assert_eq!(range.last(), 20);
let range = Range::from((10, 20));
assert_eq!(range.start(), 10);
assert_eq!(range.last(), 20);
}
#[test]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_range_from_tuple_panic() { let _ = Range::from((20, 10)); }
#[test]
fn test_range_new_unchecked() {
let range = unsafe { Range::new_unchecked(10, 20) };
assert_eq!(range.start(), 10);
assert_eq!(range.last(), 20);
assert_eq!(range.len(), 11);
let single = unsafe { Range::new_unchecked(5, 5) };
assert_eq!(single.len(), 1);
}
#[test]
fn test_rangeset_insert_basic() {
let mut set = RangeSet::new();
assert!(set.is_empty());
set.insert_range(&Range::new(10, 20));
check_ranges(&set, &[(10, 20)]);
assert_eq!(set.len(), 11);
set.insert_range(&Range::new(30, 40));
check_ranges(&set, &[(10, 20), (30, 40)]);
set.insert_range(&Range::new(0, 5));
check_ranges(&set, &[(0, 5), (10, 20), (30, 40)]);
set.insert_range(&Range::new(22, 28));
check_ranges(&set, &[(0, 5), (10, 20), (22, 28), (30, 40)]);
}
#[test]
fn test_rangeset_insert_merge() {
let mut set = make_set(&[(10, 20), (30, 40)]);
set.insert_range(&Range::new(15, 25));
check_ranges(&set, &[(10, 25), (30, 40)]);
set.insert_range(&Range::new(28, 35));
check_ranges(&set, &[(10, 25), (28, 40)]);
set.insert_range(&Range::new(20, 30));
check_ranges(&set, &[(10, 40)]);
}
#[test]
fn test_rangeset_insert_adjacency() {
let mut set = make_set(&[(10, 20)]);
set.insert_range(&Range::new(21, 25));
check_ranges(&set, &[(10, 25)]);
set.insert_range(&Range::new(5, 9));
check_ranges(&set, &[(5, 25)]);
}
#[test]
fn test_rangeset_insert_contained() {
let mut set = make_set(&[(10, 50)]);
assert!(!set.insert_range(&Range::new(20, 30)));
check_ranges(&set, &[(10, 50)]);
assert!(!set.insert_range(&Range::new(10, 50)));
check_ranges(&set, &[(10, 50)]);
}
#[test]
fn test_rangeset_insert_consuming() {
let mut set = make_set(&[(10, 20), (30, 40), (50, 60)]);
set.insert_range(&Range::new(0, 100));
check_ranges(&set, &[(0, 100)]);
}
#[test]
fn test_rangeset_insert_n_at() {
let mut set = RangeSet::new();
set.insert_n_at(5, 10); check_ranges(&set, &[(10, 14)]);
set.insert_n_at(0, 20); check_ranges(&set, &[(10, 14)]);
set.insert_n_at(1, 15); check_ranges(&set, &[(10, 15)]);
}
#[test]
fn test_rangeset_union() {
let s1 = make_set(&[(0, 10), (20, 30)]);
let s2 = make_set(&[(5, 25), (35, 40)]);
let u = s1.union(&s2);
check_ranges(&u, &[(0, 30), (35, 40)]);
let u2 = s2.union(&s1);
check_ranges(&u2, &[(0, 30), (35, 40)]);
}
#[test]
fn test_rangeset_difference() {
let a = make_set(&[(0, 50)]);
let b = make_set(&[(20, 30)]);
let d1 = a.difference(&b);
check_ranges(&d1, &[(0, 19), (31, 50)]);
let c = make_set(&[(0, 10)]);
let d2 = a.difference(&c);
check_ranges(&d2, &[(11, 50)]);
let d = make_set(&[(40, 60)]); let d3 = a.difference(&d);
check_ranges(&d3, &[(0, 39)]);
let e = make_set(&[(10, 15), (35, 40)]);
let d4 = a.difference(&e);
check_ranges(&d4, &[(0, 9), (16, 34), (41, 50)]);
}
#[test]
fn test_rangeset_difference_complex() {
let a = make_set(&[(0, 10), (20, 30), (40, 50)]);
let b = make_set(&[(5, 25), (45, 55)]);
let res = a.difference(&b);
check_ranges(&res, &[(0, 4), (26, 30), (40, 44)]);
}
#[test]
fn test_frozen_lifecycle() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(0, 10));
set.insert_range(&Range::new(20, 30));
let frozen = set.freeze();
assert_eq!(frozen.ranges_count(), 2);
assert!(frozen.contains_n(5));
assert!(frozen.contains(&Range::new(20, 25)));
let thawed: RangeSet = frozen.into();
check_ranges(&thawed, &[(0, 10), (20, 30)]);
}
#[test]
fn test_frozen_operators() {
let s1 = make_set(&[(0, 10)]);
let mut s2 = RangeSet::new();
s2.insert_range(&Range::new(5, 15));
let f2 = s2.freeze();
let u = &s1 | &f2;
check_ranges(&u, &[(0, 15)]);
let d = &s1 - &f2; check_ranges(&d, &[(0, 4)]);
let mut s3 = s1.clone();
s3 |= &f2;
check_ranges(&s3, &[(0, 15)]);
let mut s4 = s1.clone();
s4 -= &f2;
check_ranges(&s4, &[(0, 4)]);
}
#[test]
fn test_chunks_basic() {
let mut set = make_set(&[(0, 9)]); let chunks: Vec<FrozenRangeSet> = set.into_chunks(4).collect();
assert_eq!(chunks.len(), 3);
let c1 = &chunks[0];
assert_eq!(c1.len(), 1);
assert_eq!(c1[0], Range::new(0, 3));
let c2 = &chunks[1];
assert_eq!(c2.len(), 1);
assert_eq!(c2[0], Range::new(4, 7));
let c3 = &chunks[2];
assert_eq!(c3.len(), 1);
assert_eq!(c3[0], Range::new(8, 9));
}
#[test]
fn test_chunks_fragmented() {
let mut set = make_set(&[(0, 1), (10, 11), (20, 21)]); let chunks: Vec<FrozenRangeSet> = set.into_chunks(3).collect();
assert_eq!(chunks.len(), 2);
assert_eq!(chunks[0].len(), 2);
assert_eq!(chunks[0][0], Range::new(0, 1));
assert_eq!(chunks[0][1], Range::new(10, 10));
assert_eq!(chunks[1].len(), 2);
assert_eq!(chunks[1][0], Range::new(11, 11));
assert_eq!(chunks[1][1], Range::new(20, 21));
}
#[cfg(feature = "http")]
#[test]
fn test_http_parsing_success() {
let total_size = 1000;
let s = RangeSet::parse_ranges_headers("bytes=0-499", total_size).unwrap();
check_ranges(&s, &[(0, 499)]);
let s = RangeSet::parse_ranges_headers("bytes=500-", total_size).unwrap();
check_ranges(&s, &[(500, 999)]);
let s = RangeSet::parse_ranges_headers("bytes=-100", total_size).unwrap();
check_ranges(&s, &[(900, 999)]);
let s = RangeSet::parse_ranges_headers("bytes=0-10,5-20,-10", total_size).unwrap();
check_ranges(&s, &[(0, 20), (990, 999)]);
let s = RangeSet::parse_ranges_headers("bytes=0-2000", total_size).unwrap();
check_ranges(&s, &[(0, 999)]);
}
#[cfg(feature = "http")]
#[test]
fn test_http_parsing_errors() {
let total = 100;
assert_eq!(RangeSet::parse_ranges_headers("bytes=50-40", total), Err(Error::Invalid));
assert_eq!(RangeSet::parse_ranges_headers("bytes=100-", total), Err(Error::Invalid));
assert_eq!(RangeSet::parse_ranges_headers("bytes=0-50", 0), Err(Error::Empty));
}
#[cfg(feature = "http")]
#[test]
fn test_http_generation() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(0, 9));
set.insert_range(&Range::new(20, 29));
let header = set.to_http_range_header().unwrap();
assert_eq!(&*header, "bytes=0-9,20-29");
let frozen = set.freeze();
let f_header = frozen.to_http_range_header().unwrap();
assert_eq!(&*f_header, "bytes=0-9,20-29");
}
#[test]
fn test_formatting() {
let r = Range::new(0, 1023); let s = format!("{}", r);
assert!(s.contains("0 ~ 1023 B"));
let r2 = Range::new(0, 2048); let s2 = format!("{}", r2);
assert!(s2.contains("2 KiB"));
let set = make_set(&[(0, 10), (20, 30)]);
let debug_str = format!("{:?}", set);
assert!(debug_str.contains("RangeSet {0..=10, 20..=30}"));
}
#[test]
fn test_rangeset_union_merge_explicit() {
let s1 = make_set(&[(0, 10), (20, 30), (40, 50)]);
let s2 = make_set(&[(5, 25), (35, 45)]);
let res = s1.union_merge(&s2);
check_ranges(&res, &[(0, 30), (35, 50)]);
let res2 = s2.union_merge(&s1);
check_ranges(&res2, &[(0, 30), (35, 50)]);
let d1 = make_set(&[(0, 5)]);
let d2 = make_set(&[(10, 15)]);
check_ranges(&d1.union_merge(&d2), &[(0, 5), (10, 15)]);
let t1 = make_set(&[(0, 5)]);
let t2 = make_set(&[(6, 10)]);
check_ranges(&t1.union_merge(&t2), &[(0, 10)]);
let large = make_set(&[(0, 100)]);
let small = make_set(&[(20, 30), (50, 60)]);
check_ranges(&large.union_merge(&small), &[(0, 100)]);
check_ranges(&small.union_merge(&large), &[(0, 100)]);
let gap_set = make_set(&[(0, 10), (100, 110)]);
let bridge_set = make_set(&[(5, 105)]);
check_ranges(&gap_set.union_merge(&bridge_set), &[(0, 110)]);
}
#[test]
fn test_rangeset_union_assign() {
let mut set1 = make_set(&[(0, 10), (20, 30)]);
let set2 = make_set(&[(5, 15), (25, 35)]);
set1.union_assign(&set2);
check_ranges(&set1, &[(0, 15), (20, 35)]);
let mut set3 = RangeSet::new();
let set4 = make_set(&[(0, 10)]);
set3.union_assign(&set4);
check_ranges(&set3, &[(0, 10)]);
let mut set5 = make_set(&[(0, 10)]);
let set6 = RangeSet::new();
set5.union_assign(&set6);
check_ranges(&set5, &[(0, 10)]);
}
#[test]
fn test_rangeset_difference_assign() {
let mut set1 = make_set(&[(0, 50)]);
let set2 = make_set(&[(20, 30)]);
set1.difference_assign(&set2);
check_ranges(&set1, &[(0, 19), (31, 50)]);
let mut set3 = make_set(&[(0, 10)]);
let set4 = RangeSet::new();
set3.difference_assign(&set4);
check_ranges(&set3, &[(0, 10)]);
let mut set5 = RangeSet::new();
let set6 = make_set(&[(0, 10)]);
set5.difference_assign(&set6);
assert!(set5.is_empty());
}
#[test]
fn test_rangeset_frozen_operations() {
let set1 = make_set(&[(0, 10)]);
let set2 = make_set(&[(5, 15)]);
let frozen2 = set2.freeze();
let result = set1.union_frozen(&frozen2);
check_ranges(&result, &[(0, 15)]);
let empty = RangeSet::new();
let result2 = empty.union_frozen(&frozen2);
check_ranges(&result2, &[(5, 15)]);
let frozen_empty = RangeSet::new().freeze();
let result3 = set1.union_frozen(&frozen_empty);
check_ranges(&result3, &[(0, 10)]);
let mut set3 = make_set(&[(0, 10)]);
set3.union_assign_frozen(&frozen2);
check_ranges(&set3, &[(0, 15)]);
let set4 = make_set(&[(0, 20)]);
let frozen3 = make_set(&[(5, 15)]).freeze();
let result4 = set4.difference_frozen(&frozen3);
check_ranges(&result4, &[(0, 4), (16, 20)]);
let mut set5 = make_set(&[(0, 20)]);
set5.difference_assign_frozen(&frozen3);
check_ranges(&set5, &[(0, 4), (16, 20)]);
}
#[test]
fn test_rangeset_from_iterator() {
let ranges = vec![Range::new(0, 10), Range::new(20, 30), Range::new(5, 15)];
let set: RangeSet = ranges.into_iter().collect();
check_ranges(&set, &[(0, 15), (20, 30)]);
let tuples = vec![(0, 10), (20, 30)];
let set2: RangeSet = tuples.into_iter().collect();
check_ranges(&set2, &[(0, 10), (20, 30)]);
let empty: Vec<Range> = vec![];
let set3: RangeSet = empty.into_iter().collect();
assert!(set3.is_empty());
}
#[test]
fn test_rangeset_operators() {
let set1 = make_set(&[(0, 10)]);
let set2 = make_set(&[(5, 15)]);
let union = &set1 | &set2;
check_ranges(&union, &[(0, 15)]);
let diff = &set1 - &set2;
check_ranges(&diff, &[(0, 4)]);
let mut set3 = set1.clone();
set3 |= &set2;
check_ranges(&set3, &[(0, 15)]);
let mut set4 = set1.clone();
set4 -= &set2;
check_ranges(&set4, &[(0, 4)]);
}
#[test]
fn test_rangeset_empty_operations() {
let empty = RangeSet::new();
let non_empty = make_set(&[(0, 10)]);
let result1 = empty.union(&non_empty);
check_ranges(&result1, &[(0, 10)]);
let result2 = non_empty.union(&empty);
check_ranges(&result2, &[(0, 10)]);
let result3 = empty.difference(&non_empty);
assert!(result3.is_empty());
let result4 = non_empty.difference(&empty);
check_ranges(&result4, &[(0, 10)]);
assert_eq!(empty.start(), None);
assert_eq!(empty.last(), None);
assert_eq!(empty.len(), 0);
assert_eq!(empty.ranges_count(), 0);
assert!(!empty.contains_n(5));
assert!(!empty.contains(&Range::new(0, 10)));
}
#[test]
fn test_frozen_rangeset_empty() {
let empty = RangeSet::new().freeze();
assert_eq!(empty.start(), None);
assert_eq!(empty.last(), None);
assert_eq!(empty.len(), 0);
assert_eq!(empty.ranges_count(), 0);
assert!(empty.is_empty());
assert!(!empty.contains_n(5));
assert!(!empty.contains(&Range::new(0, 10)));
#[cfg(feature = "http")]
assert!(empty.to_http_range_header().is_none());
}
#[test]
fn test_rangeset_partial_eq() {
let set1 = make_set(&[(0, 10)]);
let range1 = Range::new(0, 10);
assert_eq!(set1, range1);
assert_eq!(range1, set1);
let set2 = make_set(&[(0, 5), (7, 10)]);
assert_ne!(set2, range1);
let frozen = set1.freeze();
assert_eq!(frozen, range1);
assert_eq!(range1, frozen);
assert_eq!(frozen, set1);
assert_eq!(set1, frozen);
}
#[cfg(feature = "http")]
#[test]
fn test_http_edge_cases() {
let result = RangeSet::parse_ranges_headers("bytes=-0", 100);
assert!(result.is_err());
let result = RangeSet::parse_ranges_headers("bytes=-200", 100).unwrap();
check_ranges(&result, &[(0, 99)]);
let empty = RangeSet::new();
assert!(empty.to_http_range_header().is_none());
let result = RangeSet::parse_ranges_headers("bytes=0-0", 100).unwrap();
check_ranges(&result, &[(0, 0)]);
let result = RangeSet::parse_ranges_headers("bytes=0-10,5-15,20-30", 100).unwrap();
check_ranges(&result, &[(0, 15), (20, 30)]);
}
#[test]
fn test_display_formatting() {
let small = Range::new(0, 999);
let display = format!("{}", small);
assert!(display.contains("B"));
let binary = Range::new(0, 1024);
let binary_display = format!("{}", binary);
assert!(binary_display.contains("KiB") || binary_display.contains("KB"));
let si = Range::new(0, 1024);
let si_display = format!("{:#}", si); assert!(si_display.contains("B"));
let set = make_set(&[(0, 10), (20, 30)]);
let display = format!("{}", set);
assert!(display.contains("0"));
assert!(display.contains("10"));
assert!(display.contains("20"));
assert!(display.contains("30"));
}
#[test]
fn test_chunks_edge_cases() {
let mut empty = RangeSet::new();
let chunks: Vec<FrozenRangeSet> = empty.into_chunks(10).collect();
assert!(chunks.is_empty());
let mut small = make_set(&[(0, 5)]);
let chunks: Vec<FrozenRangeSet> = small.into_chunks(10).collect();
assert_eq!(chunks.len(), 1);
assert_eq!(chunks[0][0], Range::new(0, 5));
let mut large = make_set(&[(0, 25)]);
let chunks: Vec<FrozenRangeSet> = large.into_chunks(10).collect();
assert_eq!(chunks.len(), 3);
assert_eq!(chunks[0][0], Range::new(0, 9));
assert_eq!(chunks[1][0], Range::new(10, 19));
assert_eq!(chunks[2][0], Range::new(20, 25));
let mut set = make_set(&[(0, 2)]);
let chunks: Vec<FrozenRangeSet> = set.into_chunks(1).collect();
assert_eq!(chunks.len(), 3);
}
#[test]
fn test_insert_range_return_value() {
let mut set = RangeSet::new();
assert!(set.insert_range(&Range::new(0, 10)));
assert!(!set.insert_range(&Range::new(0, 10)));
assert!(!set.insert_range(&Range::new(2, 8)));
assert!(set.insert_range(&Range::new(5, 15)));
check_ranges(&set, &[(0, 15)]);
}
#[test]
fn test_range_boundary_values() {
let max_range = Range::new(0, usize::MAX - 1);
assert_eq!(max_range.start(), 0);
assert_eq!(max_range.last(), usize::MAX - 1);
assert_eq!(max_range.len(), usize::MAX);
let high_range = Range::new(usize::MAX - 10, usize::MAX - 1);
assert_eq!(high_range.len(), 10);
assert!(high_range.contains_n(usize::MAX - 5));
assert!(!high_range.contains_n(usize::MAX));
let single_max = Range::new(usize::MAX - 1, usize::MAX - 1);
assert_eq!(single_max.len(), 1);
assert!(single_max.contains_n(usize::MAX - 1));
let zero_range = Range::new(0, 0);
assert_eq!(zero_range.len(), 1);
assert_eq!(zero_range.start(), 0);
assert_eq!(zero_range.last(), 0);
}
#[test]
#[should_panic(expected = "last must be less than usize::MAX")]
fn test_range_new_with_usize_max() {
let _ = Range::new(0, usize::MAX);
}
#[test]
#[should_panic(expected = "last must be less than usize::MAX")]
fn test_range_new_both_usize_max() {
let _ = Range::new(usize::MAX, usize::MAX);
}
#[test]
fn test_range_operations_with_boundary_values() {
let r1 = Range::new(usize::MAX - 20, usize::MAX - 10);
let r2 = Range::new(usize::MAX - 15, usize::MAX - 5);
let intersection = r1.intersection(&r2).unwrap();
assert_eq!(intersection.start(), usize::MAX - 15);
assert_eq!(intersection.last(), usize::MAX - 10);
let union = r1.union(&r2).unwrap();
assert_eq!(union.start(), usize::MAX - 20);
assert_eq!(union.last(), usize::MAX - 5);
let r3 = Range::new(usize::MAX - 10, usize::MAX - 6);
let r4 = Range::new(usize::MAX - 5, usize::MAX - 1);
assert!(r3.is_adjacent(&r4));
let large = Range::new(usize::MAX - 100, usize::MAX - 1);
let mid = large.midpoint();
assert!(mid >= usize::MAX - 100 && mid <= usize::MAX - 1);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_insert_n_at_overflow() {
let mut set = RangeSet::new();
set.insert_n_at(100, usize::MAX - 1);
}
#[test]
fn test_insert_n_at_boundary() {
let mut set = RangeSet::new();
set.insert_n_at(0, 0);
assert!(set.is_empty());
set.insert_n_at(1, usize::MAX - 2);
check_ranges(&set, &[(usize::MAX - 2, usize::MAX - 2)]);
let mut set2 = RangeSet::new();
set2.insert_n_at(10, usize::MAX - 20);
check_ranges(&set2, &[(usize::MAX - 20, usize::MAX - 11)]);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_chunks_zero_block_size() {
let mut set = make_set(&[(0, 10)]);
let _ = set.into_chunks(0).collect::<Vec<_>>();
}
#[test]
fn test_rangeset_with_maximum_values() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(usize::MAX - 100, usize::MAX - 50));
assert_eq!(set.len(), 51);
assert!(set.contains_n(usize::MAX - 75));
assert!(!set.contains_n(usize::MAX - 49));
set.insert_range(&Range::new(usize::MAX - 40, usize::MAX - 1));
assert_eq!(set.ranges_count(), 2);
set.insert_range(&Range::new(usize::MAX - 50, usize::MAX - 40));
check_ranges(&set, &[(usize::MAX - 100, usize::MAX - 1)]);
}
#[test]
fn test_rangeset_contains_with_boundaries() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(0, 10));
set.insert_range(&Range::new(usize::MAX - 10, usize::MAX - 1));
assert!(set.contains_n(0));
assert!(set.contains_n(10));
assert!(!set.contains_n(11));
assert!(set.contains_n(usize::MAX - 10));
assert!(set.contains_n(usize::MAX - 1));
assert!(!set.contains_n(usize::MAX - 11));
assert!(set.contains(&Range::new(0, 10)));
assert!(set.contains(&Range::new(0, 5)));
assert!(!set.contains(&Range::new(0, 11)));
assert!(set.contains(&Range::new(usize::MAX - 10, usize::MAX - 1)));
assert!(!set.contains(&Range::new(usize::MAX - 11, usize::MAX - 1)));
}
#[test]
fn test_frozen_with_extreme_values() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(0, 0));
set.insert_range(&Range::new(usize::MAX / 2, usize::MAX / 2 + 100));
set.insert_range(&Range::new(usize::MAX - 1, usize::MAX - 1));
let frozen = set.freeze();
assert_eq!(frozen.start(), Some(0));
assert_eq!(frozen.last(), Some(usize::MAX - 1));
assert_eq!(frozen.ranges_count(), 3);
assert!(frozen.contains_n(0));
assert!(frozen.contains_n(usize::MAX / 2 + 50));
assert!(frozen.contains_n(usize::MAX - 1));
assert!(!frozen.contains_n(1));
}
#[test]
fn test_union_with_extreme_gaps() {
let set1 = make_set(&[(0, 10)]);
let set2 = make_set(&[(usize::MAX - 10, usize::MAX - 1)]);
let union = set1.union(&set2);
assert_eq!(union.ranges_count(), 2);
check_ranges(&union, &[(0, 10), (usize::MAX - 10, usize::MAX - 1)]);
let merged = set1.union_merge(&set2);
check_ranges(&merged, &[(0, 10), (usize::MAX - 10, usize::MAX - 1)]);
}
#[test]
fn test_difference_with_extreme_values() {
let large = make_set(&[(0, usize::MAX - 1)]);
let small = make_set(&[(usize::MAX / 2 - 5, usize::MAX / 2 + 5)]);
let diff = large.difference(&small);
assert_eq!(diff.ranges_count(), 2);
assert_eq!(diff.start(), Some(0));
assert_eq!(diff.last(), Some(usize::MAX - 1));
assert!(!diff.contains_n(usize::MAX / 2));
assert!(diff.contains_n(usize::MAX / 2 - 6));
assert!(diff.contains_n(usize::MAX / 2 + 6));
}
#[test]
fn test_chunks_with_extreme_ranges() {
let mut set = make_set(&[(usize::MAX - 100, usize::MAX - 1)]);
let chunks: Vec<_> = set.into_chunks(25).collect();
assert_eq!(chunks.len(), 4);
let total: usize = chunks.iter().map(|c| c.iter().map(|r| r.len()).sum::<usize>()).sum();
assert_eq!(total, 100);
}
#[test]
fn test_range_edge_case_operations() {
let r1 = Range::new(0, 5);
let r2 = Range::new(6, 10);
assert!(r1.is_adjacent(&r2));
assert!(r2.is_adjacent(&r1));
let r3 = Range::new(0, 3);
let r4 = Range::new(5, 10);
assert!(!r3.is_adjacent(&r4));
let r5 = Range::new(0, 10);
let r6 = Range::new(10, 20);
assert!(r5.intersects(&r6));
let r7 = Range::new(5, 10);
let r8 = Range::new(5, 10);
assert_eq!(r7.difference(&r8), (None, None));
let r9 = Range::new(0, 10);
let r10 = Range::new(0, 0);
let (left, right) = r9.difference(&r10);
assert_eq!(left, None);
assert_eq!(right, Some(Range::new(1, 10)));
}
#[test]
fn test_rangeset_stress_many_ranges() {
let mut set = RangeSet::new();
for i in (0..1000).step_by(2) {
set.insert_range(&Range::new(i, i));
}
assert_eq!(set.ranges_count(), 500);
assert_eq!(set.len(), 500);
for i in (1..1000).step_by(2) {
set.insert_range(&Range::new(i, i));
}
assert_eq!(set.ranges_count(), 1);
check_ranges(&set, &[(0, 999)]);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_range_new_unchecked_panic_order() {
let _ = unsafe { Range::new_unchecked(20, 10) };
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "last must be less than usize::MAX")]
fn test_range_new_unchecked_panic_max() {
let _ = unsafe { Range::new_unchecked(0, usize::MAX) };
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_insert_n_at_unchecked_overflow() {
let mut set = RangeSet::new();
unsafe { set.insert_n_at_unchecked(100, usize::MAX - 1) };
}
#[test]
fn test_range_len_calculation() {
let r = Range::new(0, usize::MAX - 1);
assert_eq!(r.len(), usize::MAX);
let r2 = Range::new(usize::MAX - 10, usize::MAX - 1);
assert_eq!(r2.len(), 10);
}
#[test]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_range_from_tuple_invalid_order() {
let _ = Range::from((100, 50));
}
#[test]
fn test_range_contains_boundary() {
let r = Range::new(10, 20);
assert!(r.contains_n(10));
assert!(r.contains_n(20));
assert!(!r.contains_n(9));
assert!(!r.contains_n(21));
let r2 = Range::new(0, usize::MAX - 1);
assert!(r2.contains_n(0));
assert!(r2.contains_n(usize::MAX - 1));
assert!(!r2.contains_n(usize::MAX));
}
#[test]
fn test_rangeset_insert_range_boundary_merge() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(0, 5));
set.insert_range(&Range::new(6, 10)); check_ranges(&set, &[(0, 10)]);
set.insert_range(&Range::new(11, 20));
check_ranges(&set, &[(0, 20)]);
let mut set2 = RangeSet::new();
set2.insert_range(&Range::new(usize::MAX - 10, usize::MAX - 5));
set2.insert_range(&Range::new(usize::MAX - 4, usize::MAX - 1));
check_ranges(&set2, &[(usize::MAX - 10, usize::MAX - 1)]);
}
#[test]
fn test_range_intersection_no_overlap() {
let r1 = Range::new(0, 10);
let r2 = Range::new(11, 20);
assert!(r1.intersection(&r2).is_none());
assert!(r2.intersection(&r1).is_none());
let r3 = Range::new(0, 10);
let r4 = Range::new(10, 20);
assert!(r3.intersection(&r4).is_some()); }
#[test]
fn test_range_union_non_adjacent() {
let r1 = Range::new(0, 10);
let r2 = Range::new(12, 20);
assert!(r1.union(&r2).is_none());
assert!(r2.union(&r1).is_none());
let r3 = Range::new(0, 10);
let r4 = Range::new(11, 20);
assert!(r3.union(&r4).is_some());
}
#[test]
fn test_rangeset_difference_no_overlap() {
let set1 = make_set(&[(0, 10)]);
let set2 = make_set(&[(20, 30)]);
let diff = set1.difference(&set2);
check_ranges(&diff, &[(0, 10)]);
let diff2 = set2.difference(&set1);
check_ranges(&diff2, &[(20, 30)]); }
#[test]
fn test_rangeset_union_empty_combinations() {
let empty = RangeSet::new();
let non_empty = make_set(&[(0, 10)]);
let result = empty.union(&empty);
assert!(result.is_empty());
let result = empty.union(&non_empty);
check_ranges(&result, &[(0, 10)]);
let result = non_empty.union(&empty);
check_ranges(&result, &[(0, 10)]);
}
#[test]
fn test_frozen_start_last_none() {
let empty = RangeSet::new().freeze();
assert_eq!(empty.start(), None);
assert_eq!(empty.last(), None);
let non_empty = make_set(&[(5, 15), (20, 30)]).freeze();
assert_eq!(non_empty.start(), Some(5));
assert_eq!(non_empty.last(), Some(30));
}
#[test]
fn test_rangeset_contains_edge_cases() {
let mut set = RangeSet::new();
assert!(!set.contains_n(0));
assert!(!set.contains(&Range::new(0, 10)));
set.insert_range(&Range::new(5, 5));
assert!(set.contains_n(5));
assert!(!set.contains_n(4));
assert!(!set.contains_n(6));
assert!(set.contains(&Range::new(5, 5)));
assert!(!set.contains(&Range::new(4, 5)));
assert!(!set.contains(&Range::new(5, 6)));
}
#[test]
fn test_range_midpoint_edge_cases() {
let r = Range::new(5, 5);
assert_eq!(r.midpoint(), 5);
let r = Range::new(5, 6);
assert_eq!(r.midpoint(), 5);
let r = Range::new(usize::MAX - 100, usize::MAX - 1);
let mid = r.midpoint();
assert!(mid >= usize::MAX - 100 && mid <= usize::MAX - 1);
assert_eq!(mid, usize::MAX - 100 + 49); }
#[test]
fn test_rangeset_multiple_operations_chain() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(0, 10));
set.insert_range(&Range::new(20, 30));
let set2 = make_set(&[(5, 25)]);
let union = set.union(&set2);
check_ranges(&union, &[(0, 30)]);
let set3 = make_set(&[(8, 12)]);
let diff = union.difference(&set3);
check_ranges(&diff, &[(0, 7), (13, 30)]);
let frozen = diff.freeze();
let thawed: RangeSet = frozen.into();
check_ranges(&thawed, &[(0, 7), (13, 30)]);
}
#[test]
fn test_range_is_empty_always_false() {
let r1 = Range::new(0, 0);
assert!(!r1.is_empty());
let r2 = Range::new(10, 20);
assert!(!r2.is_empty());
let r3 = Range::new(usize::MAX - 1, usize::MAX - 1);
assert!(!r3.is_empty());
}
#[cfg(feature = "http")]
#[test]
fn test_http_with_boundary_values() {
let total_size = usize::MAX / 2;
let result = RangeSet::parse_ranges_headers(&format!("bytes=0-{}", total_size - 1), total_size).unwrap();
assert_eq!(result.len(), total_size);
let result =
RangeSet::parse_ranges_headers(&format!("bytes={}-{}", total_size - 1, total_size - 1), total_size)
.unwrap();
check_ranges(&result, &[(total_size - 1, total_size - 1)]);
let result = RangeSet::parse_ranges_headers(&format!("bytes=-{}", total_size), total_size).unwrap();
check_ranges(&result, &[(0, total_size - 1)]);
}
#[test]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_range_new_panic_reversed_large_values() {
let _ = Range::new(usize::MAX - 1, usize::MAX - 10);
}
#[test]
#[should_panic(expected = "last must be less than usize::MAX")]
fn test_range_new_panic_last_is_max_zero_start() {
let _ = Range::new(0, usize::MAX);
}
#[test]
#[should_panic(expected = "last must be less than usize::MAX")]
fn test_range_new_panic_last_is_max_large_start() {
let _ = Range::new(usize::MAX - 100, usize::MAX);
}
#[test]
#[should_panic]
fn test_insert_n_at_panic_overflow_exact_max() {
let mut set = RangeSet::new();
set.insert_n_at(2, usize::MAX - 1);
}
#[test]
#[should_panic]
fn test_insert_n_at_panic_overflow_exceed_max() {
let mut set = RangeSet::new();
set.insert_n_at(10, usize::MAX - 5);
}
#[test]
#[should_panic]
fn test_insert_n_at_panic_large_n_at_boundary() {
let mut set = RangeSet::new();
set.insert_n_at(usize::MAX / 2, usize::MAX / 2 + 1);
}
#[test]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_from_tuple_panic_small_difference() {
let _ = Range::from((2, 1));
}
#[test]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_from_tuple_panic_zero_vs_max() {
let _ = Range::from((usize::MAX - 1, 0));
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "last must be less than usize::MAX")]
fn test_new_unchecked_panic_last_equals_max_in_debug() {
let _ = unsafe { Range::new_unchecked(usize::MAX - 10, usize::MAX) };
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "start must be less than or equal to last")]
fn test_new_unchecked_panic_reversed_in_debug() {
let _ = unsafe { Range::new_unchecked(100, 50) };
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_insert_n_at_unchecked_panic_overflow_in_debug() {
let mut set = RangeSet::new();
unsafe {
set.insert_n_at_unchecked(100, usize::MAX - 50);
}
}
#[test]
fn test_range_try_from_empty_range() {
let empty = 0..0;
assert!(Range::try_from(&empty).is_err());
}
#[test]
fn test_range_operations_no_panic_with_valid_boundaries() {
let r1 = Range::new(0, usize::MAX - 1);
assert_eq!(r1.len(), usize::MAX);
assert!(r1.contains_n(0));
assert!(r1.contains_n(usize::MAX - 1));
let r2 = Range::new(usize::MAX - 2, usize::MAX - 1);
assert_eq!(r2.len(), 2);
assert_eq!(r2.midpoint(), usize::MAX - 2);
let r3 = Range::new(0, 100);
let r4 = Range::new(50, usize::MAX - 1);
assert!(r3.intersects(&r4));
let intersection = r3.intersection(&r4).unwrap();
assert_eq!(intersection.start(), 50);
assert_eq!(intersection.last(), 100);
}
#[test]
fn test_rangeset_operations_no_panic_near_max() {
let mut set = RangeSet::new();
set.insert_range(&Range::new(usize::MAX - 100, usize::MAX - 50));
set.insert_range(&Range::new(usize::MAX - 49, usize::MAX - 1));
assert_eq!(set.ranges_count(), 1);
assert_eq!(set.len(), 100); assert!(set.contains_n(usize::MAX - 75));
assert!(set.contains_n(usize::MAX - 1));
check_ranges(&set, &[(usize::MAX - 100, usize::MAX - 1)]);
let frozen = set.freeze();
assert_eq!(frozen.ranges_count(), 1); let total_elements: usize = frozen.iter().map(|r| r.len()).sum();
assert_eq!(total_elements, 100);
assert!(frozen.contains_n(usize::MAX - 50));
}
#[test]
fn test_insert_n_at_valid_at_near_max() {
let mut set = RangeSet::new();
set.insert_n_at(1, usize::MAX - 2);
check_ranges(&set, &[(usize::MAX - 2, usize::MAX - 2)]);
let mut set2 = RangeSet::new();
set2.insert_n_at(10, usize::MAX - 20);
check_ranges(&set2, &[(usize::MAX - 20, usize::MAX - 11)]);
let mut set3 = RangeSet::new();
set3.insert_n_at(usize::MAX - 100, 0);
check_ranges(&set3, &[(0, usize::MAX - 101)]);
}
}