1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//! Capability-oriented random number generators
//!
//! This corresponds to [`rand`].
//!
//! Capability-oriented APIs represent access to external resources as
//! objects which can be passed around between different parts of a
//! program.
//!
//! Two notable features are the [`OsRng`] and [`CapRng`] types, which
//! wrap up access to the operating system entropy source in capability
//! objects.
//!
//! This crate uses the existing `rand::SeedableRng` trait rather than having
//! its own version, however while `rand::SeedableRng` is mostly just a pure
//! interface, it provides a `from_entropy` function which directly reads
//! from the operating system entropy source. To preserve the
//! capability-oriented interface, avoid using `rand::SeedableRng`'s
//! `from_entropy` function on any of the types that implement that trait.

//! [`rand`]: https://docs.rs/rand/current/rand/index.html
//! [`OsRng`]: rngs/struct.OsRng.html
//! [`CapRng`]: rngs/struct.CapRng.html

#![deny(missing_docs)]
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/sunfishcode/cap-std/main/media/cap-std.svg"
)]
#![doc(
    html_favicon_url = "https://raw.githubusercontent.com/sunfishcode/cap-std/main/media/cap-std.ico"
)]

pub use rand::{distributions, seq, AsByteSliceMut, CryptoRng, Error, Rng, RngCore, SeedableRng};

/// Convenience re-export of common members.
///
/// This corresponds to [`rand::prelude`].
///
/// [`rand::prelude`]: https://docs.rs/rand/current/rand/prelude/index.html
pub mod prelude {
    pub use crate::distributions::Distribution;
    pub use crate::random;
    pub use crate::rngs::CapRng;
    #[cfg(feature = "small_rng")]
    pub use crate::rngs::SmallRng;
    pub use crate::rngs::StdRng;
    pub use crate::seq::IteratorRandom;
    pub use crate::seq::SliceRandom;
    pub use crate::thread_rng;
    pub use crate::CryptoRng;
    pub use crate::Rng;
    pub use crate::RngCore;
    pub use crate::SeedableRng;
}

/// Random number generators and adapters.
///
/// This corresponds to [`rand::rngs`].
///
/// [`rand::rngs`]: https://docs.rs/rand/current/rand/rngs/
pub mod rngs {
    pub use rand::rngs::{adapter, mock, StdRng};

    #[cfg(feature = "small_rng")]
    pub use rand::rngs::SmallRng;

    /// A random number generator that retrieves randomness from from the operating system.
    ///
    /// This corresponds to [`rand::rngs::OsRng`], except instead of implementing
    /// `Default` it has an unsafe `default` function since accessing the
    /// operating system requires ambient authority.
    ///
    /// [`OsRng`]: https://docs.rs/rand/current/rand/rngs/struct.OsRng.html
    #[derive(Clone, Copy, Debug)]
    pub struct OsRng(());

    impl OsRng {
        /// Returns an `OsRng` instance.
        ///
        /// # Safety
        ///
        /// This function is unsafe because it makes use of ambient authority to
        /// access the platform entropy source, which doesn't uphold the invariant
        /// of the rest of the API. It is otherwise safe to use.
        pub unsafe fn default() -> Self {
            Self(())
        }
    }

    impl crate::RngCore for OsRng {
        fn next_u32(&mut self) -> u32 {
            rand::rngs::OsRng.next_u32()
        }

        fn next_u64(&mut self) -> u64 {
            rand::rngs::OsRng.next_u64()
        }

        fn fill_bytes(&mut self, bytes: &mut [u8]) {
            rand::rngs::OsRng.fill_bytes(bytes)
        }

        fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), crate::Error> {
            rand::rngs::OsRng.try_fill_bytes(bytes)
        }
    }

    impl crate::CryptoRng for OsRng {}

    /// The type returned by `thread_rng`, essentially just a reference to a PRNG
    /// in memory.
    ///
    /// This corresponds to [`rand::rngs::ThreadRng`], except that it isn't tied
    /// to thread-local memory.
    ///
    /// [`rand::rngs::ThreadRng`]: https://docs.rs/rand/current/rand/rngs/struct.ThreadRng.html
    #[derive(Clone, Copy, Debug)]
    pub struct CapRng {
        pub(super) inner: rand::rngs::ThreadRng,
    }

    impl CapRng {
        /// A convenience alias for calling `thread_rng`.
        ///
        /// # Safety
        ///
        /// This function is unsafe because it makes use of ambient authority to
        /// access the platform entropy source, which doesn't uphold the invariant
        /// of the rest of the API. It is otherwise safe to use.
        pub unsafe fn default() -> Self {
            crate::thread_rng()
        }
    }

    impl crate::RngCore for CapRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }

        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }

        fn fill_bytes(&mut self, bytes: &mut [u8]) {
            self.inner.fill_bytes(bytes)
        }

        fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), crate::Error> {
            self.inner.try_fill_bytes(bytes)
        }
    }

    impl crate::CryptoRng for CapRng {}
}

/// Retrieve the lazily-initialized thread-local random number generator, seeded by the system.
///
/// This corresponds to [`rand::thread_rng`].
///
/// [`rand::thread_rng`]: https://docs.rs/rand/current/rand/fn.thread_rng.html
///
/// # Safety
///
/// This function is unsafe because it makes use of ambient authority to
/// access the platform entropy source, which doesn't uphold the invariant
/// of the rest of the API. It is otherwise safe to use.
pub unsafe fn thread_rng() -> rngs::CapRng {
    rngs::CapRng {
        inner: rand::thread_rng(),
    }
}

/// Generates a random value using the thread-local random number generator.
///
/// This corresponds to [`rand::random`].
///
/// [`rand::random`]: https://docs.rs/rand/current/rand/fn.random.html
///
/// # Safety
///
/// This function is unsafe because it makes use of ambient authority to
/// access the platform entropy source, which doesn't uphold the invariant
/// of the rest of the API. It is otherwise safe to use.
pub unsafe fn random<T>() -> T
where
    crate::distributions::Standard: crate::distributions::Distribution<T>,
{
    rand::random()
}