use alloc::vec::Vec;
use core::marker::ConstParamTy_;
use core::marker::Destruct;
use core::marker::Freeze;
use crate::const_helpers;
use crate::sure_eq::SureEq;
pub(crate) const LENGTH<T: ConstParamTy_ + 'static, const SET: &'static [T]>: usize =
const { SET.len() };
pub(crate) const CARTESIAN_LENGTH<
T: ConstParamTy_ + 'static,
U: ConstParamTy_ + 'static,
const A: &'static [T],
const B: &'static [U],
>: usize = const { A.len() * B.len() };
pub const SORT<T: const Ord + ConstParamTy_ + Copy + const Destruct + Freeze + 'static, const SET: &'static [T]>:
&[T] = const {
#[expect(clippy::ok_expect)]
let arr: [T; LENGTH::<T, SET>] = SET.try_into().ok().expect("this is infallible");
&const_helpers::sort(arr)
};
pub const NORMALIZE<
T: SureEq + const Ord + Copy + const Destruct + 'static,
const SET: &'static [T],
>: &[T] = const {
'out: {
let set_sorted = SORT::<T, SET>;
let mut normalized: Vec<T> = Vec::new();
let [first, ..] = set_sorted else {
break 'out &[];
};
normalized.push(*first);
let mut i: usize = 1;
while i < set_sorted.len() {
let (previous, current) = (set_sorted[i - 1], set_sorted[i]);
if previous != current {
normalized.push(current);
}
i += 1;
}
normalized.const_make_global()
}
};
pub const UNION<T: ConstParamTy_ + Copy + Freeze + 'static , const SETS: &'static [&'static [T]]>:
&[T] = const {
let mut onion: Vec<T> = Vec::new();
let mut i: usize = 0;
while i < SETS.len() {
let mut j: usize = 0;
while j < SETS[i].len() {
onion.push(SETS[i][j]);
j += 1;
}
i += 1;
}
onion.const_make_global()
};
pub const INTERSECTION<
T: SureEq + Copy + const Destruct + 'static ,
const SETS: &'static [&'static [T]],
>: &[T] = const {
'out: {
let [first_set, ..] = SETS else {
break 'out &[];
};
let mut intersection: Vec<T> = const_helpers::slice_to_vec(first_set);
let mut i: usize = 1;
while i < SETS.len() {
const_helpers::vec_reduce_to_intersection_with(&mut intersection, SETS[i]);
i += 1;
}
intersection.const_make_global()
}
};
pub(crate) const EMPTY<T: 'static>: &[T] = &[];
pub(crate) const SLICEINATOR<T: 'static + ConstParamTy_ + Freeze, const NUM: T>: &[T] =
const { &[NUM] };