use core::{
cmp::min,
ops::{Add, Bound, Index, IndexMut, RangeBounds},
};
#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Range {
pub start: usize,
pub end: usize,
}
impl Range {
#[inline(always)]
pub const fn new(start: usize, end: usize) -> Self {
debug_assert!(start <= end);
Self { start, end }
}
#[inline(always)]
pub const fn to(end: usize) -> Self {
Self { start: 0, end }
}
#[inline(always)]
pub const fn len(&self) -> usize {
debug_assert!(self.end <= self.start);
self.end - self.start
}
#[inline(always)]
pub const fn as_core(&self) -> core::ops::Range<usize> {
core::ops::Range { start: self.start, end: self.end }
}
#[inline(always)]
pub const fn from_core(r: core::ops::Range<usize>) -> Self {
Self { start: r.start, end: r.end }
}
}
impl core::fmt::Display for Range {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
impl Add<Range> for Range {
type Output = Range;
fn add(self, rhs: Range) -> Self::Output {
Self { start: min(self.start, rhs.start), end: self.len() + rhs.len() }
}
}
impl Add<usize> for Range {
type Output = Range;
fn add(self, rhs: usize) -> Self::Output {
Self { start: self.start, end: self.end + rhs }
}
}
impl Index<Range> for [u8] {
type Output = [u8];
fn index(&self, range: Range) -> &[u8] {
&self[range.start..range.end]
}
}
impl IndexMut<Range> for [u8] {
fn index_mut(&mut self, range: Range) -> &mut Self::Output {
&mut self[range.start..range.end]
}
}
impl RangeBounds<usize> for Range {
#[inline]
fn start_bound(&self) -> Bound<&usize> {
Bound::Included(&self.start)
}
#[inline]
fn end_bound(&self) -> Bound<&usize> {
Bound::Excluded(&self.end)
}
}
impl PartialOrd for Range {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.len().partial_cmp(&other.len())
}
}
impl From<Range> for (usize, usize) {
#[inline(always)]
fn from(r: Range) -> Self {
(r.start, r.end)
}
}
impl From<(usize, usize)> for Range {
#[inline(always)]
fn from(v: (usize, usize)) -> Self {
Self { start: v.0, end: v.1 }
}
}
impl From<core::ops::Range<usize>> for Range {
#[inline(always)]
fn from(r: core::ops::Range<usize>) -> Self {
Self::from_core(r)
}
}
impl From<Range> for core::ops::Range<usize> {
#[inline(always)]
fn from(r: Range) -> Self {
r.as_core()
}
}