Coverage Report

Created: 2025-06-22 07:07

/rust/registry/src/index.crates.io-6f17d22bba15001f/uuid-1.17.0/src/rng.rs
Line
Count
Source (jump to first uncovered line)
1
#![allow(dead_code, unused_imports)] // Keeps our cfg's from becoming too convoluted in here
2
3
trait Rng {
4
    fn u128() -> u128;
5
    fn u64() -> u64;
6
    fn u16() -> u16;
7
}
8
9
0
pub(crate) fn u128() -> u128 {
10
0
    imp::RngImp::u128()
11
0
}
12
13
0
pub(crate) fn u64() -> u64 {
14
0
    imp::RngImp::u64()
15
0
}
16
17
0
pub(crate) fn u16() -> u16 {
18
0
    imp::RngImp::u16()
19
0
}
20
21
#[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
22
mod imp {
23
    /*
24
    Random support for non `wasm32-unknown-unknown` platforms.
25
    */
26
27
    use super::*;
28
29
    // Using `rand`
30
    #[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
    // Using `getrandom`
49
    #[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
0
        fn u128() -> u128 {
55
0
            let mut bytes = [0u8; 16];
56
0
57
0
            getrandom::fill(&mut bytes).unwrap_or_else(|err| {
58
0
                // NB: getrandom::Error has no source; this is adequate display
59
0
                panic!("could not retrieve random bytes for uuid: {}", err)
60
0
            });
61
0
62
0
            u128::from_ne_bytes(bytes)
63
0
        }
64
65
0
        fn u64() -> u64 {
66
0
            let mut bytes = [0u8; 8];
67
0
68
0
            getrandom::fill(&mut bytes).unwrap_or_else(|err| {
69
0
                // NB: getrandom::Error has no source; this is adequate display
70
0
                panic!("could not retrieve random bytes for uuid: {}", err)
71
0
            });
72
0
73
0
            u64::from_ne_bytes(bytes)
74
0
        }
75
76
0
        fn u16() -> u16 {
77
0
            let mut bytes = [0u8; 2];
78
0
79
0
            getrandom::fill(&mut bytes).unwrap_or_else(|err| {
80
0
                // NB: getrandom::Error has no source; this is adequate display
81
0
                panic!("could not retrieve random bytes for uuid: {}", err)
82
0
            });
83
0
84
0
            u16::from_ne_bytes(bytes)
85
0
        }
86
    }
87
}
88
89
#[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
90
mod imp {
91
    /*
92
    Random support for `wasm32-unknown-unknown`.
93
    */
94
95
    #![allow(dead_code, unused_imports)] // Keeps our cfg's from becoming too convoluted in here
96
97
    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
    // Using `rand`
107
    #[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
    // Using `getrandom`
126
    #[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
                // NB: getrandom::Error has no source; this is adequate display
136
                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
                // NB: getrandom::Error has no source; this is adequate display
147
                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
                // NB: getrandom::Error has no source; this is adequate display
158
                panic!("could not retrieve random bytes for uuid: {}", err)
159
            });
160
161
            u16::from_ne_bytes(bytes)
162
        }
163
    }
164
165
    // Using WebCrypto via `wasm-bindgen`
166
    #[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
        /*
213
        This module preserves the stabilized behavior of `uuid` that requires the
214
        `js` feature to enable rng on `wasm32-unknown-unknown`, which it inherited
215
        from `getrandom` `0.2`.
216
217
        Vendored from `getrandom`: https://github.com/rust-random/getrandom/blob/ce3b017fdee0233c6ecd61e68b96a84bf6f911bf/src/backends/wasm_js.rs
218
219
        Copyright (c) 2018-2024 The rust-random Project Developers
220
        Copyright (c) 2014 The Rust Project Developers
221
222
        Permission is hereby granted, free of charge, to any
223
        person obtaining a copy of this software and associated
224
        documentation files (the "Software"), to deal in the
225
        Software without restriction, including without
226
        limitation the rights to use, copy, modify, merge,
227
        publish, distribute, sublicense, and/or sell copies of
228
        the Software, and to permit persons to whom the Software
229
        is furnished to do so, subject to the following
230
        conditions:
231
232
        The above copyright notice and this permission notice
233
        shall be included in all copies or substantial portions
234
        of the Software.
235
236
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
237
        ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
238
        TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
239
        PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
240
        SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
241
        CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
242
        OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
243
        IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
244
        DEALINGS IN THE SOFTWARE.
245
        */
246
247
        use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
248
249
        #[cfg(target_feature = "atomics")]
250
        use core::convert::TryInto;
251
252
        // Maximum buffer size allowed in `Crypto.getRandomValuesSize` is 65536 bytes.
253
        // See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
254
        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
            // getRandomValues does not work with all types of WASM memory,
271
            // so we initially write to browser memory to avoid exceptions.
272
            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
                // The chunk can be smaller than buf's length, so we call to
283
                // JS to create a smaller view of buf without allocation.
284
                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
            // Crypto.getRandomValues()
303
            #[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
}