use crate::polymorphism::CmpWrapper;
use core::marker::PhantomData;
pub trait ConstCmpMarker {
type Kind;
type This: ?Sized;
}
pub struct IsArrayKind<T>(PhantomData<T>);
pub struct IsStdKind;
pub struct IsNotStdKind;
#[allow(clippy::type_complexity)]
pub struct IsAConstCmpMarker<K, T: ?Sized, R: ?Sized>(
PhantomData<(
PhantomData<fn() -> PhantomData<K>>,
PhantomData<fn() -> PhantomData<T>>,
PhantomData<fn() -> PhantomData<R>>,
)>,
);
impl<K, T: ?Sized, R: ?Sized> Copy for IsAConstCmpMarker<K, T, R> {}
impl<K, T: ?Sized, R: ?Sized> Clone for IsAConstCmpMarker<K, T, R> {
fn clone(&self) -> Self {
*self
}
}
impl<R> IsAConstCmpMarker<R::Kind, R::This, R>
where
R: ?Sized + ConstCmpMarker,
{
pub const NEW: Self = Self(PhantomData);
}
impl<K, T: ?Sized, R: ?Sized> IsAConstCmpMarker<K, T, R> {
#[inline(always)]
pub const fn infer_type(self, _: &R) -> Self {
self
}
#[inline(always)]
pub const fn unreference(self, r: &T) -> &T {
r
}
}
impl<U, T: ?Sized, R: ?Sized> IsAConstCmpMarker<IsArrayKind<U>, T, R> {
#[inline(always)]
pub const fn coerce(self, slice: &[U]) -> CmpWrapper<&[U]> {
CmpWrapper(slice)
}
}
impl<T: ?Sized, R: ?Sized> IsAConstCmpMarker<IsNotStdKind, T, R> {
#[inline(always)]
pub const fn coerce(self, reference: &T) -> &T {
reference
}
}
#[cfg(feature = "const_generics")]
macro_rules! array_impls {
($($tt:tt)*) => {
impl<T, const N: usize> ConstCmpMarker for [T; N] {
type Kind = IsArrayKind<T>;
type This = Self;
}
};
}
#[cfg(not(feature = "const_generics"))]
macro_rules! array_impls {
($($len:literal),* $(,)* ) => (
$(
impl<T> ConstCmpMarker for [T; $len] {
type Kind = IsArrayKind<T>;
type This = Self;
}
)*
)
}
impl ConstCmpMarker for str {
type Kind = IsStdKind;
type This = Self;
}
impl<R: ?Sized> IsAConstCmpMarker<IsStdKind, str, R> {
#[inline(always)]
pub const fn coerce(self, reference: &str) -> CmpWrapper<&str> {
CmpWrapper(reference)
}
}
array_impls! {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
32,
}
impl<T> ConstCmpMarker for [T] {
type Kind = IsArrayKind<T>;
type This = [T];
}
impl<T> ConstCmpMarker for &T
where
T: ?Sized + ConstCmpMarker,
{
type Kind = T::Kind;
type This = T::This;
}
impl<T> ConstCmpMarker for &mut T
where
T: ?Sized + ConstCmpMarker,
{
type Kind = T::Kind;
type This = T::This;
}