1 // Copyright 2018 Developers of the Rand project.
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
12 use core
::num
::NonZeroU32
;
14 #[cfg(feature = "std")] use std::boxed::Box;
16 /// Error type of random number generators
18 /// In order to be compatible with `std` and `no_std`, this type has two
19 /// possible implementations: with `std` a boxed `Error` trait object is stored,
20 /// while with `no_std` we merely store an error code.
22 #[cfg(feature = "std")]
23 inner
: Box
<dyn std
::error
::Error
+ Send
+ Sync
+ '
static>,
24 #[cfg(not(feature = "std"))]
29 /// Codes at or above this point can be used by users to define their own
32 /// This has a fixed value of `(1 << 31) + (1 << 30) = 0xC000_0000`,
33 /// therefore the number of values available for custom codes is `1 << 30`.
35 /// This is identical to [`getrandom::Error::CUSTOM_START`](https://docs.rs/getrandom/latest/getrandom/struct.Error.html#associatedconstant.CUSTOM_START).
36 pub const CUSTOM_START
: u32 = (1 << 31) + (1 << 30);
37 /// Codes below this point represent OS Errors (i.e. positive i32 values).
38 /// Codes at or above this point, but below [`Error::CUSTOM_START`] are
39 /// reserved for use by the `rand` and `getrandom` crates.
41 /// This is identical to [`getrandom::Error::INTERNAL_START`](https://docs.rs/getrandom/latest/getrandom/struct.Error.html#associatedconstant.INTERNAL_START).
42 pub const INTERNAL_START
: u32 = 1 << 31;
44 /// Construct from any type supporting `std::error::Error`
46 /// Available only when configured with `std`.
48 /// See also `From<NonZeroU32>`, which is available with and without `std`.
49 #[cfg(feature = "std")]
50 #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
52 pub fn new
<E
>(err
: E
) -> Self
54 E
: Into
<Box
<dyn std
::error
::Error
+ Send
+ Sync
+ '
static>>,
56 Error { inner: err.into() }
59 /// Reference the inner error (`std` only)
61 /// When configured with `std`, this is a trivial operation and never
62 /// panics. Without `std`, this method is simply unavailable.
63 #[cfg(feature = "std")]
64 #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
66 pub fn inner(&self) -> &(dyn std
::error
::Error
+ Send
+ Sync
+ '
static) {
70 /// Unwrap the inner error (`std` only)
72 /// When configured with `std`, this is a trivial operation and never
73 /// panics. Without `std`, this method is simply unavailable.
74 #[cfg(feature = "std")]
75 #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
77 pub fn take_inner(self) -> Box
<dyn std
::error
::Error
+ Send
+ Sync
+ '
static> {
81 /// Extract the raw OS error code (if this error came from the OS)
83 /// This method is identical to `std::io::Error::raw_os_error()`, except
84 /// that it works in `no_std` contexts. If this method returns `None`, the
85 /// error value can still be formatted via the `Diplay` implementation.
87 pub fn raw_os_error(&self) -> Option
<i32> {
88 #[cfg(feature = "std")]
90 if let Some(e
) = self.inner
.downcast_ref
::<std
::io
::Error
>() {
91 return e
.raw_os_error();
95 Some(code
) if u32::from(code
) < Self::INTERNAL_START
=> Some(u32::from(code
) as i32),
100 /// Retrieve the error code, if any.
102 /// If this `Error` was constructed via `From<NonZeroU32>`, then this method
103 /// will return this `NonZeroU32` code (for `no_std` this is always the
104 /// case). Otherwise, this method will return `None`.
106 pub fn code(&self) -> Option
<NonZeroU32
> {
107 #[cfg(feature = "std")]
109 self.inner
.downcast_ref
::<ErrorCode
>().map(|c
| c
.0)
111 #[cfg(not(feature = "std"))]
118 impl fmt
::Debug
for Error
{
119 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
120 #[cfg(feature = "std")]
122 write
!(f
, "Error {{ inner: {:?} }}", self.inner
)
124 #[cfg(all(feature = "getrandom", not(feature = "std")))]
126 getrandom
::Error
::from(self.code
).fmt(f
)
128 #[cfg(not(feature = "getrandom"))]
130 write
!(f
, "Error {{ code: {} }}", self.code
)
135 impl fmt
::Display
for Error
{
136 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
137 #[cfg(feature = "std")]
139 write
!(f
, "{}", self.inner
)
141 #[cfg(all(feature = "getrandom", not(feature = "std")))]
143 getrandom
::Error
::from(self.code
).fmt(f
)
145 #[cfg(not(feature = "getrandom"))]
147 write
!(f
, "error code {}", self.code
)
152 impl From
<NonZeroU32
> for Error
{
154 fn from(code
: NonZeroU32
) -> Self {
155 #[cfg(feature = "std")]
158 inner
: Box
::new(ErrorCode(code
)),
161 #[cfg(not(feature = "std"))]
168 #[cfg(feature = "getrandom")]
169 impl From
<getrandom
::Error
> for Error
{
171 fn from(error
: getrandom
::Error
) -> Self {
172 #[cfg(feature = "std")]
175 inner
: Box
::new(error
),
178 #[cfg(not(feature = "std"))]
180 Error { code: error.code() }
185 #[cfg(feature = "std")]
186 impl std
::error
::Error
for Error
{
188 fn source(&self) -> Option
<&(dyn std
::error
::Error
+ '
static)> {
193 #[cfg(feature = "std")]
194 impl From
<Error
> for std
::io
::Error
{
196 fn from(error
: Error
) -> Self {
197 if let Some(code
) = error
.raw_os_error() {
198 std
::io
::Error
::from_raw_os_error(code
)
200 std
::io
::Error
::new(std
::io
::ErrorKind
::Other
, error
)
205 #[cfg(feature = "std")]
206 #[derive(Debug, Copy, Clone)]
207 struct ErrorCode(NonZeroU32
);
209 #[cfg(feature = "std")]
210 impl fmt
::Display
for ErrorCode
{
211 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
212 write
!(f
, "error code {}", self.0)
216 #[cfg(feature = "std")]
217 impl std
::error
::Error
for ErrorCode {}
221 #[cfg(feature = "getrandom")]
223 fn test_error_codes() {
224 // Make sure the values are the same as in `getrandom`.
225 assert_eq
!(super::Error
::CUSTOM_START
, getrandom
::Error
::CUSTOM_START
);
226 assert_eq
!(super::Error
::INTERNAL_START
, getrandom
::Error
::INTERNAL_START
);