Coverage Report

Created: 2025-05-07 06:59

/rust/registry/src/index.crates.io-6f17d22bba15001f/uuid-1.16.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
1.57k
pub(crate) fn u128() -> u128 {
10
1.57k
    imp::RngImp::u128()
11
1.57k
}
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(
22
    target_arch = "wasm32",
23
    target_vendor = "unknown",
24
    target_os = "unknown"
25
)))]
26
mod imp {
27
    /*
28
    Random support for non `wasm32-unknown-unknown` platforms.
29
    */
30
31
    use super::*;
32
33
    // Using `rand`
34
    #[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
    // Using `getrandom`
53
    #[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
1.57k
        fn u128() -> u128 {
59
1.57k
            let mut bytes = [0u8; 16];
60
1.57k
61
1.57k
            getrandom::fill(&mut bytes).unwrap_or_else(|err| {
62
0
                // NB: getrandom::Error has no source; this is adequate display
63
0
                panic!("could not retrieve random bytes for uuid: {}", err)
64
1.57k
            });
65
1.57k
66
1.57k
            u128::from_ne_bytes(bytes)
67
1.57k
        }
68
69
0
        fn u64() -> u64 {
70
0
            let mut bytes = [0u8; 8];
71
0
72
0
            getrandom::fill(&mut bytes).unwrap_or_else(|err| {
73
0
                // NB: getrandom::Error has no source; this is adequate display
74
0
                panic!("could not retrieve random bytes for uuid: {}", err)
75
0
            });
76
0
77
0
            u64::from_ne_bytes(bytes)
78
0
        }
79
80
0
        fn u16() -> u16 {
81
0
            let mut bytes = [0u8; 2];
82
0
83
0
            getrandom::fill(&mut bytes).unwrap_or_else(|err| {
84
0
                // NB: getrandom::Error has no source; this is adequate display
85
0
                panic!("could not retrieve random bytes for uuid: {}", err)
86
0
            });
87
0
88
0
            u16::from_ne_bytes(bytes)
89
0
        }
90
    }
91
}
92
93
#[cfg(all(
94
    target_arch = "wasm32",
95
    target_vendor = "unknown",
96
    target_os = "unknown"
97
))]
98
mod imp {
99
    /*
100
    Random support for `wasm32-unknown-unknown`.
101
    */
102
103
    #![allow(dead_code, unused_imports)] // Keeps our cfg's from becoming too convoluted in here
104
105
    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
    // Using `rand`
115
    #[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
    // Using `getrandom`
134
    #[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
                // NB: getrandom::Error has no source; this is adequate display
144
                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
                // NB: getrandom::Error has no source; this is adequate display
155
                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
                // NB: getrandom::Error has no source; this is adequate display
166
                panic!("could not retrieve random bytes for uuid: {}", err)
167
            });
168
169
            u16::from_ne_bytes(bytes)
170
        }
171
    }
172
173
    // Using WebCrypto via `wasm-bindgen`
174
    #[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
        /*
221
        This module preserves the stabilized behavior of `uuid` that requires the
222
        `js` feature to enable rng on `wasm32-unknown-unknown`, which it inherited
223
        from `getrandom` `0.2`.
224
225
        Vendored from `getrandom`: https://github.com/rust-random/getrandom/blob/ce3b017fdee0233c6ecd61e68b96a84bf6f911bf/src/backends/wasm_js.rs
226
227
        Copyright (c) 2018-2024 The rust-random Project Developers
228
        Copyright (c) 2014 The Rust Project Developers
229
230
        Permission is hereby granted, free of charge, to any
231
        person obtaining a copy of this software and associated
232
        documentation files (the "Software"), to deal in the
233
        Software without restriction, including without
234
        limitation the rights to use, copy, modify, merge,
235
        publish, distribute, sublicense, and/or sell copies of
236
        the Software, and to permit persons to whom the Software
237
        is furnished to do so, subject to the following
238
        conditions:
239
240
        The above copyright notice and this permission notice
241
        shall be included in all copies or substantial portions
242
        of the Software.
243
244
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
245
        ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
246
        TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
247
        PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
248
        SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
249
        CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
250
        OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
251
        IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
252
        DEALINGS IN THE SOFTWARE.
253
        */
254
255
        use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
256
257
        #[cfg(target_feature = "atomics")]
258
        use core::convert::TryInto;
259
260
        // Maximum buffer size allowed in `Crypto.getRandomValuesSize` is 65536 bytes.
261
        // See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
262
        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
            // getRandomValues does not work with all types of WASM memory,
279
            // so we initially write to browser memory to avoid exceptions.
280
            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
                // The chunk can be smaller than buf's length, so we call to
291
                // JS to create a smaller view of buf without allocation.
292
                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
            // Crypto.getRandomValues()
311
            #[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
}