use alloc::boxed::Box;
use core::ops::{Deref, DerefMut};
use redoubt_zero::{
FastZeroizable, RedoubtZero, ZeroizationProbe, ZeroizeMetadata, ZeroizeOnDropSentinel,
};
#[derive(RedoubtZero)]
pub struct RedoubtArray<T, const N: usize>
where
T: FastZeroizable + ZeroizeMetadata + ZeroizationProbe,
{
inner: Box<[T; N]>,
__sentinel: ZeroizeOnDropSentinel,
}
#[cfg(any(test, feature = "test-utils"))]
impl<T: FastZeroizable + ZeroizeMetadata + ZeroizationProbe + PartialEq, const N: usize> PartialEq
for RedoubtArray<T, N>
{
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
#[cfg(any(test, feature = "test-utils"))]
impl<T: FastZeroizable + ZeroizeMetadata + Eq + ZeroizationProbe, const N: usize> Eq
for RedoubtArray<T, N>
{
}
impl<T, const N: usize> core::fmt::Debug for RedoubtArray<T, N>
where
T: FastZeroizable + ZeroizeMetadata + ZeroizationProbe,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("RedoubtArray")
.field("data", &"REDACTED")
.field("len", &N)
.finish()
}
}
impl<T, const N: usize> RedoubtArray<T, N>
where
T: FastZeroizable + ZeroizeMetadata + ZeroizationProbe,
{
pub fn new() -> Self
where
T: Default,
{
Self {
inner: Box::new(core::array::from_fn(|_| T::default())),
__sentinel: ZeroizeOnDropSentinel::default(),
}
}
pub fn from_mut_array(src: &mut [T; N]) -> Self
where
T: Default,
{
let mut arr = Self::new();
arr.replace_from_mut_array(src);
arr
}
#[inline]
pub const fn len(&self) -> usize {
N
}
#[inline]
pub const fn is_empty(&self) -> bool {
N == 0
}
pub fn replace_from_mut_array(&mut self, src: &mut [T; N]) {
self.fast_zeroize();
unsafe {
core::ptr::swap_nonoverlapping(src.as_mut_ptr(), self.inner.as_mut_ptr(), N);
}
src.fast_zeroize();
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self.inner.as_ref()
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.inner.as_mut()
}
#[inline]
pub fn as_array(&self) -> &[T; N] {
&self.inner
}
#[inline]
pub fn as_mut_array(&mut self) -> &mut [T; N] {
&mut self.inner
}
}
impl<T, const N: usize> Default for RedoubtArray<T, N>
where
T: FastZeroizable + ZeroizeMetadata + ZeroizationProbe + Default,
{
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> Deref for RedoubtArray<T, N>
where
T: FastZeroizable + ZeroizeMetadata + ZeroizationProbe,
{
type Target = [T];
fn deref(&self) -> &Self::Target {
&*self.inner
}
}
impl<T, const N: usize> DerefMut for RedoubtArray<T, N>
where
T: FastZeroizable + ZeroizeMetadata + ZeroizationProbe,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.inner
}
}