#![allow(unsafe_code)]
use crate::{Error, Result};
use core::{ops::BitXorAssign, slice};
use sha2::Sha256;
pub(crate) fn xor<T>(dst: &mut [T], src: &[T])
where
T: BitXorAssign + Copy,
{
assert_eq!(dst.len(), src.len());
for (dst, src) in core::iter::zip(dst, src) {
*dst ^= *src;
}
}
pub(crate) fn cast_slice(input: &[u32]) -> Result<&[u8]> {
let new_len = input
.len()
.checked_mul(size_of::<u32>() / size_of::<u8>())
.ok_or(Error::Internal)?;
Ok(unsafe { slice::from_raw_parts(input.as_ptr().cast(), new_len) })
}
pub(crate) fn cast_slice_mut(input: &mut [u32]) -> Result<&mut [u8]> {
let new_len = input
.len()
.checked_mul(size_of::<u32>() / size_of::<u8>())
.ok_or(Error::Internal)?;
Ok(unsafe { slice::from_raw_parts_mut(input.as_mut_ptr().cast(), new_len) })
}
pub(crate) fn hmac_sha256(key: &[u8], in_0: &[u8]) -> Result<[u8; 32]> {
use hmac::{KeyInit, Mac};
let mut hmac = hmac::Hmac::<Sha256>::new_from_slice(key).map_err(|_| Error::Internal)?;
hmac.update(in_0);
Ok(hmac.finalize().into_bytes().into())
}
#[inline]
#[must_use]
pub(crate) fn slice_as_chunks_mut<T, const N: usize>(slice: &mut [T]) -> (&mut [[T; N]], &mut [T]) {
assert!(N != 0, "chunk size must be non-zero");
let len_rounded_down = slice.len() / N * N;
let (multiple_of_n, remainder) = unsafe { slice.split_at_mut_unchecked(len_rounded_down) };
let array_slice = unsafe { slice_as_chunks_unchecked_mut(multiple_of_n) };
(array_slice, remainder)
}
#[inline]
#[must_use]
unsafe fn slice_as_chunks_unchecked_mut<T, const N: usize>(slice: &mut [T]) -> &mut [[T; N]] {
assert!(
N != 0 && slice.len() % N == 0,
"slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks"
);
let new_len = slice.len() / N;
unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), new_len) }
}