#![no_std]
pub mod concepts;
pub mod either;
pub mod both;
use core::ops::{BitAnd, BitOr, Not};
pub use crate::{
any_of_x::{AnyOf16, AnyOf4, AnyOf8},
both::Both,
concepts::{Any, Couple, LeftOrRight, Map, Pair, Swap, Unwrap},
either::Either,
};
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub enum AnyOf<L, R = L> {
Neither,
Either(Either<L, R>),
Both(Both<L, R>),
}
impl<L, R> AnyOf<L, R> {
pub fn new(left: Option<L>, right: Option<R>) -> Self {
match (left, right) {
(None, None) => Self::Neither,
(Some(l), None) => Self::Either(Either::Left(l)),
(None, Some(r)) => Self::Either(Either::Right(r)),
(Some(l), Some(r)) => Self::Both(Both { left: l, right: r }),
}
}
pub fn new_neither() -> Self {
Self::new(None, None)
}
pub fn new_left(left: L) -> Self {
Self::new(Some(left), None)
}
pub fn new_right(right: R) -> Self {
Self::new(None, Some(right))
}
pub fn new_both(l: L, r: R) -> Self {
Self::new(Some(l), Some(r))
}
pub fn from_both(both: Both<L, R>) -> Self {
Self::new(Some(both.left), Some(both.right))
}
pub fn from_any(any: Any<L, R>) -> Self {
Self::new(any.0, any.1)
}
pub fn from_either(either: Either<L, R>) -> Self {
Self::Either(either)
}
pub fn into_both(self) -> Both<L, R> {
match self {
AnyOf::Both(b) => b,
_ => panic!("Can only convert Either::Both to Both"),
}
}
pub fn into_either(self) -> Either<L, R> {
if let AnyOf::Either(e) = self {
e
} else {
panic!("Can only convert Either::Either to Either");
}
}
pub fn to_either_pair(&self) -> Pair<Option<Either<L, R>>>
where
L: Clone,
R: Clone,
{
let both = self.any();
let left = both.0.map(|l| Either::Left(l.clone()));
let right = both.1.map(|r| Either::Right(r.clone()));
(left, right)
}
pub fn has_left(&self) -> bool {
matches!(self, Self::Either(Either::Left(_)) | Self::Both(_))
}
pub fn has_right(&self) -> bool {
matches!(self, Self::Either(Either::Right(_)) | Self::Both(_))
}
pub fn is_any(&self) -> bool {
matches!(
self,
Self::Either(Either::Left(_)) | Self::Either(Either::Right(_)) | Self::Both(_)
)
}
#[deprecated(since = "1.3.1", note = "Use `is_either` instead. Will be removed in 2.0.0.")]
pub fn is_one(&self) -> bool {
self.is_either()
}
pub fn is_either(&self) -> bool {
matches!(self, Self::Either(_))
}
pub fn is_both(&self) -> bool {
matches!(self, Self::Both(_))
}
pub fn is_neither(&self) -> bool {
matches!(self, Self::Neither)
}
pub fn is_neither_or_both(&self) -> bool {
matches!(self, Self::Neither | Self::Both(_))
}
pub fn both_or_none(&self) -> Option<Couple<&L, &R>> {
Some((self.left()?, self.right()?))
}
pub fn both_or_else(self, f: impl FnOnce() -> Both<L, R>) -> Both<L, R> {
match self {
Self::Neither => f(),
Self::Either(Either::Left(l)) => Both::new(l, f().right),
Self::Either(Either::Right(r)) => Both::new(f().left, r),
Self::Both(b) => b,
}
}
pub fn both_or(self, other: Both<L, R>) -> Both<L, R> {
self.both_or_else(|| other)
}
pub fn unwrap_both(self) -> Both<L, R> {
self.both_or_else(|| panic!("Can only unwrap both of Either::Both"))
}
pub fn filter_left(self) -> Self {
match self {
Self::Neither => Self::Neither,
Self::Either(Either::Left(l)) => Self::Either(Either::Left(l)),
Self::Either(Either::Right(_)) => Self::Neither,
Self::Both(Both { left: l, .. }) => Self::Either(Either::Left(l)),
}
}
pub fn filter_right(self) -> Self {
match self {
Self::Neither => Self::Neither,
Self::Either(Either::Left(_)) => Self::Neither,
Self::Either(Either::Right(r)) => Self::Either(Either::Right(r)),
Self::Both(Both { right: r, .. }) => Self::Either(Either::Right(r)),
}
}
pub fn with_right(self, right: R) -> Self {
match self {
Self::Neither => Self::Either(Either::Right(right)),
Self::Either(Either::Left(l)) => Self::Both(Both { left: l, right }),
Self::Either(Either::Right(_)) => Self::Either(Either::Right(right)),
Self::Both(Both { left: l, .. }) => Self::Both(Both { left: l, right }),
}
}
pub fn with_left(self, left: L) -> Self {
match self {
Self::Neither => Self::Either(Either::Left(left)),
Self::Either(Either::Left(_)) => Self::Either(Either::Left(left)),
Self::Either(Either::Right(r)) => Self::Both(Both { left, right: r }),
Self::Both(Both { right: r, .. }) => Self::Both(Both { left, right: r }),
}
}
pub fn combine(self, other: Self) -> Self {
match self {
Self::Neither => other,
Self::Either(Either::Left(l)) => match other {
AnyOf::Neither => Self::Either(Either::Left(l)),
AnyOf::Either(Either::Left(_)) => Self::Either(Either::Left(l)),
AnyOf::Either(Either::Right(r)) => Self::Both(Both { left: l, right: r }),
AnyOf::Both(Both { right: r, .. }) => Self::Both(Both { left: l, right: r }),
},
Self::Either(Either::Right(r)) => match other {
AnyOf::Neither => Self::Either(Either::Right(r)),
AnyOf::Either(Either::Left(l)) => Self::Both(Both { left: l, right: r }),
AnyOf::Either(Either::Right(r2)) => Self::Either(Either::Right(r2)),
AnyOf::Both(Both { left: l, .. }) => Self::Both(Both { left: l, right: r }),
},
Self::Both(b) => Self::Both(b),
}
}
pub fn filter(self, other: Self) -> Self {
match other {
AnyOf::Neither => self,
AnyOf::Either(Either::Left(_)) => match self {
AnyOf::Either(Either::Left(_)) => AnyOf::Neither,
AnyOf::Either(Either::Right(r)) => AnyOf::Either(Either::Right(r)),
AnyOf::Both(Both { right: r, .. }) => AnyOf::Either(Either::Right(r)),
_ => self,
},
AnyOf::Either(Either::Right(_)) => match self {
AnyOf::Either(Either::Left(l)) => AnyOf::Either(Either::Left(l)),
AnyOf::Either(Either::Right(_)) => AnyOf::Neither,
AnyOf::Both(Both { left: l, .. }) => AnyOf::Either(Either::Left(l)),
_ => self,
},
AnyOf::Both(_) => AnyOf::Neither,
}
}
}
impl<L, R> BitAnd for AnyOf<L, R> {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
self.combine(rhs)
}
}
impl<L, R> BitOr for AnyOf<L, R> {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
self.filter(rhs)
}
}
impl<L, R> Not for AnyOf<L, R> {
type Output = AnyOf<R, L>;
fn not(self) -> Self::Output {
self.swap()
}
}
impl<L, R> LeftOrRight<L, R> for AnyOf<L, R> {
fn left(&self) -> Option<&L> {
match self {
Self::Neither => None,
Self::Either(e) => e.left(),
Self::Both(b) => b.left(),
}
}
fn right(&self) -> Option<&R> {
match self {
Self::Neither => None,
Self::Either(e) => e.right(),
Self::Both(b) => b.right(),
}
}
}
impl<L, R> Swap<L, R> for AnyOf<L, R> {
type Output = AnyOf<R, L>;
fn swap(self) -> Self::Output {
match self {
Self::Neither => AnyOf::<R, L>::Neither,
Self::Either(e) => AnyOf::<R, L>::Either(e.swap()),
Self::Both(b) => AnyOf::<R, L>::Both(b.swap()),
}
}
}
impl<L, R> Map<L, R> for AnyOf<L, R> {
type Output<L2, R2> = AnyOf<L2, R2>;
fn map<FL, FR, L2, R2>(self, fl: FL, fr: FR) -> Self::Output<L2, R2>
where
FL: FnOnce(L) -> L2,
FR: FnOnce(R) -> R2,
{
match self {
Self::Neither => AnyOf::<L2, R2>::Neither,
Self::Either(e) => AnyOf::<L2, R2>::Either(e.map(fl, fr)),
Self::Both(b) => AnyOf::<L2, R2>::Both(b.map(fl, fr)),
}
}
}
impl<L, R> Unwrap<L, R> for AnyOf<L, R> {
fn left_or_else(self, f: impl FnOnce() -> L) -> L {
match self {
Self::Neither => f(),
Self::Either(Either::Left(l)) => l,
Self::Either(Either::Right(_)) => f(),
Self::Both(Both { left: l, .. }) => l,
}
}
fn right_or_else(self, f: impl FnOnce() -> R) -> R {
match self {
Self::Neither => f(),
Self::Either(Either::Left(_)) => f(),
Self::Either(Either::Right(r)) => r,
Self::Both(Both { right: r, .. }) => r,
}
}
}
pub mod any_of_x;
#[cfg(test)]
mod tests;