use crate::helpers::TypeEquals;
use core::marker::Sized;
use core::mem::{MaybeUninit, transmute_copy};
pub trait Init<T, I, V = ()>: Sized {
#[cfg_attr(feature = "std", doc = r##"
Constructing a Vec containing the values 0 to 4:
```rust
use higher_order_functions::Init;
let vec = Vec::<usize>::init_with(5, |i| i);
assert_eq!(vec, vec![0, 1, 2, 3, 4]);
```
"##)]
fn init_with<F: FnMut(I) -> T>(value: V, elem: F) -> Self;
fn init<F: FnMut(I) -> T>(elem: F) -> Self where V: TypeEquals<()> {
Self::init_with(().into(), elem)
}
}
impl<T, const N: usize> Init<T, usize> for [T; N] {
fn init_with<F: FnMut(usize) -> T>(_: (), mut elem: F) -> Self {
let mut contents: [MaybeUninit<T>; N] = MaybeUninit::uninit_array();
for i in 0..N {
contents[i] = MaybeUninit::new(elem(i));
}
unsafe { transmute_copy(&contents) }
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Init<T, usize, usize> for lib::vec::Vec<T> {
fn init_with<F: FnMut(usize) -> T>(length: usize, mut elem: F) -> Self {
let mut value = lib::vec::Vec::with_capacity(length);
for i in 0..length {
value.push(elem(i));
}
value
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Init<T, usize, usize> for lib::collections::LinkedList<T> {
fn init_with<F: FnMut(usize) -> T>(length: usize, mut elem: F) -> Self {
let mut value = lib::collections::LinkedList::new();
for i in 0..length {
value.push_back(elem(i));
}
value
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> Init<Option<T>, usize> for lib::collections::LinkedList<T> {
fn init_with<F: FnMut(usize) -> Option<T>>(_: (), mut elem: F) -> Self {
let mut value = lib::collections::LinkedList::new();
while let Some(x) = elem(value.len()) {
value.push_back(x);
}
value
}
}