use crate::spec::dispatch::StaticMethodImpl;
pub trait Bool: 'static {
const VALUE: bool;
type If<Then, Else>;
type Elif<Then: Bool, Else: Bool>: Bool;
type And<Other: Bool>: Bool;
type Or<Other: Bool>: Bool;
fn static_dispatch<Then, Else, Output>() -> Output
where
Then: StaticMethodImpl<Output>,
Else: StaticMethodImpl<Output>;
}
#[derive(Debug)]
pub struct Present;
#[derive(Debug)]
pub struct Absent;
impl Bool for Present {
const VALUE: bool = true;
type If<Then, Else> = Then;
type Elif<Then: Bool, Else: Bool> = Then;
type And<Other: Bool> = Other;
type Or<Other: Bool> = Present;
#[inline(always)]
fn static_dispatch<Then, Else, Output>() -> Output
where
Then: StaticMethodImpl<Output>,
Else: StaticMethodImpl<Output>,
{
Then::call()
}
}
impl Bool for Absent {
const VALUE: bool = false;
type If<Then, Else> = Else;
type Elif<Then: Bool, Else: Bool> = Else;
type And<Other: Bool> = Absent;
type Or<Other: Bool> = Other;
#[inline(always)]
fn static_dispatch<Then, Else, Output>() -> Output
where
Then: StaticMethodImpl<Output>,
Else: StaticMethodImpl<Output>,
{
Else::call()
}
}
pub trait BoolAnd<Other: Bool>: Bool {
type Out: Bool;
}
impl<A: Bool, B: Bool> BoolAnd<B> for A {
type Out = A::And<B>;
}
pub trait BoolOr<Other: Bool>: Bool {
type Out: Bool;
}
impl<A: Bool, B: Bool> BoolOr<B> for A {
type Out = A::Or<B>;
}
pub trait BoolNot: Bool {
type Out: Bool;
}
impl BoolNot for Present {
type Out = Absent;
}
impl BoolNot for Absent {
type Out = Present;
}
pub trait SelectBool<const B: bool> {
type Out: Bool;
}
impl SelectBool<true> for () {
type Out = Present;
}
impl SelectBool<false> for () {
type Out = Absent;
}
pub type If<const C: bool, T, E> = <<() as SelectBool<C>>::Out as Bool>::If<T, E>;
pub type Elif<const C: bool, T, E> = <<() as SelectBool<C>>::Out as Bool>::Elif<T, E>;