secret_tree/
byte_slice.rs

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