#![no_std]
#![warn(unsafe_op_in_unsafe_fn)]
mod into_iter;
mod transmute;
use core::hint;
use core::mem;
use core::mem::MaybeUninit;
use core::ptr;
use crate::transmute::transmute_unchecked;
pub use crate::into_iter::IntoIter;
#[inline]
pub fn from_iter<I, T, const N: usize>(mut iter: I) -> Result<[T; N], IntoIter<T, N>>
where
I: Iterator<Item = T>,
{
struct Guard<'a, T, const N: usize> {
arr: &'a mut [MaybeUninit<T>; N],
init: usize,
}
impl<T, const N: usize> Drop for Guard<'_, T, N> {
fn drop(&mut self) {
for elem in &mut self.arr.as_mut_slice()[..self.init] {
unsafe { ptr::drop_in_place(elem.as_mut_ptr()) };
}
}
}
let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
let mut guard = Guard {
arr: &mut arr,
init: 0,
};
for _ in 0..N {
match iter.next() {
Some(item) => {
unsafe { guard.arr.get_unchecked_mut(guard.init) }.write(item);
guard.init += 1;
}
None => {
let init = guard.init;
mem::forget(guard);
let rem = unsafe { IntoIter::new_unchecked(arr, 0..init) };
return Err(rem);
}
}
}
mem::forget(guard);
Ok(unsafe { transmute_unchecked(arr) })
}
#[inline]
pub unsafe fn from_iter_unchecked<I, T, const N: usize>(iter: I) -> [T; N]
where
I: Iterator<Item = T>,
{
match from_iter(iter) {
Ok(arr) => arr,
Err(_) =>
unsafe { hint::unreachable_unchecked() },
}
}