use crate::uint::Unsigned;
use crate::*;
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct Compress<T: CompressFinite>(T::Index);
#[doc(hidden)]
#[allow(clippy::missing_safety_doc)] pub unsafe trait CompressFinite: Finite {
#[allow(missing_docs)]
type Index: Unsigned;
}
impl<T: CompressFinite> Compress<T> {
pub fn new(value: T) -> Self {
Compress(T::Index::from_usize_unchecked(T::index_of(value)))
}
pub fn expand(&self) -> T {
unsafe { T::nth(self.0.to_usize()).unwrap_unchecked() }
}
}
pub fn compress<T: CompressFinite>(value: T) -> Compress<T> {
Compress::new(value)
}
unsafe impl<T: CompressFinite> Finite for Compress<T> {
const COUNT: usize = T::COUNT;
fn index_of(value: Self) -> usize {
value.0.to_usize()
}
fn nth(index: usize) -> Option<Self> {
if index < Self::COUNT {
Some(Compress(T::Index::from_usize_unchecked(index)))
} else {
None
}
}
}
impl<T: CompressFinite> Clone for Compress<T> {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<T: CompressFinite> Copy for Compress<T> { }
#[test]
fn test_compress_zst() {
assert_eq!(core::mem::size_of::<()>(), 0);
}