use core::mem::MaybeUninit;
pub trait Array<T>: AsRef<[T]> + AsMut<[T]> + IntoIterator<Item = T> + Sized {
fn from_fn<F>(f: F) -> Self
where
F: FnMut(usize) -> T;
fn try_from_fn<F, E>(f: F) -> Result<Self, E>
where
F: FnMut(usize) -> Result<T, E>;
}
impl<const N: usize, T> Array<T> for [T; N] {
#[inline]
fn from_fn<F>(f: F) -> Self
where
F: FnMut(usize) -> T,
{
core::array::from_fn(f)
}
fn try_from_fn<F, E>(mut f: F) -> Result<Self, E>
where
F: FnMut(usize) -> Result<T, E>,
{
let mut arr = MaybeUninit::<Self>::uninit();
let ptr = arr.as_mut_ptr() as *mut T;
struct Guard<T> {
ptr: *mut T,
initialized: usize,
}
impl<T> Drop for Guard<T> {
fn drop(&mut self) {
let slice = core::ptr::slice_from_raw_parts_mut(self.ptr, self.initialized);
unsafe { core::ptr::drop_in_place(slice) }
}
}
let mut guard = Guard { ptr, initialized: 0 };
for i in 0..N {
unsafe {
ptr.add(i).write(f(i)?);
}
guard.initialized += 1;
}
core::mem::forget(guard);
Ok(unsafe { arr.assume_init() })
}
}
pub trait DictKey {
type Array<T>: Array<T>;
const VARIANTS: &'static [&'static str];
fn from_index(index: usize) -> Self;
fn as_index(&self) -> usize;
}