use std::ops::Neg;
use crate::{EdgeDirection, VertexDirection};
#[derive(Debug)]
pub enum DirectionWay<T> {
Single(T),
Tie([T; 2]),
}
pub trait Way: Copy + Neg<Output = Self> {
fn ccw(self) -> Self;
fn cw(self) -> Self;
}
impl<T: PartialEq> PartialEq<T> for DirectionWay<T> {
fn eq(&self, other: &T) -> bool {
self.contains(other)
}
}
impl<T> DirectionWay<T> {
#[inline]
#[must_use]
pub fn unwrap(self) -> T {
match self {
Self::Single(v) | Self::Tie([v, _]) => v,
}
}
#[inline]
#[must_use]
pub fn contains(&self, dir: &T) -> bool
where
T: PartialEq,
{
match self {
Self::Single(d) => d.eq(dir),
Self::Tie([a, b]) => a.eq(dir) || b.eq(dir),
}
}
#[inline]
#[must_use]
pub fn map<U>(self, mut func: impl FnMut(T) -> U) -> DirectionWay<U> {
match self {
Self::Single(v) => DirectionWay::Single(func(v)),
Self::Tie(v) => DirectionWay::Tie(v.map(func)),
}
}
}
impl<T: Way> DirectionWay<T> {
#[inline]
pub(crate) fn way_from(is_neg: bool, eq_left: bool, eq_right: bool, dir: T) -> Self {
let dir = if is_neg { -dir } else { dir };
match [eq_left, eq_right] {
[true, _] => Self::Tie([dir, dir.ccw()]),
[_, true] => Self::Tie([dir, dir.cw()]),
_ => Self::Single(dir),
}
}
}
impl<T> From<T> for DirectionWay<T> {
#[inline]
fn from(value: T) -> Self {
Self::Single(value)
}
}
impl<T> From<[T; 2]> for DirectionWay<T> {
#[inline]
fn from(value: [T; 2]) -> Self {
Self::Tie(value)
}
}
impl Way for EdgeDirection {
#[inline]
fn ccw(self) -> Self {
self.counter_clockwise()
}
#[inline]
fn cw(self) -> Self {
self.clockwise()
}
}
impl Way for VertexDirection {
#[inline]
fn ccw(self) -> Self {
self.counter_clockwise()
}
#[inline]
fn cw(self) -> Self {
self.clockwise()
}
}