You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
2.8 KiB

//! Contains `Collapse` impls for primitive types through a newtime wrapper.
//!
//! Such wrappers are a workaround for the lack of template specialisation available in Rust so far, as the generic `impl<T: Hash> Collapse<T> for T` still requires computing the hash of the internal types before reducing to the `u8` page index.
//! For primitive types, this is unnessisary and causes a (very slight) performance loss.
use super::*;
use std::num::*;
pub trait PrimitiveCollapse: private::Sealed
{
fn collapse(&self) -> u8;
}
#[derive(Debug, Clone, PartialEq, Eq, Copy, Default, Ord, PartialOrd)]
pub struct Primitive<T>(T);
impl<T: PrimitiveCollapse+ Eq> Collapse for Primitive<T>
{
#[inline(always)] fn collapse(&self) -> u8 {
self.0.collapse()
}
}
impl<T: PrimitiveCollapse+ Eq> Primitive<T>
{
#[const_fn]
#[inline] pub const fn new(value: T) -> Self
{
Self(value)
}
#[inline] pub fn into_inner(self) -> T
{
self.0
}
#[const_fn]
#[inline] pub fn inner(&self) -> &T
{
&self.0
}
#[inline] pub fn inner_mut(&mut self) -> &mut T
{
&mut self.0
}
#[const_fn]
#[inline] pub const fn copy_into_inner(&self) -> T
where T: Copy
{
self.0
}
}
macro_rules! prim {
($name:ty) => {
impl private::Sealed for $name{}
impl PrimitiveCollapse for $name
{
#[inline(always)] fn collapse(&self) -> u8 {
(*self) as u8
}
}
};
($name:ty: +) => {
impl private::Sealed for $name{}
impl PrimitiveCollapse for $name
{
#[inline(always)] fn collapse(&self) -> u8 {
self.get() as u8
}
}
};
($name:ty: ^) => {
impl private::Sealed for $name{}
impl PrimitiveCollapse for $name
{
#[inline(always)] fn collapse(&self) -> u8 {
super::collapse(<$name>::to_ne_bytes(*self))
}
}
};
($name:ty: ^+) => {
impl private::Sealed for $name{}
impl PrimitiveCollapse for $name
{
#[inline(always)] fn collapse(&self) -> u8 {
super::collapse(self.get().to_ne_bytes())
}
}
};
($name:ty: fn {$($block:tt)*}) => {
impl private::Sealed for $name{}
impl PrimitiveCollapse for $name
{
#[inline(always)] fn collapse(&self) -> u8 {
$($block)+
}
}
};
($name:ty: {$($block:tt)*}) => {
impl private::Sealed for $name{}
impl PrimitiveCollapse for $name
{
$($block)+
}
};
}
prim!(u8);
prim!(i8);
prim!(u16: ^);
prim!(i16: ^);
prim!(u32: ^);
prim!(i32: ^);
prim!(u64: ^);
prim!(i64: ^);
prim!(u128: ^);
prim!(i128: ^);
prim!(isize: ^);
prim!(usize: ^);
prim!(NonZeroU8: +);
prim!(NonZeroI8: +);
prim!(NonZeroU16: ^+);
prim!(NonZeroI16: ^+);
prim!(NonZeroU32: ^+);
prim!(NonZeroI32: ^+);
prim!(NonZeroU64: ^+);
prim!(NonZeroI64: ^+);
prim!(NonZeroU128: ^+);
prim!(NonZeroI128: ^+);
prim!(NonZeroIsize: ^+);
prim!(NonZeroUsize: ^+);
prim!((): fn {
0
});
#[cfg(nightly)]
prim!(!: {
fn collapse(&self) -> u8
{
*self
}
});