use super::super::rand::R;
use super::base::Generator;
use std::mem::MaybeUninit;
use std::ptr;
pub struct Array<G, const N: usize> {
generator: G,
}
impl<G: Generator, const N: usize> Array<G, N> {
pub fn new(g: G) -> Self {
Self { generator: g }
}
}
impl<T, G, const N: usize> Generator for Array<G, N>
where
G: Generator<Item = T>,
{
type Item = [T; N];
fn generate<'a>(&self, r: &mut R) -> Self::Item {
let mut items: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
let mut sub_r = r.sub();
for elem in &mut items[..] {
let cell: T = (self.generator).generate(&mut sub_r);
unsafe { ptr::write(elem.as_mut_ptr(), cell) }
}
let ptr = &mut items as *mut _ as *mut [T; N];
let res = unsafe { ptr.read() };
core::mem::forget(items);
res
}
}
#[derive(Clone)]
pub struct Vector<SZ, G> {
size: SZ,
t: G,
}
impl<T, SZ, G> Generator for Vector<SZ, G>
where
SZ: Generator<Item = usize>,
G: Generator<Item = T>,
{
type Item = Vec<T>;
fn generate(&self, r: &mut R) -> Self::Item {
let sz = (self.size).generate(r);
let mut v = Vec::with_capacity(sz);
let mut sub_r = r.sub();
for _ in 0..sz {
let cell = self.t.generate(&mut sub_r);
v.push(cell)
}
v
}
}
pub fn array<EL, T, const SZ: usize>(elements: EL) -> Array<EL, SZ>
where
EL: Generator<Item = T>,
{
Array {
generator: elements,
}
}
pub fn vector<SZ, EL, T>(size: SZ, elements: EL) -> Vector<SZ, EL>
where
SZ: Generator<Item = usize>,
EL: Generator<Item = T>,
{
Vector { size, t: elements }
}