use core::marker::PhantomData;
pub trait Higher {
type Param;
type Target<T>: Higher<Param = T>;
fn unsafe_cast<T, R>(self) -> R
where
Self: Higher<Param = T> + Sized,
R: Higher<Param = T>,
{
let ptr = &self as *const _ as *const R;
let result = unsafe { core::ptr::read_volatile(ptr) };
core::mem::forget(self);
result
}
}
pub trait Higher2 {
type Param1;
type Param2;
type Target<T1, T2>: Higher2<Param1 = T1, Param2 = T2>;
}
#[macro_export]
macro_rules! higher {
($t:ident) => {
impl<P> $crate::higher::Higher for $t<P> {
type Param = P;
type Target<T> = $t<T>;
}
};
}
higher!(Option);
higher!(PhantomData);
impl<P, E> Higher for Result<P, E> {
type Param = P;
type Target<T> = Result<T, E>;
}
impl<P, E> Higher2 for Result<P, E> {
type Param1 = P;
type Param2 = E;
type Target<TP, TE> = Result<TP, TE>;
}
impl<A, B> Higher2 for (A, B) {
type Param1 = A;
type Param2 = B;
type Target<TA, TB> = (TA, TB);
}
if_std! {
use std::boxed::Box;
use std::collections::*;
use std::vec::Vec;
higher!(Vec);
higher!(Box);
higher!(LinkedList);
higher!(BinaryHeap);
higher!(BTreeSet);
higher!(VecDeque);
higher!(HashSet);
impl<K, V> Higher for HashMap<K, V> {
type Param = V;
type Target<T> = HashMap<K, T>;
}
impl<K, V> Higher2 for HashMap<K, V>{
type Param1 = K;
type Param2 = V;
type Target<TK, TV> = HashMap<TK, TV>;
}
}