use std::ops::{Not, BitAnd, BitOr};
pub enum True {}
pub enum False {}
pub enum Unknown {}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Ternary {
T,
U,
F,
}
pub trait ToTernary {
fn to_ternary() -> Ternary;
}
impl ToTernary for True {
#[inline] fn to_ternary() -> Ternary { Ternary::T }
}
impl ToTernary for False {
#[inline] fn to_ternary() -> Ternary { Ternary::F }
}
impl ToTernary for Unknown {
#[inline] fn to_ternary() -> Ternary { Ternary::U }
}
impl Not for True {
type Output = False;
fn not(self) -> Self::Output { unreachable!() }
}
impl Not for False {
type Output = True;
fn not(self) -> Self::Output { unreachable!() }
}
impl Not for Unknown {
type Output = Unknown;
fn not(self) -> Self::Output { unreachable!() }
}
impl<X: ToTernary> BitAnd<X> for True {
type Output = X;
fn bitand(self, _: X) -> Self::Output { unreachable!() }
}
impl<X: ToTernary> BitAnd<X> for False {
type Output = False;
fn bitand(self, _: X) -> Self::Output { unreachable!() }
}
impl BitAnd<True> for Unknown {
type Output = Unknown;
fn bitand(self, _: True) -> Self::Output { unreachable!() }
}
impl BitAnd<Unknown> for Unknown {
type Output = Unknown;
fn bitand(self, _: Unknown) -> Self::Output { unreachable!() }
}
impl BitAnd<False> for Unknown {
type Output = False;
fn bitand(self, _: False) -> Self::Output { unreachable!() }
}
impl<X: ToTernary> BitOr<X> for True {
type Output = True;
fn bitor(self, _: X) -> Self::Output { unreachable!() }
}
impl<X: ToTernary> BitOr<X> for False {
type Output = X;
fn bitor(self, _: X) -> Self::Output { unreachable!() }
}
impl BitOr<True> for Unknown {
type Output = True;
fn bitor(self, _: True) -> Self::Output { unreachable!() }
}
impl BitOr<Unknown> for Unknown {
type Output = Unknown;
fn bitor(self, _: Unknown) -> Self::Output { unreachable!() }
}
impl BitOr<False> for Unknown {
type Output = Unknown;
fn bitor(self, _: False) -> Self::Output { unreachable!() }
}
pub trait Same<Rhs = Self> {
type Output;
}
impl<T> Same<T> for T {
type Output = T;
}