use core::any::Any;
use core::fmt;
use std::error::Error;
#[doc(hidden)]
#[derive(Debug)]
pub enum End {}
impl std::error::Error for End {}
#[doc(hidden)]
#[derive(Debug)]
pub struct Cons<Head, Tail>(core::marker::PhantomData<Head>, Tail);
#[doc(hidden)]
#[derive(Debug)]
pub struct Recurse<Tail>(Tail);
pub trait ErrorFold {
fn source_fold(any: &dyn Any) -> Option<&(dyn Error + 'static)>;
}
impl ErrorFold for End {
fn source_fold(_: &dyn Any) -> Option<&(dyn Error + 'static)> {
unreachable!("source_fold called on End");
}
}
impl<Head, Tail> Error for Cons<Head, Tail>
where
Head: Error,
Tail: Error,
{
}
impl<Head, Tail> ErrorFold for Cons<Head, Tail>
where
Cons<Head, Tail>: Error,
Head: 'static + Error,
Tail: ErrorFold,
{
fn source_fold(any: &dyn Any) -> Option<&(dyn Error + 'static)> {
if let Some(head_ref) = any.downcast_ref::<Head>() {
head_ref.source()
} else {
Tail::source_fold(any)
}
}
}
impl<Head, Tail> fmt::Display for Cons<Head, Tail>
where
Head: fmt::Display,
Tail: fmt::Display,
{
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!("Display called for Cons which is not constructable")
}
}
impl fmt::Display for End {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!("Display::fmt called for an End, which is not constructible.")
}
}
pub trait DisplayFold {
fn display_fold(any: &dyn Any, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
}
impl DisplayFold for End {
fn display_fold(_: &dyn Any, _: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!("display_fold called on End");
}
}
impl<Head, Tail> DisplayFold for Cons<Head, Tail>
where
Cons<Head, Tail>: fmt::Display,
Head: 'static + fmt::Display,
Tail: DisplayFold,
{
fn display_fold(any: &dyn Any, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(head_ref) = any.downcast_ref::<Head>() {
head_ref.fmt(formatter)
} else {
Tail::display_fold(any, formatter)
}
}
}
pub trait DebugFold {
fn debug_fold(any: &dyn Any, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
}
impl DebugFold for End {
fn debug_fold(_: &dyn Any, _: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!("debug_fold called on End");
}
}
impl<Head, Tail> DebugFold for Cons<Head, Tail>
where
Cons<Head, Tail>: fmt::Debug,
Head: 'static + fmt::Debug,
Tail: DebugFold,
{
fn debug_fold(any: &dyn Any, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(head_ref) = any.downcast_ref::<Head>() {
head_ref.fmt(formatter)
} else {
Tail::debug_fold(any, formatter)
}
}
}
pub trait IsFold {
fn is_fold(any: &dyn Any) -> bool;
}
impl IsFold for End {
fn is_fold(_: &dyn Any) -> bool {
false
}
}
impl<Head, Tail> IsFold for Cons<Head, Tail>
where
Head: 'static,
Tail: IsFold,
{
fn is_fold(any: &dyn Any) -> bool {
if any.is::<Head>() {
true
} else {
Tail::is_fold(any)
}
}
}
pub trait TypeSet {
type Variants: TupleForm;
type Enum;
type EnumRef<'a>
where
Self: 'a;
}
impl TypeSet for () {
type Variants = End;
type Enum = E0;
type EnumRef<'a>
= E0
where
Self: 'a;
}
impl<A> TypeSet for (A,) {
type Variants = Cons<A, End>;
type Enum = E1<A>;
type EnumRef<'a>
= E1<&'a A>
where
Self: 'a;
}
impl<A, B> TypeSet for (A, B) {
type Variants = Cons<A, Cons<B, End>>;
type Enum = E2<A, B>;
type EnumRef<'a>
= E2<&'a A, &'a B>
where
Self: 'a;
}
impl<A, B, C> TypeSet for (A, B, C) {
type Variants = Cons<A, Cons<B, Cons<C, End>>>;
type Enum = E3<A, B, C>;
type EnumRef<'a>
= E3<&'a A, &'a B, &'a C>
where
Self: 'a;
}
impl<A, B, C, D> TypeSet for (A, B, C, D) {
type Variants = Cons<A, Cons<B, Cons<C, Cons<D, End>>>>;
type Enum = E4<A, B, C, D>;
type EnumRef<'a>
= E4<&'a A, &'a B, &'a C, &'a D>
where
Self: 'a;
}
impl<A, B, C, D, E> TypeSet for (A, B, C, D, E) {
type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, End>>>>>;
type Enum = E5<A, B, C, D, E>;
type EnumRef<'a>
= E5<&'a A, &'a B, &'a C, &'a D, &'a E>
where
Self: 'a;
}
impl<A, B, C, D, E, F> TypeSet for (A, B, C, D, E, F) {
type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, End>>>>>>;
type Enum = E6<A, B, C, D, E, F>;
type EnumRef<'a>
= E6<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F>
where
Self: 'a;
}
impl<A, B, C, D, E, F, G> TypeSet for (A, B, C, D, E, F, G) {
type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, End>>>>>>>;
type Enum = E7<A, B, C, D, E, F, G>;
type EnumRef<'a>
= E7<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G>
where
Self: 'a;
}
impl<A, B, C, D, E, F, G, H> TypeSet for (A, B, C, D, E, F, G, H) {
type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, End>>>>>>>>;
type Enum = E8<A, B, C, D, E, F, G, H>;
type EnumRef<'a>
= E8<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H>
where
Self: 'a;
}
impl<A, B, C, D, E, F, G, H, I> TypeSet for (A, B, C, D, E, F, G, H, I) {
type Variants =
Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, Cons<I, End>>>>>>>>>;
type Enum = E9<A, B, C, D, E, F, G, H, I>;
type EnumRef<'a>
= E9<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H, &'a I>
where
Self: 'a;
}
pub trait TupleForm {
type Tuple: TypeSet;
}
impl TupleForm for End {
type Tuple = ();
}
impl<A> TupleForm for Cons<A, End> {
type Tuple = (A,);
}
impl<A, B> TupleForm for Cons<A, Cons<B, End>> {
type Tuple = (A, B);
}
impl<A, B, C> TupleForm for Cons<A, Cons<B, Cons<C, End>>> {
type Tuple = (A, B, C);
}
impl<A, B, C, D> TupleForm for Cons<A, Cons<B, Cons<C, Cons<D, End>>>> {
type Tuple = (A, B, C, D);
}
impl<A, B, C, D, E> TupleForm for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, End>>>>> {
type Tuple = (A, B, C, D, E);
}
impl<A, B, C, D, E, F> TupleForm for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, End>>>>>> {
type Tuple = (A, B, C, D, E, F);
}
impl<A, B, C, D, E, F, G> TupleForm
for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, End>>>>>>>
{
type Tuple = (A, B, C, D, E, F, G);
}
impl<A, B, C, D, E, F, G, H> TupleForm
for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, End>>>>>>>>
{
type Tuple = (A, B, C, D, E, F, G, H);
}
impl<A, B, C, D, E, F, G, H, I> TupleForm
for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, Cons<I, End>>>>>>>>>
{
type Tuple = (A, B, C, D, E, F, G, H, I);
}
pub enum E0 {}
pub enum E1<A> {
A(A),
}
impl<A> From<A> for E1<A> {
fn from(a: A) -> E1<A> {
E1::A(a)
}
}
pub enum E2<A, B> {
A(A),
B(B),
}
pub enum E3<A, B, C> {
A(A),
B(B),
C(C),
}
pub enum E4<A, B, C, D> {
A(A),
B(B),
C(C),
D(D),
}
pub enum E5<A, B, C, D, E> {
A(A),
B(B),
C(C),
D(D),
E(E),
}
pub enum E6<A, B, C, D, E, F> {
A(A),
B(B),
C(C),
D(D),
E(E),
F(F),
}
pub enum E7<A, B, C, D, E, F, G> {
A(A),
B(B),
C(C),
D(D),
E(E),
F(F),
G(G),
}
pub enum E8<A, B, C, D, E, F, G, H> {
A(A),
B(B),
C(C),
D(D),
E(E),
F(F),
G(G),
H(H),
}
pub enum E9<A, B, C, D, E, F, G, H, I> {
A(A),
B(B),
C(C),
D(D),
E(E),
F(F),
G(G),
H(H),
I(I),
}
pub trait Contains<T, Index> {}
impl<T, Tail> Contains<T, End> for Cons<T, Tail> {}
impl<T, Index, Head, Tail> Contains<T, Cons<Index, ()>> for Cons<Head, Tail> where
Tail: Contains<T, Index>
{
}
pub trait Narrow<Target, Index>: TupleForm {
type Remainder: TupleForm;
}
impl<Target, Tail> Narrow<Target, End> for Cons<Target, Tail>
where
Tail: TupleForm,
Cons<Target, Tail>: TupleForm,
{
type Remainder = Tail;
}
impl<Head, Tail, Target, Index> Narrow<Target, Recurse<Index>> for Cons<Head, Tail>
where
Tail: Narrow<Target, Index>,
Tail: TupleForm,
Cons<Head, Tail>: TupleForm,
Cons<Head, <Tail as Narrow<Target, Index>>::Remainder>: TupleForm,
{
type Remainder = Cons<Head, <Tail as Narrow<Target, Index>>::Remainder>;
}
fn _narrow_test() {
fn can_narrow<Types, Target, Remainder, Index>()
where
Types: Narrow<Target, Index, Remainder = Remainder>,
{
}
type T0 = <(u32, String) as TypeSet>::Variants;
can_narrow::<T0, u32, _, _>();
can_narrow::<T0, String, Cons<u32, End>, _>();
}
pub trait SupersetOf<Other, Index> {
type Remainder: TupleForm;
}
impl<T: TupleForm> SupersetOf<End, End> for T {
type Remainder = T;
}
impl<SubHead, SubTail, SuperHead, SuperTail, HeadIndex, TailIndex>
SupersetOf<Cons<SubHead, SubTail>, Cons<HeadIndex, TailIndex>> for Cons<SuperHead, SuperTail>
where
Cons<SuperHead, SuperTail>: Narrow<SubHead, HeadIndex>,
<Cons<SuperHead, SuperTail> as Narrow<SubHead, HeadIndex>>::Remainder:
SupersetOf<SubTail, TailIndex>,
{
type Remainder =
<<Cons<SuperHead, SuperTail> as Narrow<SubHead, HeadIndex>>::Remainder as SupersetOf<
SubTail,
TailIndex,
>>::Remainder;
}
fn _superset_test() {
fn is_superset<S1, S2, Remainder, Index>()
where
S1: SupersetOf<S2, Index, Remainder = Remainder>,
{
}
type T0 = <(u32,) as TypeSet>::Variants;
type T1A = <(u32, String) as TypeSet>::Variants;
type T1B = <(String, u32) as TypeSet>::Variants;
type T2 = <(String, i32, u32) as TypeSet>::Variants;
type T3 = <(Vec<u8>, Vec<i8>, u32, f32, String, f64, i32) as TypeSet>::Variants;
is_superset::<T0, T0, _, _>();
is_superset::<T1A, T1A, _, _>();
is_superset::<T1A, T1B, _, _>();
is_superset::<T1B, T1A, _, _>();
is_superset::<T2, T2, _, _>();
is_superset::<T1A, T0, _, _>();
is_superset::<T1B, T0, _, _>();
is_superset::<T2, T0, <(String, i32) as TypeSet>::Variants, _>();
is_superset::<T2, T1A, <(i32,) as TypeSet>::Variants, _>();
is_superset::<T2, T1B, <(i32,) as TypeSet>::Variants, _>();
is_superset::<T3, T1A, <(Vec<u8>, Vec<i8>, f32, f64, i32) as TypeSet>::Variants, _>();
is_superset::<T3, T1B, _, _>();
is_superset::<T3, T0, _, _>();
is_superset::<T3, T2, _, _>();
type T5sup = <(u8, u16, u32, u64, u128) as TypeSet>::Variants;
type T5sub = <(u8, u128) as TypeSet>::Variants;
type T5rem = <(u16, u32, u64) as TypeSet>::Variants;
is_superset::<T5sup, T5sub, T5rem, _>();
}