use core::marker::PhantomData;
use core::fmt::{self, Debug};
use typewit::{type_fn, Identity, TypeEq};
pub mod type_fns;
#[doc(no_inline)]
pub use self::type_fns::*;
pub trait Receiver<'a, T: 'a>: Sized {
type Hkt: ReceiverHkt<'a, Apply<T>: Identity<Type = Self>>;
const RECEIVER_WIT :ReceiverWit<'a, Self, T> = {
let identity_te: TypeEq<HktApply<'a, Self::Hkt, T>, Self> =
<HktApply<'a, Self::Hkt, T> as Identity>::TYPE_EQ;
identity_te
.map(MapReceiverWitRArgFn::<'a, T>::NEW)
.to_right(match HktOf::<Self, T>::HKT_WIT {
HktWit::Value(te) => ReceiverWit::Value(te.map(HktApplyFn::<'a, T>::NEW)),
HktWit::Ref(te) => ReceiverWit::Ref(te.map(HktApplyFn::<'a, T>::NEW)),
HktWit::RefMut(te) => ReceiverWit::RefMut(te.map(HktApplyFn::<'a, T>::NEW)),
})
};
}
pub trait ReceiverHkt<'a>: Sized {
type Apply<X: 'a>: 'a + Receiver<'a, X, Hkt = Self>;
const HKT_WIT: HktWit<'a, Self>;
}
impl<'a, T: 'a> Receiver<'a, T> for T {
type Hkt = ValueHkt<'a>;
}
impl<'a, T: 'a> Receiver<'a, T> for &'a T {
type Hkt = RefHkt<'a>;
}
impl<'a, T: 'a> Receiver<'a, T> for &'a mut T {
type Hkt = RefMutHkt<'a>;
}
pub struct ValueHkt<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
pub struct RefHkt<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
pub struct RefMutHkt<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
impl<'a> ReceiverHkt<'a> for ValueHkt<'a> {
type Apply<X: 'a> = X;
const HKT_WIT: HktWit<'a, Self> = HktWit::Value(TypeEq::NEW);
}
impl<'a> ReceiverHkt<'a> for RefHkt<'a> {
type Apply<X: 'a> = &'a X;
const HKT_WIT: HktWit<'a, Self> = HktWit::Ref(TypeEq::NEW);
}
impl<'a> ReceiverHkt<'a> for RefMutHkt<'a> {
type Apply<X: 'a> = &'a mut X;
const HKT_WIT: HktWit<'a, Self> = HktWit::RefMut(TypeEq::NEW);
}
pub type HktOf<'a, R, T> = <R as Receiver<'a, T>>::Hkt;
pub type HktApply<'a, H, T> = <H as ReceiverHkt<'a>>::Apply<T>;
pub type MapReceiver<'a, R, T, U> = HktApply<'a, HktOf<'a, R, T>, U>;
pub enum HktWit<'a, K>
where
K: ReceiverHkt<'a>
{
Value(TypeEq<K, ValueHkt<'a>>),
Ref(TypeEq<K, RefHkt<'a>>),
RefMut(TypeEq<K, RefMutHkt<'a>>),
}
impl<'a, K> Copy for HktWit<'a, K>
where
K: ReceiverHkt<'a>
{}
impl<'a, K> Clone for HktWit<'a, K>
where
K: ReceiverHkt<'a>
{
fn clone(&self) -> Self {
*self
}
}
impl<'a, K> Debug for HktWit<'a, K>
where
K: ReceiverHkt<'a>
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Value{..} => fmt.write_str("Value"),
Self::Ref{..} => fmt.write_str("Ref"),
Self::RefMut{..} => fmt.write_str("RefMut"),
}
}
}
pub enum ReceiverWit<'a, R, T>
where
R: Receiver<'a, T>
{
Value(TypeEq<R, T>),
Ref(TypeEq<R, &'a T>),
RefMut(TypeEq<R, &'a mut T>),
}
impl<'a, R, T> Copy for ReceiverWit<'a, R, T>
where
R: Receiver<'a, T>,
{}
impl<'a, R, T> Clone for ReceiverWit<'a, R, T>
where
R: Receiver<'a, T>,
{
fn clone(&self) -> Self {
*self
}
}
impl<'a, R, T> Debug for ReceiverWit<'a, R, T>
where
R: Receiver<'a, T>,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Value{..} => fmt.write_str("Value"),
Self::Ref{..} => fmt.write_str("Ref"),
Self::RefMut{..} => fmt.write_str("RefMut"),
}
}
}
impl<'a, R, T> ReceiverWit<'a, R, T>
where
R: Receiver<'a, T>,
{
pub const NEW: Self = R::RECEIVER_WIT;
}
typewit::type_fn! {
struct MapReceiverWitRArgFn<'a, T>;
impl<R> R => ReceiverWit<'a, R, T>
where
R: Receiver<'a, T>,
T: 'a;
}
typewit::type_fn! {
struct HktApplyFn<'a, T>;
impl<K: ReceiverHkt<'a>> K => K::Apply<T>
where
T: 'a;
}
pub const fn as_ref<'a, 'b, T>(this: &'b impl Receiver<'a, T>) -> &'b T
where
T: 'a,
'a: 'b,
{
let func = type_fn::GRef::<'b>::NEW;
match ReceiverWit::<'a, _, T>::NEW {
ReceiverWit::Value(te) => te.map(func).to_right(this),
ReceiverWit::Ref(te) => te.map(func).to_right(this),
ReceiverWit::RefMut(te) => te.map(func).to_right(this),
}
}