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