use core::fmt::Debug;
use arrayvec::ArrayVec;
use zeroize::{Zeroize, ZeroizeOnDrop};
pub trait ByteArray: Sized + Zeroize + PartialEq + Debug + Clone {
const LENGTH: usize;
fn new_zero() -> Self;
fn new_with(_: u8) -> Self;
fn from_slice(_: &[u8]) -> Self;
fn len() -> usize {
Self::LENGTH
}
fn as_slice(&self) -> &[u8];
fn as_mut(&mut self) -> &mut [u8];
}
#[derive(ZeroizeOnDrop, Zeroize, Clone, PartialEq, Debug)]
pub struct SensitiveByteArray<A: ByteArray>(A);
impl<A: ByteArray> SensitiveByteArray<A> {
pub fn new(a: A) -> Self {
Self(a)
}
}
impl<A: ByteArray> core::ops::Deref for SensitiveByteArray<A> {
type Target = A;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<A: ByteArray> core::ops::DerefMut for SensitiveByteArray<A> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<A: ByteArray> ByteArray for SensitiveByteArray<A> {
const LENGTH: usize = A::LENGTH;
fn new_zero() -> Self {
Self::new(A::new_zero())
}
fn new_with(a: u8) -> Self {
Self::new(A::new_with(a))
}
fn from_slice(s: &[u8]) -> Self {
Self::new(A::from_slice(s))
}
fn as_slice(&self) -> &[u8] {
self.0.as_slice()
}
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
#[cfg(feature = "alloc")]
#[derive(Zeroize, Debug, PartialEq, Clone)]
pub struct HeapArray<const N: usize>(alloc::vec::Vec<u8>);
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
#[cfg(feature = "alloc")]
impl<const N: usize> ByteArray for HeapArray<N> {
const LENGTH: usize = N;
fn new_zero() -> Self {
Self::new_with(0)
}
fn new_with(x: u8) -> Self {
let v = alloc::vec![x; N];
Self(v)
}
fn from_slice(s: &[u8]) -> Self {
assert_eq!(s.len(), N);
let mut v = alloc::vec![0; N];
v.as_mut_slice().copy_from_slice(s);
Self(v)
}
fn as_slice(&self) -> &[u8] {
self.0.as_slice()
}
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut_slice()
}
}
impl<const N: usize> ByteArray for ArrayVec<u8, N> {
const LENGTH: usize = N;
fn new_zero() -> Self {
Self::new_with(0)
}
fn new_with(x: u8) -> Self {
let mut a = ArrayVec::<u8, N>::new();
for _ in 0..N {
a.push(x);
}
a
}
fn from_slice(s: &[u8]) -> Self {
assert_eq!(s.len(), N);
let mut a = Self::new_zero();
a.copy_from_slice(s);
a
}
fn as_slice(&self) -> &[u8] {
self
}
fn as_mut(&mut self) -> &mut [u8] {
self
}
}
impl<const N: usize> ByteArray for [u8; N] {
const LENGTH: usize = N;
fn new_zero() -> Self {
[0u8; N]
}
fn new_with(x: u8) -> Self {
[x; N]
}
fn from_slice(data: &[u8]) -> Self {
assert_eq!(data.len(), N);
let mut a = [0u8; N];
a.copy_from_slice(data);
a
}
fn as_slice(&self) -> &[u8] {
self
}
fn as_mut(&mut self) -> &mut [u8] {
self
}
}