Documentation
use core::mem::{self, ManuallyDrop, MaybeUninit};

use crate::{Random, RandomSource};

impl Random for bool {
    fn random<S>(source: &mut S) -> Self
    where
        S: RandomSource + ?Sized
    {
        u8::random(source) & 1 == 1
    }
}

macro_rules! numerics {
    ($($t:ty),* $(,)?) => {
        $(
            impl Random for $t {
                fn random<S>(source: &mut S) -> Self
                where
                    S: RandomSource + ?Sized
                {
                    let mut bytes = (0 as Self).to_ne_bytes();
                    source.fill_bytes(&mut bytes);
                    Self::from_ne_bytes(bytes)
                }
            }
        )*
    };
}

numerics!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);

impl<R: Random> Random for MaybeUninit<R> {
    fn random<S>(source: &mut S) -> Self
    where
        S: RandomSource + ?Sized
    {
        MaybeUninit::new(R::random(source))
    }
}

impl<R: Random, const N: usize> Random for [R; N] {
    fn random<S>(source: &mut S) -> Self
    where
        S: RandomSource + ?Sized
    {
        let mut arr = ManuallyDrop::new([ const { MaybeUninit::uninit() }; N ]);
        for elem in arr.iter_mut() {
            elem.write(R::random(source));
        }
        unsafe {
            mem::transmute_copy(&arr)
        }
    }
}