#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Z;
#[repr(transparent)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct S<N>(pub N);
pub type UnaryOf<const N: usize> = <Number<N> as ToUnary>::AsUnary;
pub trait Unary: sealed::Unary + Sized + Sync + Send + 'static {
const VALUE: usize;
}
impl Unary for Z {
const VALUE: usize = 0;
}
impl<N: Unary> Unary for S<N> {
const VALUE: usize = N::VALUE + 1;
}
pub trait LessThan<N: Unary>
where
Self: Unary,
{
}
impl<N: Unary> LessThan<S<N>> for Z {}
impl<N: Unary, M: LessThan<N>> LessThan<S<N>> for S<M> {}
pub trait Compare<IfLess, IfEqual, IfGreater>: sealed::Compare {
type Result;
}
impl<N: Unary, M: Unary, IfLess, IfEqual, IfGreater> Compare<IfLess, IfEqual, IfGreater>
for (S<N>, S<M>)
where
(N, M): Compare<IfLess, IfEqual, IfGreater>,
{
type Result = <(N, M) as Compare<IfLess, IfEqual, IfGreater>>::Result;
}
impl<IfLess, IfEqual, IfGreater> Compare<IfLess, IfEqual, IfGreater> for (Z, Z) {
type Result = IfEqual;
}
impl<N: Unary, IfLess, IfEqual, IfGreater> Compare<IfLess, IfEqual, IfGreater> for (S<N>, Z) {
type Result = IfGreater;
}
impl<N: Unary, IfLess, IfEqual, IfGreater> Compare<IfLess, IfEqual, IfGreater> for (Z, S<N>) {
type Result = IfLess;
}
pub trait Add: sealed::Add {
type Result: Unary;
}
impl<N: Unary> Add for (N, Z) {
type Result = N;
}
impl<N: Unary, M: Unary> Add for (N, S<M>)
where
(N, M): Add,
{
type Result = S<<(N, M) as Add>::Result>;
}
pub trait Constant: sealed::Constant {}
#[derive(Debug)]
pub enum Number<const N: usize> {}
impl<const N: usize> Constant for Number<N> {}
pub trait ToUnary {
type AsUnary: Unary + ToConstant<AsConstant = Self>;
}
pub trait ToConstant: Unary {
type AsConstant: Constant + ToUnary<AsUnary = Self>;
}
dialectic_macro::generate_unary_conversion_impls!(256);
mod sealed {
use super::*;
pub trait Unary: 'static {}
impl Unary for Z {}
impl<N: Unary> Unary for S<N> {}
pub trait Constant: 'static {}
impl<const N: usize> Constant for Number<N> {}
pub trait Compare {}
impl<N: Unary, M: Unary> Compare for (N, M) {}
pub trait Add {}
impl<N: Unary, M: Unary> Add for (N, M) {}
}