use core::marker::Destruct;
use core::marker::Freeze;
use crate::const_helpers;
use crate::set;
use crate::sure_eq::SureEq;
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct Sure<T: SureEq + 'static, const SET: &'static [T]>(T);
impl<T> Sure<T, { set::EMPTY::<T> }>
where
T: Copy + const Ord + Freeze + SureEq + const Destruct + 'static,
{
pub const NEW<const NUM: T>: Sure<T, { set::SLICEINATOR::<T, NUM> }> = const {
const { Sure::new(NUM).expect("This should be infallible, please file a bug report.") }
};
}
impl<T, const SET: &'static [T]> Sure<T, SET>
where
T: Copy + const Destruct + Freeze + SureEq + const Ord + 'static,
{
pub const SET: &'static [T] = SET;
#[must_use]
pub const fn set(self) -> &'static [T] {
SET
}
pub const fn new(value: T) -> Option<Self> {
match Self::contains(&value) {
true => Some(
unsafe { Self::new_unchecked(value) },
),
false => None,
}
}
#[must_use]
pub const unsafe fn new_unchecked(value: T) -> Self {
debug_assert!(
Self::contains(&value),
"Tried to create a Sure with a value thats not contained in its SET, this is UB."
);
Self(value)
}
pub const fn contains(value: &T) -> bool {
const_helpers::slice_contains(SET, value)
}
#[must_use]
pub const fn inner(self) -> T {
self.0
}
#[must_use]
pub const fn sort(self) -> Sure<T, { set::SORT::<T, SET> }> {
unsafe { self.cast_unchecked() }
}
#[must_use]
pub const fn normalize(self) -> Sure<T, { set::NORMALIZE::<T, SET> }> {
unsafe { self.cast_unchecked() }
}
#[must_use]
pub const fn widen<const SUPER_SET: &'static [T]>(self) -> Sure<T, SUPER_SET> {
const {
assert!(
const_helpers::slice_is_subset(SET, SUPER_SET),
"Tried to widen a Sure which failed because the target's SET isn't a superset of the original."
);
}
unsafe { self.cast_unchecked() }
}
#[must_use]
pub const fn cast<const NEW_SET: &'static [T]>(self) -> Option<Sure<T, NEW_SET>> {
match Sure::<T, NEW_SET>::contains(&self.inner()) {
true => Some(
unsafe { self.cast_unchecked() },
),
false => None,
}
}
#[must_use]
pub const unsafe fn cast_unchecked<const NEW_SET: &'static [T]>(self) -> Sure<T, NEW_SET> {
unsafe { Sure::new_unchecked(self.inner()) }
}
}