1 | // Overwrite links to crate items with intra-crate links |
2 | //! [`Error::UNEXPECTED`]: Error::UNEXPECTED |
3 | //! [`fill_uninit`]: fill_uninit |
4 | |
5 | #![no_std ] |
6 | #![doc ( |
7 | html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png" , |
8 | html_favicon_url = "https://www.rust-lang.org/favicon.ico" |
9 | )] |
10 | #![doc = include_str!("../README.md" )] |
11 | #![warn (rust_2018_idioms, unused_lifetimes, missing_docs)] |
12 | #![cfg_attr (docsrs, feature(doc_auto_cfg))] |
13 | #![deny ( |
14 | clippy::cast_lossless, |
15 | clippy::cast_possible_truncation, |
16 | clippy::cast_possible_wrap, |
17 | clippy::cast_precision_loss, |
18 | clippy::cast_ptr_alignment, |
19 | clippy::cast_sign_loss, |
20 | clippy::char_lit_as_u8, |
21 | clippy::checked_conversions, |
22 | clippy::fn_to_numeric_cast, |
23 | clippy::fn_to_numeric_cast_with_truncation, |
24 | clippy::ptr_as_ptr, |
25 | clippy::unnecessary_cast, |
26 | clippy::useless_conversion |
27 | )] |
28 | |
29 | #[macro_use ] |
30 | extern crate cfg_if; |
31 | |
32 | use core::mem::MaybeUninit; |
33 | |
34 | mod backends; |
35 | mod error; |
36 | mod util; |
37 | |
38 | #[cfg (feature = "std" )] |
39 | mod error_std_impls; |
40 | |
41 | pub use crate::error::Error; |
42 | |
43 | /// Fill `dest` with random bytes from the system's preferred random number source. |
44 | /// |
45 | /// This function returns an error on any failure, including partial reads. We |
46 | /// make no guarantees regarding the contents of `dest` on error. If `dest` is |
47 | /// empty, `getrandom` immediately returns success, making no calls to the |
48 | /// underlying operating system. |
49 | /// |
50 | /// Blocking is possible, at least during early boot; see module documentation. |
51 | /// |
52 | /// In general, `getrandom` will be fast enough for interactive usage, though |
53 | /// significantly slower than a user-space CSPRNG; for the latter consider |
54 | /// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html). |
55 | /// |
56 | /// # Examples |
57 | /// |
58 | /// ``` |
59 | /// # fn main() -> Result<(), getrandom::Error> { |
60 | /// let mut buf = [0u8; 32]; |
61 | /// getrandom::fill(&mut buf)?; |
62 | /// # Ok(()) } |
63 | /// ``` |
64 | #[inline ] |
65 | pub fn fill(dest: &mut [u8]) -> Result<(), Error> { |
66 | // SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape, |
67 | // and `fill_uninit` guarantees it will never de-initialize |
68 | // any part of `dest`. |
69 | fill_uninit(dest:unsafe { util::slice_as_uninit_mut(slice:dest) })?; |
70 | Ok(()) |
71 | } |
72 | |
73 | /// Fill potentially uninitialized buffer `dest` with random bytes from |
74 | /// the system's preferred random number source and return a mutable |
75 | /// reference to those bytes. |
76 | /// |
77 | /// On successful completion this function is guaranteed to return a slice |
78 | /// which points to the same memory as `dest` and has the same length. |
79 | /// In other words, it's safe to assume that `dest` is initialized after |
80 | /// this function has returned `Ok`. |
81 | /// |
82 | /// No part of `dest` will ever be de-initialized at any point, regardless |
83 | /// of what is returned. |
84 | /// |
85 | /// # Examples |
86 | /// |
87 | /// ```ignore |
88 | /// # // We ignore this test since `uninit_array` is unstable. |
89 | /// #![feature(maybe_uninit_uninit_array)] |
90 | /// # fn main() -> Result<(), getrandom::Error> { |
91 | /// let mut buf = core::mem::MaybeUninit::uninit_array::<1024>(); |
92 | /// let buf: &mut [u8] = getrandom::fill_uninit(&mut buf)?; |
93 | /// # Ok(()) } |
94 | /// ``` |
95 | #[inline ] |
96 | pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> { |
97 | if !dest.is_empty() { |
98 | backends::fill_inner(dest)?; |
99 | } |
100 | |
101 | #[cfg (getrandom_msan)] |
102 | extern "C" { |
103 | fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize); |
104 | } |
105 | |
106 | // SAFETY: `dest` has been fully initialized by `imp::fill_inner` |
107 | // since it returned `Ok`. |
108 | Ok(unsafe { |
109 | #[cfg (getrandom_msan)] |
110 | __msan_unpoison(dest.as_mut_ptr().cast(), dest.len()); |
111 | |
112 | util::slice_assume_init_mut(slice:dest) |
113 | }) |
114 | } |
115 | |
116 | /// Get random `u32` from the system's preferred random number source. |
117 | /// |
118 | /// # Examples |
119 | /// |
120 | /// ``` |
121 | /// # fn main() -> Result<(), getrandom::Error> { |
122 | /// let rng_seed = getrandom::u32()?; |
123 | /// # Ok(()) } |
124 | /// ``` |
125 | #[inline ] |
126 | pub fn u32() -> Result<u32, Error> { |
127 | backends::inner_u32() |
128 | } |
129 | |
130 | /// Get random `u64` from the system's preferred random number source. |
131 | /// |
132 | /// # Examples |
133 | /// |
134 | /// ``` |
135 | /// # fn main() -> Result<(), getrandom::Error> { |
136 | /// let rng_seed = getrandom::u64()?; |
137 | /// # Ok(()) } |
138 | /// ``` |
139 | #[inline ] |
140 | pub fn u64() -> Result<u64, Error> { |
141 | backends::inner_u64() |
142 | } |
143 | |