wallet-standard-base 0.2.0

The base features required by wallet-standard
Documentation
use core::fmt;

use zeroize::{Zeroize, ZeroizeOnDrop};

pub struct RandomBytes<const N: usize>([u8; N]);

impl<const N: usize> RandomBytes<N> {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn generate_with_buffer(buffer: &mut [u8; N]) {
        use getrandom::SysRng;

        use rand_chacha::ChaCha12Rng;
        use rand_core::{Rng, SeedableRng};

        let mut rng = ChaCha12Rng::try_from_rng(&mut SysRng).unwrap();

        rng.fill_bytes(buffer);
    }

    pub fn generate() -> Self {
        let mut buffer = Self::new();

        Self::generate_with_buffer(&mut buffer.0);

        buffer
    }

    pub const fn expose(&self) -> &[u8; N] {
        &self.0
    }
}

impl<const N: usize> Zeroize for RandomBytes<N> {
    fn zeroize(&mut self) {
        self.0.fill(0u8);

        assert_eq!(self.0, [0u8; N]);
    }
}
impl<const N: usize> ZeroizeOnDrop for RandomBytes<N> {}

impl<const N: usize> Default for RandomBytes<N> {
    fn default() -> Self {
        Self([0u8; N])
    }
}

impl<const N: usize> fmt::Debug for RandomBytes<N> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "RandomBytes(REDACTED[{N}])")
    }
}

impl<const N: usize> fmt::Display for RandomBytes<N> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{self:?}")
    }
}