1use crate::RngCore;
21use core::cmp::min;
22
23pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
25 let x = u64::from(rng.next_u32());
27 let y = u64::from(rng.next_u32());
28 (y << 32) | x
29}
30
31pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
38 let mut left = dest;
39 while left.len() >= 8 {
40 let (l, r) = { left }.split_at_mut(8);
41 left = r;
42 let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
43 l.copy_from_slice(&chunk);
44 }
45 let n = left.len();
46 if n > 4 {
47 let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
48 left.copy_from_slice(&chunk[..n]);
49 } else if n > 0 {
50 let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
51 left.copy_from_slice(&chunk[..n]);
52 }
53}
54
55trait Observable: Copy {
56 type Bytes: AsRef<[u8]>;
57 fn to_le_bytes(self) -> Self::Bytes;
58
59 fn as_byte_slice(x: &[Self]) -> &[u8];
61}
62impl Observable for u32 {
63 type Bytes = [u8; 4];
64 fn to_le_bytes(self) -> Self::Bytes {
65 self.to_le_bytes()
66 }
67 fn as_byte_slice(x: &[Self]) -> &[u8] {
68 let ptr = x.as_ptr() as *const u8;
69 let len = x.len() * core::mem::size_of::<Self>();
70 unsafe { core::slice::from_raw_parts(ptr, len) }
71 }
72}
73impl Observable for u64 {
74 type Bytes = [u8; 8];
75 fn to_le_bytes(self) -> Self::Bytes {
76 self.to_le_bytes()
77 }
78 fn as_byte_slice(x: &[Self]) -> &[u8] {
79 let ptr = x.as_ptr() as *const u8;
80 let len = x.len() * core::mem::size_of::<Self>();
81 unsafe { core::slice::from_raw_parts(ptr, len) }
82 }
83}
84
85fn fill_via_chunks<T: Observable>(src: &[T], dest: &mut [u8]) -> (usize, usize) {
86 let size = core::mem::size_of::<T>();
87 let byte_len = min(src.len() * size, dest.len());
88 let num_chunks = (byte_len + size - 1) / size;
89
90 if cfg!(target_endian = "little") {
91 dest[..byte_len].copy_from_slice(&T::as_byte_slice(&src[..num_chunks])[..byte_len]);
93 } else {
94 let mut i = 0;
96 let mut iter = dest[..byte_len].chunks_exact_mut(size);
97 for chunk in &mut iter {
98 chunk.copy_from_slice(src[i].to_le_bytes().as_ref());
99 i += 1;
100 }
101 let chunk = iter.into_remainder();
102 if !chunk.is_empty() {
103 chunk.copy_from_slice(&src[i].to_le_bytes().as_ref()[..chunk.len()]);
104 }
105 }
106
107 (num_chunks, byte_len)
108}
109
110pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
141 fill_via_chunks(src, dest)
142}
143
144pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
155 fill_via_chunks(src, dest)
156}
157
158pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
160 let mut buf = [0; 4];
161 rng.fill_bytes(&mut buf);
162 u32::from_le_bytes(buf)
163}
164
165pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
167 let mut buf = [0; 8];
168 rng.fill_bytes(&mut buf);
169 u64::from_le_bytes(buf)
170}
171
172#[cfg(test)]
173mod test {
174 use super::*;
175
176 #[test]
177 fn test_fill_via_u32_chunks() {
178 let src = [1, 2, 3];
179 let mut dst = [0u8; 11];
180 assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11));
181 assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);
182
183 let mut dst = [0u8; 13];
184 assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12));
185 assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);
186
187 let mut dst = [0u8; 5];
188 assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5));
189 assert_eq!(dst, [1, 0, 0, 0, 2]);
190 }
191
192 #[test]
193 fn test_fill_via_u64_chunks() {
194 let src = [1, 2];
195 let mut dst = [0u8; 11];
196 assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11));
197 assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);
198
199 let mut dst = [0u8; 17];
200 assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16));
201 assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);
202
203 let mut dst = [0u8; 5];
204 assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5));
205 assert_eq!(dst, [1, 0, 0, 0, 0]);
206 }
207}