Skip to content

Commit c9c82df

Browse files
committed
Simplify Error type and remove methods
1 parent c71ad9a commit c9c82df

11 files changed

+76
-99
lines changed

src/cloudabi.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88

99
//! Implementation for CloudABI
1010
use crate::Error;
11+
use core::num::NonZeroU32;
1112

1213
extern "C" {
1314
fn cloudabi_sys_random_get(buf: *mut u8, buf_len: usize) -> u16;
1415
}
1516

1617
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
1718
let errno = unsafe { cloudabi_sys_random_get(dest.as_mut_ptr(), dest.len()) };
18-
if errno != 0 {
19+
if let Some(code) = NonZeroU32::new(errno as u32) {
1920
error!("cloudabi_sys_random_get: failed with {}", errno);
20-
Err(Error::from_os_error(errno.into()))
21+
Err(Error::from(code))
2122
} else {
2223
Ok(()) // Zero means success for CloudABI
2324
}

src/dummy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010
use crate::{error::UNSUPPORTED, Error};
1111

1212
pub fn getrandom_inner(_: &mut [u8]) -> Result<(), Error> {
13-
Err(Error::internal(UNSUPPORTED))
13+
Err(UNSUPPORTED)
1414
}

src/error.rs

+52-81
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,21 @@ use core::num::NonZeroU32;
1313
/// The [`Error::raw_os_error()`] will indicate if the error is from the OS, and
1414
/// if so, which error code the OS gave the application. If such an error is
1515
/// encountered, please consult with your system documentation.
16+
///
17+
/// Internally this type is a NonZeroU32, with certain values reserved for
18+
/// certain purposes, see [`Error::INTERNAL_START`] and [`Error::CUSTOM_START`].
1619
#[derive(Copy, Clone, Eq, PartialEq)]
1720
pub struct Error(NonZeroU32);
1821

19-
// This NonZeroU32 in Error has enough room for two types of errors:
20-
// - OS Errors: in range [1, 1 << 31) (i.e. positive i32 values)
21-
// - Custom Errors: in range [1 << 31, 1 << 32) (in blocks of 1 << 16)
22-
const CUSTOM_START: u32 = 1 << 31;
23-
const BLOCK_SIZE: u32 = 1 << 16;
24-
2522
impl Error {
26-
/// Create a new error from a raw OS error number (errno).
27-
#[inline]
28-
pub fn from_os_error(errno: i32) -> Self {
29-
assert!(errno > 0);
30-
Self(NonZeroU32::new(errno as u32).unwrap())
31-
}
23+
/// Codes below this point represent OS Errors (i.e. positive i32 values).
24+
/// Codes at or above this point, but below [`Error::CUSTOM_START`] are
25+
/// reserved for use by the `rand` and `getrandom` crates.
26+
pub const INTERNAL_START: u32 = 1 << 31;
3227

33-
/// Crate a custom error in the provided block (group of 2^16 error codes).
34-
/// The provided block must not be negative, and block 0 is reserved for
35-
/// custom errors in the `getrandom` crate.
36-
#[inline]
37-
pub fn custom_error(block: i16, code: u16) -> Self {
38-
assert!(block >= 0);
39-
let n = CUSTOM_START + (block as u16 as u32) * BLOCK_SIZE + (code as u32);
40-
Self(NonZeroU32::new(n).unwrap())
41-
}
28+
/// Codes at or above this point can be used by users to define their own
29+
/// custom errors.
30+
pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30);
4231

4332
/// Extract the raw OS error code (if this error came from the OS)
4433
///
@@ -47,33 +36,21 @@ impl Error {
4736
/// error value can still be formatted via the `Diplay` implementation.
4837
#[inline]
4938
pub fn raw_os_error(&self) -> Option<i32> {
50-
self.try_os_error().ok()
39+
if self.0.get() < Self::INTERNAL_START {
40+
Some(self.0.get() as i32)
41+
} else {
42+
None
43+
}
5144
}
5245

5346
/// Extract the bare error code.
5447
///
5548
/// This code can either come from the underlying OS, or be a custom error.
56-
/// Use [`raw_os_error()`] to disambiguate.
49+
/// Use [`Error::raw_os_error()`] to disambiguate.
5750
#[inline]
5851
pub fn code(&self) -> NonZeroU32 {
5952
self.0
6053
}
61-
62-
/// Helper method for creating internal errors
63-
#[allow(dead_code)]
64-
pub(crate) fn internal(code: u16) -> Self {
65-
Self::custom_error(0, code)
66-
}
67-
68-
/// Returns either the OS error or a (block, code) pair
69-
fn try_os_error(&self) -> Result<i32, (i16, u16)> {
70-
if self.0.get() < CUSTOM_START {
71-
Ok(self.0.get() as i32)
72-
} else {
73-
let offset = self.0.get() - CUSTOM_START;
74-
Err(((offset / BLOCK_SIZE) as i16, (offset % BLOCK_SIZE) as u16))
75-
}
76-
}
7754
}
7855

7956
#[cfg(any(unix, target_os = "redox"))]
@@ -96,44 +73,34 @@ fn os_err_desc(_errno: i32, _buf: &mut [u8]) -> Option<&str> {
9673
impl fmt::Debug for Error {
9774
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9875
let mut dbg = f.debug_struct("Error");
99-
match self.try_os_error() {
100-
Ok(errno) => {
101-
dbg.field("os_error", &errno);
102-
let mut buf = [0u8; 128];
103-
if let Some(desc) = os_err_desc(errno, &mut buf) {
104-
dbg.field("description", &desc);
105-
}
106-
}
107-
Err((0, code)) => {
108-
dbg.field("internal_code", &code);
109-
if let Some(desc) = internal_desc(code) {
110-
dbg.field("description", &desc);
111-
}
112-
}
113-
Err((block, code)) => {
114-
dbg.field("block", &block);
115-
dbg.field("custom_code", &code);
76+
if let Some(errno) = self.raw_os_error() {
77+
dbg.field("os_error", &errno);
78+
let mut buf = [0u8; 128];
79+
if let Some(desc) = os_err_desc(errno, &mut buf) {
80+
dbg.field("description", &desc);
11681
}
82+
} else if let Some(desc) = internal_desc(*self) {
83+
dbg.field("internal_code", &self.0.get());
84+
dbg.field("description", &desc);
85+
} else {
86+
dbg.field("unknown_code", &self.0.get());
11787
}
11888
dbg.finish()
11989
}
12090
}
12191

12292
impl fmt::Display for Error {
12393
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124-
match self.try_os_error() {
125-
Ok(errno) => {
126-
let mut buf = [0u8; 128];
127-
match os_err_desc(errno, &mut buf) {
128-
Some(desc) => f.write_str(desc),
129-
None => write!(f, "OS Error: {}", errno),
130-
}
131-
}
132-
Err((0, code)) => match internal_desc(code) {
94+
if let Some(errno) = self.raw_os_error() {
95+
let mut buf = [0u8; 128];
96+
match os_err_desc(errno, &mut buf) {
13397
Some(desc) => f.write_str(desc),
134-
None => write!(f, "Internal Error: {}", code),
135-
},
136-
Err((block, code)) => write!(f, "Custom Error: block={}, code={}", block, code),
98+
None => write!(f, "OS Error: {}", errno),
99+
}
100+
} else if let Some(desc) = internal_desc(*self) {
101+
f.write_str(desc)
102+
} else {
103+
write!(f, "Unknown Error: {}", self.0.get())
137104
}
138105
}
139106
}
@@ -145,19 +112,23 @@ impl From<NonZeroU32> for Error {
145112
}
146113

147114
/// Internal Error constants
148-
pub(crate) const UNSUPPORTED: u16 = 0;
149-
pub(crate) const UNKNOWN_IO_ERROR: u16 = 1;
150-
pub(crate) const SEC_RANDOM_FAILED: u16 = 2;
151-
pub(crate) const RTL_GEN_RANDOM_FAILED: u16 = 3;
152-
pub(crate) const FAILED_RDRAND: u16 = 4;
153-
pub(crate) const NO_RDRAND: u16 = 5;
154-
pub(crate) const BINDGEN_CRYPTO_UNDEF: u16 = 6;
155-
pub(crate) const BINDGEN_GRV_UNDEF: u16 = 7;
156-
pub(crate) const STDWEB_NO_RNG: u16 = 8;
157-
pub(crate) const STDWEB_RNG_FAILED: u16 = 9;
158-
159-
fn internal_desc(code: u16) -> Option<&'static str> {
160-
match code {
115+
pub(crate) const UNSUPPORTED: Error = internal_error(0);
116+
pub(crate) const UNKNOWN_IO_ERROR: Error = internal_error(1);
117+
pub(crate) const SEC_RANDOM_FAILED: Error = internal_error(2);
118+
pub(crate) const RTL_GEN_RANDOM_FAILED: Error = internal_error(3);
119+
pub(crate) const FAILED_RDRAND: Error = internal_error(4);
120+
pub(crate) const NO_RDRAND: Error = internal_error(5);
121+
pub(crate) const BINDGEN_CRYPTO_UNDEF: Error = internal_error(6);
122+
pub(crate) const BINDGEN_GRV_UNDEF: Error = internal_error(7);
123+
pub(crate) const STDWEB_NO_RNG: Error = internal_error(8);
124+
pub(crate) const STDWEB_RNG_FAILED: Error = internal_error(9);
125+
126+
const fn internal_error(n: u16) -> Error {
127+
Error(unsafe { NonZeroU32::new_unchecked(Error::INTERNAL_START + n as u32) })
128+
}
129+
130+
fn internal_desc(error: Error) -> Option<&'static str> {
131+
match error {
161132
UNSUPPORTED => Some("getrandom: this target is not supported"),
162133
UNKNOWN_IO_ERROR => Some("Unknown std::io::Error"),
163134
SEC_RANDOM_FAILED => Some("SecRandomCopyBytes: call failed"),

src/error_impls.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ extern crate std;
99

1010
use crate::{error::UNKNOWN_IO_ERROR, Error};
1111
use core::convert::From;
12+
use core::num::NonZeroU32;
1213
use std::io;
1314

1415
impl From<io::Error> for Error {
1516
fn from(err: io::Error) -> Self {
16-
match err.raw_os_error() {
17-
Some(errno) => Self::from_os_error(errno),
18-
None => Self::internal(UNKNOWN_IO_ERROR),
17+
if let Some(errno) = err.raw_os_error() {
18+
if let Some(code) = NonZeroU32::new(errno as u32) {
19+
return Error::from(code);
20+
}
1921
}
22+
UNKNOWN_IO_ERROR
2023
}
2124
}
2225

src/ios.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extern "C" {
2424
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
2525
let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, dest.len(), dest.as_mut_ptr()) };
2626
if ret == -1 {
27-
Err(Error::internal(SEC_RANDOM_FAILED))
27+
Err(SEC_RANDOM_FAILED)
2828
} else {
2929
Ok(())
3030
}

src/rdrand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
3737
// Keep looping in case this was a false positive.
3838
}
3939
}
40-
Err(Error::internal(FAILED_RDRAND))
40+
Err(FAILED_RDRAND)
4141
}
4242

4343
// "rdrand" target feature requires "+rdrnd" flag, see https://github.com/rust-lang/rust/issues/49653.
@@ -64,7 +64,7 @@ fn is_rdrand_supported() -> bool {
6464

6565
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
6666
if !is_rdrand_supported() {
67-
return Err(Error::internal(NO_RDRAND));
67+
return Err(NO_RDRAND);
6868
}
6969

7070
// SAFETY: After this point, rdrand is supported, so calling the rdrand

src/util_libc.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// except according to those terms.
88
use crate::util::LazyUsize;
99
use crate::Error;
10+
use core::num::NonZeroU32;
1011
use core::ptr::NonNull;
1112

1213
cfg_if! {
@@ -24,7 +25,7 @@ cfg_if! {
2425
}
2526

2627
pub fn last_os_error() -> Error {
27-
Error::from_os_error(unsafe { *errno_location() })
28+
Error::from(NonZeroU32::new(unsafe { *errno_location() } as u32).unwrap())
2829
}
2930

3031
// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function:

src/wasi.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88

99
//! Implementation for WASI
1010
use crate::Error;
11+
use core::num::NonZeroU32;
1112

1213
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
1314
let ret =
1415
unsafe { libc::__wasi_random_get(dest.as_mut_ptr() as *mut libc::c_void, dest.len()) };
15-
if ret != 0 {
16-
error!("WASI: __wasi_random_get: failed with {}", ret);
17-
Err(Error::from_os_error(ret.into()))
16+
if let Some(code) = NonZeroU32::new(ret as u32) {
17+
error!("WASI: __wasi_random_get: failed with {}", errno);
18+
Err(Error::from(code))
1819
} else {
1920
Ok(()) // Zero means success for WASI
2021
}

src/wasm32_bindgen.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ fn getrandom_init() -> Result<RngSource, Error> {
7979
// we're in an older web browser and the OS RNG isn't available.
8080
let crypto = this.crypto();
8181
if crypto.is_undefined() {
82-
return Err(Error::internal(BINDGEN_CRYPTO_UNDEF));
82+
return Err(BINDGEN_CRYPTO_UNDEF);
8383
}
8484

8585
// Test if `crypto.getRandomValues` is undefined as well
8686
let crypto: BrowserCrypto = crypto.into();
8787
if crypto.get_random_values_fn().is_undefined() {
88-
return Err(Error::internal(BINDGEN_GRV_UNDEF));
88+
return Err(BINDGEN_GRV_UNDEF);
8989
}
9090

9191
// Ok! `self.crypto.getRandomValues` is a defined value, so let's

src/wasm32_stdweb.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ fn getrandom_init() -> Result<RngSource, Error> {
6969
} else {
7070
let err: WebError = js! { return @{ result }.error }.try_into().unwrap();
7171
error!("getrandom unavailable: {}", err);
72-
Err(Error::internal(STDWEB_NO_RNG))
72+
Err(STDWEB_NO_RNG)
7373
}
7474
}
7575

@@ -105,7 +105,7 @@ fn getrandom_fill(source: RngSource, dest: &mut [u8]) -> Result<(), Error> {
105105
if js! { return @{ result.as_ref() }.success } != true {
106106
let err: WebError = js! { return @{ result }.error }.try_into().unwrap();
107107
error!("getrandom failed: {}", err);
108-
return Err(Error::internal(STDWEB_RNG_FAILED));
108+
return Err(STDWEB_RNG_FAILED);
109109
}
110110
}
111111
Ok(())

src/windows.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
1919
for chunk in dest.chunks_mut(u32::max_value() as usize) {
2020
let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr(), chunk.len() as u32) };
2121
if ret == 0 {
22-
return Err(Error::internal(RTL_GEN_RANDOM_FAILED));
22+
return Err(RTL_GEN_RANDOM_FAILED);
2323
}
2424
}
2525
Ok(())

0 commit comments

Comments
 (0)