use super::*;
use core::{cmp::Ordering, ops::*};
#[repr(C)]
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
pub struct Span<T, U = T> {
pub start: T,
pub count: U,
}
impl<T, U> Span<T, U> {
#[inline(always)]
pub const fn new(start: T, count: U) -> Self {
Self { start, count }
}
#[inline(always)]
pub fn is_empty(&self) -> bool
where
T: Copy + PartialEq + Add<U, Output = T>,
U: Copy,
{
self.start + self.count == self.start
}
}
impl<T, U> Span<T, U>
where
Span<T, U>: Into<Line<T>> + From<Line<T>>,
T: PartialOrd,
{
pub fn intersection(self, other: Self) -> Option<Self> {
self.into().intersection(other.into()).map(|x| x.into())
}
}
impl<T: Add<T, Output = T>> Add<T> for Span<T> {
type Output = Self;
#[inline(always)]
fn add(self, rhs: T) -> Self::Output {
Self {
start: self.start,
count: self.count + rhs,
}
}
}
impl<T: AddAssign<T>> AddAssign<T> for Span<T> {
#[inline(always)]
fn add_assign(&mut self, rhs: T) {
self.count += rhs;
}
}
impl<T: Sub<T, Output = T>> Sub<T> for Span<T> {
type Output = Self;
#[inline(always)]
fn sub(self, rhs: T) -> Self::Output {
Self {
start: self.start,
count: self.count - rhs,
}
}
}
impl<T: SubAssign<T>> SubAssign<T> for Span<T> {
#[inline(always)]
fn sub_assign(&mut self, rhs: T) {
self.count -= rhs;
}
}
impl<T: Copy + Sub<T, Output = T>> Shl<T> for Span<T> {
type Output = Self;
#[inline(always)]
#[allow(clippy::suspicious_arithmetic_impl)]
fn shl(self, rhs: T) -> Self::Output {
Self {
start: self.start - rhs,
count: self.count,
}
}
}
impl<T: Copy + SubAssign<T>> ShlAssign<T> for Span<T> {
#[inline(always)]
#[allow(clippy::suspicious_op_assign_impl)]
fn shl_assign(&mut self, rhs: T) {
self.start -= rhs;
}
}
impl<T: Copy + Add<T, Output = T>> Shr<T> for Span<T> {
type Output = Self;
#[inline(always)]
#[allow(clippy::suspicious_arithmetic_impl)]
fn shr(self, rhs: T) -> Self::Output {
Self {
start: self.start + rhs,
count: self.count,
}
}
}
impl<T: Copy + AddAssign<T>> ShrAssign<T> for Span<T> {
#[inline(always)]
#[allow(clippy::suspicious_op_assign_impl)]
fn shr_assign(&mut self, rhs: T) {
self.start += rhs;
}
}
impl<T: PartialEq, U: PartialEq> PartialOrd for Span<T, U>
where
Span<T, U>: Copy + Into<Line<T>>,
Line<T>: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(*self).into().partial_cmp(&(*other).into())
}
}
impl<T: Copy + Sub<T, Output = U>, U> From<Range<T>> for Span<T, U> {
#[inline(always)]
fn from(value: Range<T>) -> Self {
Self {
start: value.start,
count: value.end - value.start,
}
}
}
impl<T: Clone + Add<U, Output = T>, U> From<Span<T, U>> for Range<T> {
#[inline(always)]
fn from(value: Span<T, U>) -> Self {
Self {
start: value.start.clone(),
end: value.start + value.count,
}
}
}
impl<T: Clone + Sub<T, Output = U>, U> From<Line<T>> for Span<T, U> {
#[inline(always)]
fn from(value: Line<T>) -> Self {
Self {
start: value.start.clone(),
count: value.end - value.start,
}
}
}
impl<T, U> Contains<T> for Span<T, U>
where
Self: Into<Line<T>> + Clone,
Line<T>: Contains<T>,
{
#[inline(always)]
fn contains(&self, value: &T) -> bool {
self.clone().into().contains(value)
}
}
impl<T, U> Contains<Self> for Span<T, U>
where
Self: Into<Line<T>> + Clone,
T: PartialOrd,
{
#[inline(always)]
fn contains(&self, value: &Self) -> bool {
self.clone().into().contains(&value.clone().into())
}
}
impl<T, U> Split<Self> for Span<T, U>
where
Self: Into<Line<T>>,
Line<T>: Into<Self>,
Line<T>: Split<Line<T>>,
{
#[inline(always)]
fn split(self, at: Self) -> Option<(Self, Self)> {
let (l, r) = self.into().split(at.into())?;
Some((l.into(), r.into()))
}
}
impl<T, U> Split<U> for Span<T, U>
where
T: Add<U, Output = T> + Clone,
Line<T>: Split<T> + Into<Self>,
Self: Into<Line<T>>,
{
#[inline(always)]
fn split(self, at: U) -> Option<(Self, Self)> {
let e = self.start.clone() + at;
let (l, r) = self.into().split(e)?;
Some((l.into(), r.into()))
}
}