#[cfg(feature = "alloc")]
extern crate alloc;
mod util;
use core::{
hash::{Hash, Hasher},
ops::{Index, IndexMut, Range},
};
use util::RustNumber;
#[repr(C)]
pub struct Span<T: RustNumber = usize> {
pub start: T,
pub end: T,
}
impl<T: RustNumber> Clone for Span<T> {
fn clone(&self) -> Self {
Self {
start: self.start,
end: self.end,
}
}
}
impl<T: RustNumber> Copy for Span<T> {}
impl<T: RustNumber> Span<T> {
#[must_use]
pub const fn span_after(self) -> Self {
Self {
start: self.end,
end: self.end,
}
}
#[must_use]
pub const fn span_at(self) -> Self {
Self {
start: self.start,
end: self.start,
}
}
#[must_use]
pub fn with_len(self, len: T) -> Self {
Self {
start: self.start,
end: self.start + len,
}
}
#[must_use]
pub const fn with_start(self, start: T) -> Self {
Self {
start,
end: self.end,
}
}
#[must_use]
pub const fn with_end(self, end: T) -> Self {
Self {
start: self.start,
end,
}
}
#[must_use]
pub const fn at(pos: T) -> Self {
Self {
start: pos,
end: pos,
}
}
#[must_use]
pub fn contains(&self, elem: T) -> bool {
self.range().contains(&elem)
}
#[must_use]
pub fn is_empty(&self) -> bool {
&self.start == &self.end
}
#[must_use]
pub fn overlaps_with(&self, other: Self) -> bool {
self.contains(other.start) || other.contains(self.start)
}
#[must_use]
pub const fn range(self) -> Range<T> {
Range {
start: self.start,
end: self.end,
}
}
}
#[cfg(feature = "alloc")]
mod alloc_impl {
use crate::util::RustNumber;
use alloc::fmt::Debug;
use super::Span;
impl<T: RustNumber> Debug for Span<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
Debug::fmt(&self.range(), f)
}
}
}
impl<T: RustNumber> Hash for Span<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&self.range(), state)
}
}
impl<T: RustNumber> PartialEq for Span<T> {
fn eq(&self, other: &Self) -> bool {
self.range().eq(&other.range())
}
}
impl<T: RustNumber> Eq for Span<T> {}
impl<T: RustNumber> From<Range<T>> for Span<T> {
fn from(value: Range<T>) -> Self {
Span {
start: value.start,
end: value.end,
}
}
}
impl<T: RustNumber> From<Span<T>> for Range<T> {
fn from(value: Span<T>) -> Self {
value.range()
}
}
impl<U> Index<Span<usize>> for [U] {
type Output = [U];
fn index(&self, index: Span<usize>) -> &Self::Output {
&self[index.range()]
}
}
impl<U> IndexMut<Span<usize>> for [U] {
fn index_mut(&mut self, index: Span<usize>) -> &mut Self::Output {
&mut self[index.range()]
}
}
impl Index<Span<usize>> for str {
type Output = str;
fn index(&self, index: Span<usize>) -> &Self::Output {
&self[index.range()]
}
}
impl IndexMut<Span<usize>> for str {
fn index_mut(&mut self, index: Span<usize>) -> &mut Self::Output {
&mut self[index.range()]
}
}
impl<T: RustNumber> IntoIterator for Span<T>
where
Range<T>: Iterator<Item = T>,
{
type Item = T;
type IntoIter = Range<T>;
fn into_iter(self) -> Self::IntoIter {
self.into()
}
}
impl<T: RustNumber> Default for Span<T> {
fn default() -> Self {
Self::from(T::default()..T::default())
}
}