From 73251d52ffa73ba8c40569908677a3900c2300c5 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 9 Aug 2019 12:00:24 +0100 Subject: [PATCH 1/3] Update rand_core::Error in line with getrandom::Error --- rand_core/src/error.rs | 56 ++++++++++++++++++++++++++++++++++++++-- rand_jitter/src/error.rs | 16 +++++++----- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/rand_core/src/error.rs b/rand_core/src/error.rs index 7e8f0c9ba32..67f4ea23385 100644 --- a/rand_core/src/error.rs +++ b/rand_core/src/error.rs @@ -17,7 +17,6 @@ use core::num::NonZeroU32; /// In order to be compatible with `std` and `no_std`, this type has two /// possible implementations: with `std` a boxed `Error` trait object is stored, /// while with `no_std` we merely store an error code. -#[derive(Debug)] pub struct Error { #[cfg(feature="std")] inner: Box, @@ -32,6 +31,7 @@ impl Error { /// /// See also `From`, which is available with and without `std`. #[cfg(feature="std")] + #[inline] pub fn new(err: E) -> Self where E: Into> { @@ -43,6 +43,7 @@ impl Error { /// When configured with `std`, this is a trivial operation and never /// panics. Without `std`, this method is simply unavailable. #[cfg(feature="std")] + #[inline] pub fn inner(&self) -> &(dyn std::error::Error + Send + Sync + 'static) { &*self.inner } @@ -52,15 +53,45 @@ impl Error { /// When configured with `std`, this is a trivial operation and never /// panics. Without `std`, this method is simply unavailable. #[cfg(feature="std")] + #[inline] pub fn take_inner(self) -> Box { self.inner } + /// Codes below this point represent OS Errors (i.e. positive i32 values). + /// Codes at or above this point, but below [`Error::CUSTOM_START`] are + /// reserved for use by the `rand` and `getrandom` crates. + pub const INTERNAL_START: u32 = 1 << 31; + + /// Codes at or above this point can be used by users to define their own + /// custom errors. + pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30); + + /// Extract the raw OS error code (if this error came from the OS) + /// + /// This method is identical to `std::io::Error::raw_os_error()`, except + /// that it works in `no_std` contexts. If this method returns `None`, the + /// error value can still be formatted via the `Diplay` implementation. + #[inline] + pub fn raw_os_error(&self) -> Option { + #[cfg(feature="std")] { + if let Some(e) = self.inner.downcast_ref::() { + return e.raw_os_error(); + } + } + match self.code() { + Some(code) if u32::from(code) < Self::INTERNAL_START => + Some(u32::from(code) as i32), + _ => None, + } + } + /// Retrieve the error code, if any. /// /// If this `Error` was constructed via `From`, then this method /// will return this `NonZeroU32` code (for `no_std` this is always the /// case). Otherwise, this method will return `None`. + #[inline] pub fn code(&self) -> Option { #[cfg(feature="std")] { self.inner.downcast_ref::().map(|c| c.0) @@ -71,18 +102,36 @@ impl Error { } } +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + #[cfg(feature="std")] { + write!(f, "Error {{ inner: {:?} }}", self.inner) + } + #[cfg(all(feature="getrandom", not(feature="std")))] { + getrandom::Error::from(self.code).fmt(f) + } + #[cfg(not(feature="getrandom"))] { + write!(f, "Error {{ code: {} }}", self.code) + } + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[cfg(feature="std")] { write!(f, "{}", self.inner) } - #[cfg(not(feature="std"))] { + #[cfg(all(feature="getrandom", not(feature="std")))] { + getrandom::Error::from(self.code).fmt(f) + } + #[cfg(not(feature="getrandom"))] { write!(f, "error code {}", self.code) } } } impl From for Error { + #[inline] fn from(code: NonZeroU32) -> Self { #[cfg(feature="std")] { Error { inner: Box::new(ErrorCode(code)) } @@ -95,6 +144,7 @@ impl From for Error { #[cfg(feature="getrandom")] impl From for Error { + #[inline] fn from(error: getrandom::Error) -> Self { #[cfg(feature="std")] { Error { inner: Box::new(error) } @@ -107,6 +157,7 @@ impl From for Error { #[cfg(feature="std")] impl std::error::Error for Error { + #[inline] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { self.inner.source() } @@ -114,6 +165,7 @@ impl std::error::Error for Error { #[cfg(feature="std")] impl From for std::io::Error { + #[inline] fn from(error: Error) -> Self { std::io::Error::new(std::io::ErrorKind::Other, error) } diff --git a/rand_jitter/src/error.rs b/rand_jitter/src/error.rs index 3ea72c38424..b54fffacab2 100644 --- a/rand_jitter/src/error.rs +++ b/rand_jitter/src/error.rs @@ -10,24 +10,28 @@ use rand_core::Error; use core::fmt; +/// Base code for all `JitterRng` errors +const ERROR_BASE: u32 = 0xAE53_0400; + /// An error that can occur when [`JitterRng::test_timer`] fails. /// -/// All variants have a value of 0x6e530400 = 1850934272 plus a small +/// All variants have a value of 0xAE530400 = 2924676096 plus a small /// increment (1 through 5). /// /// [`JitterRng::test_timer`]: crate::JitterRng::test_timer #[derive(Debug, Clone, PartialEq, Eq)] +#[repr(u32)] pub enum TimerError { /// No timer available. - NoTimer = 0x6e530401, + NoTimer = ERROR_BASE + 1, /// Timer too coarse to use as an entropy source. - CoarseTimer = 0x6e530402, + CoarseTimer = ERROR_BASE + 2, /// Timer is not monotonically increasing. - NotMonotonic = 0x6e530403, + NotMonotonic = ERROR_BASE + 3, /// Variations of deltas of time too small. - TinyVariantions = 0x6e530404, + TinyVariantions = ERROR_BASE + 4, /// Too many stuck results (indicating no added entropy). - TooManyStuck = 0x6e530405, + TooManyStuck = ERROR_BASE + 5, #[doc(hidden)] __Nonexhaustive, } From 2f9e9b2df6a1bc65416292f24baa96092d929bd7 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 9 Aug 2019 12:08:28 +0100 Subject: [PATCH 2/3] Update rand_core and rand_jitter versions --- rand_core/CHANGELOG.md | 7 ++++++- rand_jitter/CHANGELOG.md | 5 +++++ rand_jitter/Cargo.toml | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md index c96d886bc71..f5edc58cefa 100644 --- a/rand_core/CHANGELOG.md +++ b/rand_core/CHANGELOG.md @@ -4,9 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.5.1] - 2019-09-02 +## [0.5.1] - 2019-08-28 ### Added - `OsRng` added to `rand_core` (#863) +- `Error::INTERNAL_START` and `Error::CUSTOM_START` constants (#864) +- `Error::raw_os_error` method (#864) +- `Debug` and `Display` formatting for `getrandom` error codes without `std` (#864) +### Changed +- Added `#[inline]` to `Error` conversion methods (#864) ## [0.5.0] - 2019-06-06 ### Changed diff --git a/rand_jitter/CHANGELOG.md b/rand_jitter/CHANGELOG.md index 9dd6c0a1ae6..9f4bb7e3edf 100644 --- a/rand_jitter/CHANGELOG.md +++ b/rand_jitter/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.2.1] - 2019-08-16 +### Changed +- `TimerError` changed to `repr(u32)` (#864) +- `TimerError` enum values all increased by `1<<30` to match new `rand_core::Error` range (#864) + ## [0.2.0] - 2019-06-06 - Bump `rand_core` version - Support new `Error` type in `rand_core` 0.5 diff --git a/rand_jitter/Cargo.toml b/rand_jitter/Cargo.toml index 7380f702ebb..5b7e3c3a691 100644 --- a/rand_jitter/Cargo.toml +++ b/rand_jitter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rand_jitter" -version = "0.2.0" +version = "0.2.1" authors = ["The Rand Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" From df0c772680284c8ce19dea71c1d6a906aa25a053 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Thu, 22 Aug 2019 08:20:43 +0100 Subject: [PATCH 3/3] Reconstruct io::Error from raw code if possible in From impl Supplied by newpavlov --- rand_core/src/error.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rand_core/src/error.rs b/rand_core/src/error.rs index 67f4ea23385..30b095c3cff 100644 --- a/rand_core/src/error.rs +++ b/rand_core/src/error.rs @@ -167,7 +167,11 @@ impl std::error::Error for Error { impl From for std::io::Error { #[inline] fn from(error: Error) -> Self { - std::io::Error::new(std::io::ErrorKind::Other, error) + if let Some(code) = error.raw_os_error() { + std::io::Error::from_raw_os_error(code) + } else { + std::io::Error::new(std::io::ErrorKind::Other, error) + } } }