1use crate::RngCore;
47#[allow(unused)]
48use crate::SeedableRng;
49
50pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
52    let x = u64::from(rng.next_u32());
54    let y = u64::from(rng.next_u32());
55    (y << 32) | x
56}
57
58pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
65    let mut left = dest;
66    while left.len() >= 8 {
67        let (l, r) = { left }.split_at_mut(8);
68        left = r;
69        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
70        l.copy_from_slice(&chunk);
71    }
72    let n = left.len();
73    if n > 4 {
74        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
75        left.copy_from_slice(&chunk[..n]);
76    } else if n > 0 {
77        let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
78        left.copy_from_slice(&chunk[..n]);
79    }
80}
81
82pub(crate) trait Observable: Copy {
83    type Bytes: Sized + AsRef<[u8]>;
84    fn to_le_bytes(self) -> Self::Bytes;
85}
86impl Observable for u32 {
87    type Bytes = [u8; 4];
88
89    fn to_le_bytes(self) -> Self::Bytes {
90        Self::to_le_bytes(self)
91    }
92}
93impl Observable for u64 {
94    type Bytes = [u8; 8];
95
96    fn to_le_bytes(self) -> Self::Bytes {
97        Self::to_le_bytes(self)
98    }
99}
100
101pub(crate) fn fill_via_chunks<T: Observable>(src: &[T], dest: &mut [u8]) -> (usize, usize) {
107    let size = core::mem::size_of::<T>();
108
109    let mut dest = dest.chunks_exact_mut(size);
112    let mut src = src.iter();
113
114    let zipped = dest.by_ref().zip(src.by_ref());
115    let num_chunks = zipped.len();
116    zipped.for_each(|(dest, src)| dest.copy_from_slice(src.to_le_bytes().as_ref()));
117
118    let byte_len = num_chunks * size;
119    if let Some(src) = src.next() {
120        let dest = dest.into_remainder();
122        let n = dest.len();
123        if n > 0 {
124            dest.copy_from_slice(&src.to_le_bytes().as_ref()[..n]);
125            return (num_chunks + 1, byte_len + n);
126        }
127    }
128    (num_chunks, byte_len)
129}
130
131pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
133    let mut buf = [0; 4];
134    rng.fill_bytes(&mut buf);
135    u32::from_le_bytes(buf)
136}
137
138pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
140    let mut buf = [0; 8];
141    rng.fill_bytes(&mut buf);
142    u64::from_le_bytes(buf)
143}
144
145#[inline]
154#[track_caller]
155pub fn read_u32_into(src: &[u8], dst: &mut [u32]) {
156    assert!(src.len() >= 4 * dst.len());
157    for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(4)) {
158        *out = u32::from_le_bytes(chunk.try_into().unwrap());
159    }
160}
161
162#[inline]
168#[track_caller]
169pub fn read_u64_into(src: &[u8], dst: &mut [u64]) {
170    assert!(src.len() >= 8 * dst.len());
171    for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(8)) {
172        *out = u64::from_le_bytes(chunk.try_into().unwrap());
173    }
174}
175
176#[cfg(test)]
177mod test {
178    use super::*;
179
180    #[test]
181    fn test_fill_via_u32_chunks() {
182        let src_orig = [1u32, 2, 3];
183
184        let src = src_orig;
185        let mut dst = [0u8; 11];
186        assert_eq!(fill_via_chunks(&src, &mut dst), (3, 11));
187        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);
188
189        let src = src_orig;
190        let mut dst = [0u8; 13];
191        assert_eq!(fill_via_chunks(&src, &mut dst), (3, 12));
192        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);
193
194        let src = src_orig;
195        let mut dst = [0u8; 5];
196        assert_eq!(fill_via_chunks(&src, &mut dst), (2, 5));
197        assert_eq!(dst, [1, 0, 0, 0, 2]);
198    }
199
200    #[test]
201    fn test_fill_via_u64_chunks() {
202        let src_orig = [1u64, 2];
203
204        let src = src_orig;
205        let mut dst = [0u8; 11];
206        assert_eq!(fill_via_chunks(&src, &mut dst), (2, 11));
207        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);
208
209        let src = src_orig;
210        let mut dst = [0u8; 17];
211        assert_eq!(fill_via_chunks(&src, &mut dst), (2, 16));
212        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);
213
214        let src = src_orig;
215        let mut dst = [0u8; 5];
216        assert_eq!(fill_via_chunks(&src, &mut dst), (1, 5));
217        assert_eq!(dst, [1, 0, 0, 0, 0]);
218    }
219
220    #[test]
221    fn test_read() {
222        let bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
223
224        let mut buf = [0u32; 4];
225        read_u32_into(&bytes, &mut buf);
226        assert_eq!(buf[0], 0x04030201);
227        assert_eq!(buf[3], 0x100F0E0D);
228
229        let mut buf = [0u32; 3];
230        read_u32_into(&bytes[1..13], &mut buf); assert_eq!(buf[0], 0x05040302);
232        assert_eq!(buf[2], 0x0D0C0B0A);
233
234        let mut buf = [0u64; 2];
235        read_u64_into(&bytes, &mut buf);
236        assert_eq!(buf[0], 0x0807060504030201);
237        assert_eq!(buf[1], 0x100F0E0D0C0B0A09);
238
239        let mut buf = [0u64; 1];
240        read_u64_into(&bytes[7..15], &mut buf); assert_eq!(buf[0], 0x0F0E0D0C0B0A0908);
242    }
243}