|
29 | 29 | //! |
30 | 30 | //! ### Implementing [`SeedableRng`] |
31 | 31 | //! |
32 | | -//! In many cases, [`SeedableRng::Seed`] must be converted to `[u32]` or |
33 | | -//! `[u64]`. The following helpers are provided: |
34 | | -//! |
35 | | -//! - [`read_u32_into`] |
36 | | -//! - [`read_u64_into`] |
| 32 | +//! In many cases, [`SeedableRng::Seed`] must be converted to `[u32; _]` or |
| 33 | +//! `[u64; _]`. [`read_words`] may be used for this. |
37 | 34 |
|
38 | 35 | use crate::RngCore; |
39 | 36 | #[allow(unused)] |
@@ -107,35 +104,24 @@ pub fn next_word_via_fill<W: Word, R: RngCore + ?Sized>(rng: &mut R) -> W { |
107 | 104 | W::from_le_bytes(buf) |
108 | 105 | } |
109 | 106 |
|
110 | | -/// Fills `dst: &mut [u32]` from `src` |
| 107 | +/// Reads an array of words from a byte slice |
111 | 108 | /// |
112 | | -/// Reads use Little-Endian byte order, allowing portable reproduction of `dst` |
113 | | -/// from a byte slice. |
| 109 | +/// Words are read from `src` in order, using LE conversion from bytes. |
114 | 110 | /// |
115 | 111 | /// # Panics |
116 | 112 | /// |
117 | | -/// If `src` has insufficient length (if `src.len() < 4*dst.len()`). |
118 | | -#[inline] |
119 | | -#[track_caller] |
120 | | -pub fn read_u32_into(src: &[u8], dst: &mut [u32]) { |
121 | | - assert!(src.len() >= 4 * dst.len()); |
122 | | - for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(4)) { |
123 | | - *out = u32::from_le_bytes(chunk.try_into().unwrap()); |
124 | | - } |
125 | | -} |
126 | | - |
127 | | -/// Fills `dst: &mut [u64]` from `src` |
128 | | -/// |
129 | | -/// # Panics |
130 | | -/// |
131 | | -/// If `src` has insufficient length (if `src.len() < 8*dst.len()`). |
132 | | -#[inline] |
133 | | -#[track_caller] |
134 | | -pub fn read_u64_into(src: &[u8], dst: &mut [u64]) { |
135 | | - assert!(src.len() >= 8 * dst.len()); |
136 | | - for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(8)) { |
137 | | - *out = u64::from_le_bytes(chunk.try_into().unwrap()); |
| 113 | +/// Panics if `size_of_val(src) != size_of::<[W; N]>()`. |
| 114 | +#[inline(always)] |
| 115 | +pub fn read_words<W: Word, const N: usize>(src: &[u8]) -> [W; N] { |
| 116 | + assert_eq!(size_of_val(src), size_of::<[W; N]>()); |
| 117 | + let mut dst = [W::from_usize(0); N]; |
| 118 | + let chunks = src.chunks_exact(size_of::<W>()); |
| 119 | + for (out, chunk) in dst.iter_mut().zip(chunks) { |
| 120 | + let mut buf: W::Bytes = Default::default(); |
| 121 | + buf.as_mut().copy_from_slice(chunk); |
| 122 | + *out = W::from_le_bytes(buf); |
138 | 123 | } |
| 124 | + dst |
139 | 125 | } |
140 | 126 |
|
141 | 127 | #[cfg(test)] |
@@ -186,23 +172,19 @@ mod test { |
186 | 172 | fn test_read() { |
187 | 173 | let bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; |
188 | 174 |
|
189 | | - let mut buf = [0u32; 4]; |
190 | | - read_u32_into(&bytes, &mut buf); |
| 175 | + let buf: [u32; 4] = read_words(&bytes); |
191 | 176 | assert_eq!(buf[0], 0x04030201); |
192 | 177 | assert_eq!(buf[3], 0x100F0E0D); |
193 | 178 |
|
194 | | - let mut buf = [0u32; 3]; |
195 | | - read_u32_into(&bytes[1..13], &mut buf); // unaligned |
| 179 | + let buf: [u32; 3] = read_words(&bytes[1..13]); // unaligned |
196 | 180 | assert_eq!(buf[0], 0x05040302); |
197 | 181 | assert_eq!(buf[2], 0x0D0C0B0A); |
198 | 182 |
|
199 | | - let mut buf = [0u64; 2]; |
200 | | - read_u64_into(&bytes, &mut buf); |
| 183 | + let buf: [u64; 2] = read_words(&bytes); |
201 | 184 | assert_eq!(buf[0], 0x0807060504030201); |
202 | 185 | assert_eq!(buf[1], 0x100F0E0D0C0B0A09); |
203 | 186 |
|
204 | | - let mut buf = [0u64; 1]; |
205 | | - read_u64_into(&bytes[7..15], &mut buf); // unaligned |
| 187 | + let buf: [u64; 1] = read_words(&bytes[7..15]); // unaligned |
206 | 188 | assert_eq!(buf[0], 0x0F0E0D0C0B0A0908); |
207 | 189 | } |
208 | 190 | } |
0 commit comments