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}