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(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
22mod imp {
23 use super::*;
28
29 #[cfg(any(feature = "rng-rand", feature = "fast-rng"))]
31 pub(super) struct RngImp;
32
33 #[cfg(any(feature = "rng-rand", feature = "fast-rng"))]
34 impl Rng for RngImp {
35 fn u128() -> u128 {
36 rand::random()
37 }
38
39 fn u64() -> u64 {
40 rand::random()
41 }
42
43 fn u16() -> u16 {
44 rand::random()
45 }
46 }
47
48 #[cfg(all(not(feature = "fast-rng"), not(feature = "rng-rand")))]
50 pub(super) struct RngImp;
51
52 #[cfg(all(not(feature = "fast-rng"), not(feature = "rng-rand")))]
53 impl Rng for RngImp {
54 fn u128() -> u128 {
55 let mut bytes = [0u8; 16];
56
57 getrandom::fill(&mut bytes).unwrap_or_else(|err| {
58 panic!("could not retrieve random bytes for uuid: {}", err)
60 });
61
62 u128::from_ne_bytes(bytes)
63 }
64
65 fn u64() -> u64 {
66 let mut bytes = [0u8; 8];
67
68 getrandom::fill(&mut bytes).unwrap_or_else(|err| {
69 panic!("could not retrieve random bytes for uuid: {}", err)
71 });
72
73 u64::from_ne_bytes(bytes)
74 }
75
76 fn u16() -> u16 {
77 let mut bytes = [0u8; 2];
78
79 getrandom::fill(&mut bytes).unwrap_or_else(|err| {
80 panic!("could not retrieve random bytes for uuid: {}", err)
82 });
83
84 u16::from_ne_bytes(bytes)
85 }
86 }
87}
88
89#[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
90mod imp {
91 #![allow(dead_code, unused_imports)] use super::*;
98
99 #[cfg(all(
100 not(feature = "js"),
101 not(feature = "rng-getrandom"),
102 not(feature = "rng-rand")
103 ))]
104 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");
105
106 #[cfg(feature = "rng-rand")]
108 pub(super) struct RngImp;
109
110 #[cfg(feature = "rng-rand")]
111 impl Rng for RngImp {
112 fn u128() -> u128 {
113 uuid_rng_internal_lib::__private::rand::random()
114 }
115
116 fn u64() -> u64 {
117 uuid_rng_internal_lib::__private::rand::random()
118 }
119
120 fn u16() -> u16 {
121 uuid_rng_internal_lib::__private::rand::random()
122 }
123 }
124
125 #[cfg(all(feature = "rng-getrandom", not(feature = "rng-rand")))]
127 pub(super) struct RngImp;
128
129 #[cfg(all(feature = "rng-getrandom", not(feature = "rng-rand")))]
130 impl Rng for RngImp {
131 fn u128() -> u128 {
132 let mut bytes = [0u8; 16];
133
134 uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
135 panic!("could not retrieve random bytes for uuid: {}", err)
137 });
138
139 u128::from_ne_bytes(bytes)
140 }
141
142 fn u64() -> u64 {
143 let mut bytes = [0u8; 8];
144
145 uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
146 panic!("could not retrieve random bytes for uuid: {}", err)
148 });
149
150 u64::from_ne_bytes(bytes)
151 }
152
153 fn u16() -> u16 {
154 let mut bytes = [0u8; 2];
155
156 uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
157 panic!("could not retrieve random bytes for uuid: {}", err)
159 });
160
161 u16::from_ne_bytes(bytes)
162 }
163 }
164
165 #[cfg(all(
167 feature = "js",
168 not(feature = "rng-rand"),
169 not(feature = "rng-getrandom")
170 ))]
171 pub(super) struct RngImp;
172
173 #[cfg(all(
174 feature = "js",
175 not(feature = "rng-rand"),
176 not(feature = "rng-getrandom")
177 ))]
178 impl Rng for RngImp {
179 fn u128() -> u128 {
180 let mut bytes = [0u8; 16];
181
182 if !webcrypto::fill(&mut bytes) {
183 panic!("could not retrieve random bytes for uuid")
184 }
185
186 u128::from_ne_bytes(bytes)
187 }
188
189 fn u64() -> u64 {
190 let mut bytes = [0u8; 8];
191
192 if !webcrypto::fill(&mut bytes) {
193 panic!("could not retrieve random bytes for uuid")
194 }
195
196 u64::from_ne_bytes(bytes)
197 }
198
199 fn u16() -> u16 {
200 let mut bytes = [0u8; 2];
201
202 if !webcrypto::fill(&mut bytes) {
203 panic!("could not retrieve random bytes for uuid")
204 }
205
206 u16::from_ne_bytes(bytes)
207 }
208 }
209
210 #[cfg(feature = "js")]
211 mod webcrypto {
212 use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
248
249 #[cfg(target_feature = "atomics")]
250 use core::convert::TryInto;
251
252 const MAX_BUFFER_SIZE: usize = 65536;
255
256 #[cfg(not(target_feature = "atomics"))]
257 #[inline]
258 pub fn fill(dest: &mut [u8]) -> bool {
259 for chunk in dest.chunks_mut(MAX_BUFFER_SIZE) {
260 if get_random_values(chunk).is_err() {
261 return false;
262 }
263 }
264
265 true
266 }
267
268 #[cfg(target_feature = "atomics")]
269 pub fn fill(dest: &mut [u8]) -> bool {
270 let buf_len = usize::min(dest.len(), MAX_BUFFER_SIZE);
273 let buf_len_u32 = buf_len
274 .try_into()
275 .expect("buffer length is bounded by MAX_BUFFER_SIZE");
276 let buf = js_sys::Uint8Array::new_with_length(buf_len_u32);
277 for chunk in dest.chunks_mut(buf_len) {
278 let chunk_len = chunk
279 .len()
280 .try_into()
281 .expect("chunk length is bounded by MAX_BUFFER_SIZE");
282 let sub_buf = if chunk_len == buf_len_u32 {
285 &buf
286 } else {
287 &buf.subarray(0, chunk_len)
288 };
289
290 if get_random_values(sub_buf).is_err() {
291 return false;
292 }
293
294 sub_buf.copy_to(chunk);
295 }
296
297 true
298 }
299
300 #[wasm_bindgen]
301 extern "C" {
302 #[cfg(not(target_feature = "atomics"))]
304 #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
305 fn get_random_values(buf: &mut [u8]) -> Result<(), JsValue>;
306 #[cfg(target_feature = "atomics")]
307 #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
308 fn get_random_values(buf: &js_sys::Uint8Array) -> Result<(), JsValue>;
309 }
310 }
311}