#![allow(missing_debug_implementations)]
use variadics_please::all_tuples;
pub trait Optionality: private::Sealed {}
pub struct Optional;
impl private::Sealed for Optional {}
impl Optionality for Optional {}
pub struct Required;
impl private::Sealed for Required {}
impl Optionality for Required {}
mod private {
pub trait Sealed {}
}
pub trait AllowedOptionalityChain: private::Sealed {
type Last: Optionality;
}
impl private::Sealed for () {}
impl AllowedOptionalityChain for () {
type Last = Required;
}
impl<O: Optionality> private::Sealed for (O,) {}
impl<O: Optionality> AllowedOptionalityChain for (O,) {
type Last = O;
}
impl<O: Optionality> private::Sealed for (Required, O) {}
impl<O: Optionality> AllowedOptionalityChain for (Required, O) {
type Last = O;
}
impl private::Sealed for (Optional, Optional) {}
impl AllowedOptionalityChain for (Optional, Optional) {
type Last = Optional;
}
macro_rules! impl_chain {
() => {};
($p1:ident) => {};
($p1:ident, $p2:ident) => {};
($($param:ident),*) => {
impl_chain!(@pairwise [$($param),*] [] $($param,)*);
};
(@pairwise [$($param:ident),*] [$($tt:tt)*] $a:ident, $b:ident,) => {
impl_chain!(@emit [$($param),*] [$($tt)* ($a, $b): AllowedOptionalityChain,] $b,);
};
(@pairwise [$($param:ident),*] [$($tt:tt)*] $a:ident, $b:ident, $($tail:ident,)*) => {
impl_chain!(@pairwise [$($param),*] [$($tt)* ($a, $b): AllowedOptionalityChain,] $b, $($tail,)*);
};
(@emit [$($param: ident),*] [$($tt:tt)*] $last:ident,) => {
impl<$($param: Optionality),*> private::Sealed for ($($param),*) where $($tt)* {}
impl<$($param: Optionality),*> AllowedOptionalityChain for ($($param),*) where $($tt)* {
type Last = $last;
}
};
}
all_tuples!(impl_chain, 0, 16, O);