1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
//! Operations on byte slices.
use core::{mem, slice};
/// Converts a type to a mutable byte slice. This is used within the crate to fill
/// secret values with the RNG output.
///
/// This trait is implemented for numeric types (`u8`, `i8`, ..., `u128`, `i128`), slices
/// of these types, and arrays of small sizes (1..=64).
// This is an ad-hoc replacement for the eponymous trait from `rand` v0.7, which was removed
// in `rand` v0.8.
pub trait AsByteSliceMut {
/// Performs conversion to a mutable byte slice.
fn as_byte_slice_mut(&mut self) -> &mut [u8];
/// Converts values within this type to the little-endian byte order.
///
/// This method is called after filling bytes to achieve uniform behavior across
/// big-endian and little-endian platforms.
fn convert_to_le(&mut self);
}
impl AsByteSliceMut for [u8] {
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
self
}
fn convert_to_le(&mut self) {
// No-op.
}
}
macro_rules! impl_as_byte_slice {
($ty:ty) => {
impl AsByteSliceMut for [$ty] {
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
if self.is_empty() {
// Empty slices need special handling since `from_raw_parts_mut` doesn't accept
// an empty pointer.
&mut []
} else {
let byte_len = self.len() * mem::size_of::<$ty>();
let data = (self as *mut [$ty]).cast::<u8>();
unsafe { slice::from_raw_parts_mut(data, byte_len) }
}
}
fn convert_to_le(&mut self) {
for element in self {
*element = element.to_le();
}
}
}
};
($($t:ty,)*) => {
$(impl_as_byte_slice!($t);)*
};
}
impl_as_byte_slice!(i8, u16, i16, u32, i32, u64, i64, u128, i128,);
impl<T> AsByteSliceMut for T
where
[T]: AsByteSliceMut,
{
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
AsByteSliceMut::as_byte_slice_mut(slice::from_mut(self))
}
fn convert_to_le(&mut self) {
AsByteSliceMut::convert_to_le(slice::from_mut(self));
}
}
impl<T, const N: usize> AsByteSliceMut for [T; N]
where
[T]: AsByteSliceMut,
{
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
AsByteSliceMut::as_byte_slice_mut(&mut self[..])
}
fn convert_to_le(&mut self) {
AsByteSliceMut::convert_to_le(&mut self[..]);
}
}