use std::cmp::Ordering;
pub trait Comparable: 'static {
unsafe fn equal(&self, other: *const u8) -> bool;
unsafe fn less_than(&self, other: *const u8) -> bool;
unsafe fn compare(&self, other: *const u8) -> Ordering;
}
impl<T> Comparable for T
where
T: Ord + Eq + 'static,
{
#[inline]
unsafe fn compare(&self, other: *const u8) -> Ordering {
unsafe { self.cmp(&*(other as *const Self)) }
}
#[inline]
unsafe fn equal(&self, other: *const u8) -> bool {
unsafe { self.eq(&*(other as *const Self)) }
}
#[inline]
unsafe fn less_than(&self, other: *const u8) -> bool {
unsafe { self.lt(&*(other as *const Self)) }
}
}
#[macro_export]
macro_rules! derive_comparison_traits {
($type_alias:ident <$($generic:ident),*>
where
$($bound:tt)*
) =>
{
impl<$($generic),*> PartialEq for $type_alias<$($generic),*>
where
$($bound)*
{
fn eq(&self, other: &Self) -> bool {
debug_assert_eq!(std::any::Any::type_id(self.as_any()), std::any::Any::type_id(other.as_any()));
unsafe{ self.equal(other as *const _ as *const u8) }
}
}
impl<$($generic),*> Eq for $type_alias<$($generic),*>
where
$($bound)*
{}
impl<$($generic),*> PartialOrd for $type_alias<$($generic),*>
where
$($bound)*
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<$($generic),*> Ord for $type_alias<$($generic),*>
where
$($bound)*
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
debug_assert_eq!(std::any::Any::type_id(self.as_any()), std::any::Any::type_id(other.as_any()));
unsafe{ self.compare(other as *const _ as *const u8) }
}
}
};
}