use crate::primitives::{Bool, Present, Absent};
use crate::trie::{Evaluate, And, Or, Not};
#[cfg(feature = "detect")]
pub use crate::detect::{
SelectClone, SelectCopy, SelectDebug, SelectDefault,
SelectSend, SelectSync, SelectEq, SelectPartialEq,
SelectOrd, SelectPartialOrd, SelectHash,
SelectDisplay, SelectSized, SelectUnpin,
};
pub trait SelectCap<Q, Then, Else> {
type Out;
}
impl<S, Q, Then, Else> SelectCap<Q, Then, Else> for S
where
S: Evaluate<Q>,
<S as Evaluate<Q>>::Out: Bool,
{
type Out = <<S as Evaluate<Q>>::Out as Bool>::If<Then, Else>;
}
pub trait SelectStaticCall<Q, Then, Else, Output> {
fn call() -> Output;
}
impl<S, Q, Then, Else, Output> SelectStaticCall<Q, Then, Else, Output> for S
where
S: Evaluate<Q>,
<S as Evaluate<Q>>::Out: Bool,
Then: StaticMethodImpl<Output>,
Else: StaticMethodImpl<Output>,
{
#[inline(always)]
fn call() -> Output {
<S as Evaluate<Q>>::Out::static_dispatch::<Then, Else, Output>()
}
}
pub trait BoolStaticCall<Then, Else, Output> {
fn call() -> Output;
}
impl<Then, Else, Output> BoolStaticCall<Then, Else, Output> for Present
where
Then: StaticMethodImpl<Output>,
{
#[inline(always)]
fn call() -> Output {
Then::call()
}
}
impl<Then, Else, Output> BoolStaticCall<Then, Else, Output> for Absent
where
Else: StaticMethodImpl<Output>,
{
#[inline(always)]
fn call() -> Output {
Else::call()
}
}
pub struct StaticSelect<Cap, Q, Then, Else>(
core::marker::PhantomData<(Cap, Q, Then, Else)>
);
impl<Cap, Q, Then, Else, Output> StaticMethodImpl<Output> for StaticSelect<Cap, Q, Then, Else>
where
Cap: SelectStaticCall<Q, Then, Else, Output>,
{
#[inline(always)]
fn call() -> Output {
<Cap as SelectStaticCall<Q, Then, Else, Output>>::call()
}
}
pub trait SelectAnd<Q1, Q2, Then, Else> {
type Out;
}
impl<S, Q1, Q2, Then, Else> SelectAnd<Q1, Q2, Then, Else> for S
where
S: SelectCap<And<Q1, Q2>, Then, Else>,
{
type Out = <S as SelectCap<And<Q1, Q2>, Then, Else>>::Out;
}
pub trait SelectOr<Q1, Q2, Then, Else> {
type Out;
}
impl<S, Q1, Q2, Then, Else> SelectOr<Q1, Q2, Then, Else> for S
where
S: SelectCap<Or<Q1, Q2>, Then, Else>,
{
type Out = <S as SelectCap<Or<Q1, Q2>, Then, Else>>::Out;
}
pub trait SelectNot<Q, Then, Else> {
type Out;
}
impl<S, Q, Then, Else> SelectNot<Q, Then, Else> for S
where
S: SelectCap<Not<Q>, Then, Else>,
{
type Out = <S as SelectCap<Not<Q>, Then, Else>>::Out;
}
pub trait MethodImpl<T: ?Sized, Output = ()> {
fn call(value: &T) -> Output;
}
pub trait StaticMethodImpl<Output = ()> {
fn call() -> Output;
}
pub trait SelectType<Q, Then, Else> {
type Out;
}
impl<S, Q, Then, Else> SelectType<Q, Then, Else> for S
where
S: Evaluate<Q>,
<S as Evaluate<Q>>::Out: Bool,
{
type Out = <<S as Evaluate<Q>>::Out as Bool>::If<Then, Else>;
}
pub trait TypeSelector {
type Out;
}
pub struct NoImpl;
impl<T: ?Sized, Output: Default> MethodImpl<T, Output> for NoImpl {
#[inline(always)]
fn call(_value: &T) -> Output {
Output::default()
}
}
impl<Output: Default> StaticMethodImpl<Output> for NoImpl {
#[inline(always)]
fn call() -> Output {
Output::default()
}
}
impl TypeSelector for NoImpl {
type Out = ();
}