1#![allow(dead_code, unused_imports)] trait Rng {
4 fn u128() -> u128;
5 fn u64() -> u64;
6 fn u16() -> u16;
7}
8
9pub(crate) fn u128() -> u128 {
10 imp::RngImp::u128()
11}
12
13pub(crate) fn u64() -> u64 {
14 imp::RngImp::u64()
15}
16
17pub(crate) fn u16() -> u16 {
18 imp::RngImp::u16()
19}
20
21#[cfg(not(all(
22 target_arch = "wasm32",
23 target_vendor = "unknown",
24 target_os = "unknown"
25)))]
26mod imp {
27 use super::*;
32
33 #[cfg(any(feature = "rng-rand", feature = "fast-rng"))]
35 pub(super) struct RngImp;
36
37 #[cfg(any(feature = "rng-rand", feature = "fast-rng"))]
38 impl Rng for RngImp {
39 fn u128() -> u128 {
40 rand::random()
41 }
42
43 fn u64() -> u64 {
44 rand::random()
45 }
46
47 fn u16() -> u16 {
48 rand::random()
49 }
50 }
51
52 #[cfg(all(not(feature = "fast-rng"), not(feature = "rng-rand")))]
54 pub(super) struct RngImp;
55
56 #[cfg(all(not(feature = "fast-rng"), not(feature = "rng-rand")))]
57 impl Rng for RngImp {
58 fn u128() -> u128 {
59 let mut bytes = [0u8; 16];
60
61 getrandom::fill(&mut bytes).unwrap_or_else(|err| {
62 panic!("could not retrieve random bytes for uuid: {}", err)
64 });
65
66 u128::from_ne_bytes(bytes)
67 }
68
69 fn u64() -> u64 {
70 let mut bytes = [0u8; 8];
71
72 getrandom::fill(&mut bytes).unwrap_or_else(|err| {
73 panic!("could not retrieve random bytes for uuid: {}", err)
75 });
76
77 u64::from_ne_bytes(bytes)
78 }
79
80 fn u16() -> u16 {
81 let mut bytes = [0u8; 2];
82
83 getrandom::fill(&mut bytes).unwrap_or_else(|err| {
84 panic!("could not retrieve random bytes for uuid: {}", err)
86 });
87
88 u16::from_ne_bytes(bytes)
89 }
90 }
91}
92
93#[cfg(all(
94 target_arch = "wasm32",
95 target_vendor = "unknown",
96 target_os = "unknown"
97))]
98mod imp {
99 #![allow(dead_code, unused_imports)] use super::*;
106
107 #[cfg(all(
108 not(feature = "js"),
109 not(feature = "rng-getrandom"),
110 not(feature = "rng-rand")
111 ))]
112 compile_error!("to use `uuid` on `wasm32-unknown-unknown`, specify a source of randomness using one of the `js`, `rng-getrandom`, or `rng-rand` features");
113
114 #[cfg(feature = "rng-rand")]
116 pub(super) struct RngImp;
117
118 #[cfg(feature = "rng-rand")]
119 impl Rng for RngImp {
120 fn u128() -> u128 {
121 uuid_rng_internal_lib::__private::rand::random()
122 }
123
124 fn u64() -> u64 {
125 uuid_rng_internal_lib::__private::rand::random()
126 }
127
128 fn u16() -> u16 {
129 uuid_rng_internal_lib::__private::rand::random()
130 }
131 }
132
133 #[cfg(all(feature = "rng-getrandom", not(feature = "rng-rand")))]
135 pub(super) struct RngImp;
136
137 #[cfg(all(feature = "rng-getrandom", not(feature = "rng-rand")))]
138 impl Rng for RngImp {
139 fn u128() -> u128 {
140 let mut bytes = [0u8; 16];
141
142 uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
143 panic!("could not retrieve random bytes for uuid: {}", err)
145 });
146
147 u128::from_ne_bytes(bytes)
148 }
149
150 fn u64() -> u64 {
151 let mut bytes = [0u8; 8];
152
153 uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
154 panic!("could not retrieve random bytes for uuid: {}", err)
156 });
157
158 u64::from_ne_bytes(bytes)
159 }
160
161 fn u16() -> u16 {
162 let mut bytes = [0u8; 2];
163
164 uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
165 panic!("could not retrieve random bytes for uuid: {}", err)
167 });
168
169 u16::from_ne_bytes(bytes)
170 }
171 }
172
173 #[cfg(all(
175 feature = "js",
176 not(feature = "rng-rand"),
177 not(feature = "rng-getrandom")
178 ))]
179 pub(super) struct RngImp;
180
181 #[cfg(all(
182 feature = "js",
183 not(feature = "rng-rand"),
184 not(feature = "rng-getrandom")
185 ))]
186 impl Rng for RngImp {
187 fn u128() -> u128 {
188 let mut bytes = [0u8; 16];
189
190 if !webcrypto::fill(&mut bytes) {
191 panic!("could not retrieve random bytes for uuid")
192 }
193
194 u128::from_ne_bytes(bytes)
195 }
196
197 fn u64() -> u64 {
198 let mut bytes = [0u8; 8];
199
200 if !webcrypto::fill(&mut bytes) {
201 panic!("could not retrieve random bytes for uuid")
202 }
203
204 u64::from_ne_bytes(bytes)
205 }
206
207 fn u16() -> u16 {
208 let mut bytes = [0u8; 2];
209
210 if !webcrypto::fill(&mut bytes) {
211 panic!("could not retrieve random bytes for uuid")
212 }
213
214 u16::from_ne_bytes(bytes)
215 }
216 }
217
218 #[cfg(feature = "js")]
219 mod webcrypto {
220 use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
256
257 #[cfg(target_feature = "atomics")]
258 use core::convert::TryInto;
259
260 const MAX_BUFFER_SIZE: usize = 65536;
263
264 #[cfg(not(target_feature = "atomics"))]
265 #[inline]
266 pub fn fill(dest: &mut [u8]) -> bool {
267 for chunk in dest.chunks_mut(MAX_BUFFER_SIZE) {
268 if get_random_values(chunk).is_err() {
269 return false;
270 }
271 }
272
273 true
274 }
275
276 #[cfg(target_feature = "atomics")]
277 pub fn fill(dest: &mut [u8]) -> bool {
278 let buf_len = usize::min(dest.len(), MAX_BUFFER_SIZE);
281 let buf_len_u32 = buf_len
282 .try_into()
283 .expect("buffer length is bounded by MAX_BUFFER_SIZE");
284 let buf = js_sys::Uint8Array::new_with_length(buf_len_u32);
285 for chunk in dest.chunks_mut(buf_len) {
286 let chunk_len = chunk
287 .len()
288 .try_into()
289 .expect("chunk length is bounded by MAX_BUFFER_SIZE");
290 let sub_buf = if chunk_len == buf_len_u32 {
293 &buf
294 } else {
295 &buf.subarray(0, chunk_len)
296 };
297
298 if get_random_values(sub_buf).is_err() {
299 return false;
300 }
301
302 sub_buf.copy_to(chunk);
303 }
304
305 true
306 }
307
308 #[wasm_bindgen]
309 extern "C" {
310 #[cfg(not(target_feature = "atomics"))]
312 #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
313 fn get_random_values(buf: &mut [u8]) -> Result<(), JsValue>;
314 #[cfg(target_feature = "atomics")]
315 #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
316 fn get_random_values(buf: &js_sys::Uint8Array) -> Result<(), JsValue>;
317 }
318 }
319}