#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum These<T, U> {
This(T),
That(U),
Both(T, U),
}
impl<T, U> These<T, U> {
pub fn as_ref(&self) -> These<&T, &U> {
match *self {
These::This(ref t) => These::This(t),
These::That(ref u) => These::That(u),
These::Both(ref t, ref u) => These::Both(t, u),
}
}
pub fn as_mut(&mut self) -> These<&mut T, &mut U> {
match *self {
These::This(ref mut t) => These::This(t),
These::That(ref mut u) => These::That(u),
These::Both(ref mut t, ref mut u) => These::Both(t, u),
}
}
pub fn collapse_these<V, F, G, H>(self, f: F, g: G, h: H) -> V
where
F: FnOnce(T) -> V,
G: FnOnce(U) -> V,
H: FnOnce(T, U) -> V,
{
match self {
Self::This(t) => f(t),
Self::That(u) => g(u),
Self::Both(t, u) => h(t, u),
}
}
pub fn map<V, F>(self, op: F) -> These<T, V>
where
F: FnOnce(U) -> V,
{
self.map_both(|x| x, op)
}
pub fn map_first<V, F>(self, op: F) -> These<V, U>
where
F: FnOnce(T) -> V,
{
self.map_both(op, |x| x)
}
pub fn map_second<V, F>(self, op: F) -> These<T, V>
where
F: FnOnce(U) -> V,
{
self.map(op)
}
pub fn map_both<V, W, F, G>(self, f: F, g: G) -> These<V, W>
where
F: FnOnce(T) -> V,
G: FnOnce(U) -> W,
{
match self {
Self::This(t) => These::This(f(t)),
Self::That(u) => These::That(g(u)),
Self::Both(t, u) => These::Both(f(t), g(u)),
}
}
pub fn fold_these<V, F>(self, default: V, op: F) -> V
where
F: FnOnce(U, V) -> V,
{
match self {
Self::This(_) => default,
Self::That(u) => op(u, default),
Self::Both(_, u) => op(u, default),
}
}
pub fn from_these(self, t_default: T, u_default: U) -> (T, U) {
self.collapse_these(|t| (t, u_default), |u| (t_default, u), |t, u| (t, u))
}
pub fn swap_these(self) -> These<U, T> {
self.collapse_these(These::That, These::This, |t, u| These::Both(u, t))
}
pub fn this(self) -> Option<T> {
if let Self::This(t) = self {
Some(t)
} else {
None
}
}
pub fn that(self) -> Option<U> {
if let Self::That(u) = self {
Some(u)
} else {
None
}
}
pub fn these(self) -> Option<(T, U)> {
if let Self::Both(t, u) = self {
Some((t, u))
} else {
None
}
}
pub fn here(self) -> Option<T> {
match self {
Self::This(t) | Self::Both(t, _) => Some(t),
Self::That(_) => None,
}
}
pub fn there(self) -> Option<U> {
match self {
Self::That(u) | Self::Both(_, u) => Some(u),
Self::This(_) => None,
}
}
pub fn is_this(&self) -> bool {
if let Self::This(_) = self {
true
} else {
false
}
}
pub fn is_that(&self) -> bool {
if let Self::That(_) = self {
true
} else {
false
}
}
pub fn is_these(&self) -> bool {
if let Self::Both(_, _) = self {
true
} else {
false
}
}
pub fn is_here(&self) -> bool {
match self {
Self::That(_) => false,
_ => true,
}
}
pub fn is_there(&self) -> bool {
match self {
Self::This(_) => false,
_ => true,
}
}
pub fn partition_these(xs: Vec<These<T, U>>) -> (Vec<T>, Vec<U>, Vec<(T, U)>) {
let mut this: Vec<T> = Vec::new();
let mut that: Vec<U> = Vec::new();
let mut these: Vec<(T, U)> = Vec::new();
for x in xs {
x.collapse_these(
|t| this.push(t),
|u| that.push(u),
|t, u| these.push((t, u)),
)
}
(this, that, these)
}
pub fn partition_here_there(xs: Vec<These<T, U>>) -> (Vec<T>, Vec<U>) {
let mut this: Vec<T> = Vec::new();
let mut that: Vec<U> = Vec::new();
for x in xs {
match x {
Self::This(t) => this.push(t),
Self::That(u) => that.push(u),
Self::Both(t, u) => {
this.push(t);
that.push(u)
}
}
}
(this, that)
}
pub fn from_option(opt: Option<T>, default: U) -> Self {
match opt {
None => Self::That(default),
Some(t) => Self::This(t),
}
}
pub fn combine<F, G>(self, other: Self, f: F, g: G) -> Self
where
F: FnOnce(T, T) -> T,
G: FnOnce(U, U) -> U,
{
match (self, other) {
(Self::This(t), Self::This(v)) => Self::This(f(t, v)),
(Self::This(t), Self::That(u)) => Self::Both(t, u),
(Self::This(t), Self::Both(v, u)) => Self::Both(f(t, v), u),
(Self::That(u), Self::This(t)) => Self::Both(t, u),
(Self::That(u), Self::That(w)) => Self::That(g(u, w)),
(Self::That(u), Self::Both(t, w)) => Self::Both(t, g(u, w)),
(Self::Both(t, u), Self::Both(v, w)) => Self::Both(f(t, v), g(u, w)),
(Self::Both(t, u), Self::This(v)) => Self::Both(f(t, v), u),
(Self::Both(t, u), Self::That(w)) => Self::Both(t, g(u, w)),
}
}
}
impl<E, T> From<Result<T, E>> for These<T, E> {
fn from(result: Result<T, E>) -> Self {
match result {
Err(e) => Self::That(e),
Ok(t) => Self::This(t),
}
}
}