From 98232c7bc262dd3902b8f3e299196ab9c83fb355 Mon Sep 17 00:00:00 2001
From: Robin Krahl <robin.krahl@ireas.org>
Date: Wed, 8 Jul 2020 12:08:26 +0200
Subject: Remove sync::PoisonError from Error::PoisonError
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Previously, the Error::PoisonError contained the sync::PoisonError that
caused the error.  This is problematic as sync::PoisonError does not
implement Send, making it impossible to use the Error enum with the
anyhow crate.  At the same time, storing the sync::PoisonError is not
very useful.  If a user wants to access the poisoned lock, they can call
the force_take function.

Therefore we remove the sync::PoisonError value from the Error::
PoisonError variant.  This also allows us to simplify the
From<sync::PoisonError<…>> and From<sync::TryLockError<…>>
implementations as we no longer need to know the type of the mutex that
caused the error.

For more information, see this thread:
	https://lists.sr.ht/~ireas/nitrokey-rs-dev/%3C68ed0f3f-d98f-63bc-04d2-81b6d6cde560%40posteo.net%3E
---
 src/error.rs | 16 ++++++++--------
 src/lib.rs   | 11 ++++-------
 2 files changed, 12 insertions(+), 15 deletions(-)

(limited to 'src')

diff --git a/src/error.rs b/src/error.rs
index 7bea3f2..e0698a2 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -21,7 +21,7 @@ pub enum Error {
     /// A library usage error.
     LibraryError(LibraryError),
     /// An error that occurred due to a poisoned lock.
-    PoisonError(sync::PoisonError<sync::MutexGuard<'static, crate::Manager>>),
+    PoisonError,
     /// An error that occurred during random number generation.
     RandError(Box<dyn error::Error>),
     /// An error that is caused by an unexpected value returned by libnitrokey.
@@ -72,14 +72,14 @@ impl From<str::Utf8Error> for Error {
     }
 }
 
-impl From<sync::PoisonError<sync::MutexGuard<'static, crate::Manager>>> for Error {
-    fn from(error: sync::PoisonError<sync::MutexGuard<'static, crate::Manager>>) -> Self {
-        Error::PoisonError(error)
+impl<T> From<sync::PoisonError<T>> for Error {
+    fn from(_error: sync::PoisonError<T>) -> Self {
+        Error::PoisonError
     }
 }
 
-impl From<sync::TryLockError<sync::MutexGuard<'static, crate::Manager>>> for Error {
-    fn from(error: sync::TryLockError<sync::MutexGuard<'static, crate::Manager>>) -> Self {
+impl<T> From<sync::TryLockError<T>> for Error {
+    fn from(error: sync::TryLockError<T>) -> Self {
         match error {
             sync::TryLockError::Poisoned(err) => err.into(),
             sync::TryLockError::WouldBlock => Error::ConcurrentAccessError,
@@ -100,7 +100,7 @@ impl error::Error for Error {
             Error::CommunicationError(ref err) => Some(err),
             Error::ConcurrentAccessError => None,
             Error::LibraryError(ref err) => Some(err),
-            Error::PoisonError(ref err) => Some(err),
+            Error::PoisonError => None,
             Error::RandError(ref err) => Some(err.as_ref()),
             Error::UnexpectedError(_) => None,
             Error::UnknownError(_) => None,
@@ -117,7 +117,7 @@ impl fmt::Display for Error {
             Error::CommunicationError(ref err) => write!(f, "Communication error: {}", err),
             Error::ConcurrentAccessError => write!(f, "Internal error: concurrent access"),
             Error::LibraryError(ref err) => write!(f, "Library error: {}", err),
-            Error::PoisonError(_) => write!(f, "Internal error: poisoned lock"),
+            Error::PoisonError => write!(f, "Internal error: poisoned lock"),
             Error::RandError(ref err) => write!(f, "RNG error: {}", err),
             Error::UnexpectedError(ref s) => write!(f, "An unexpected error occurred: {}", s),
             Error::UnknownError(ref err) => write!(f, "Unknown error: {}", err),
diff --git a/src/lib.rs b/src/lib.rs
index 3fa3ae3..5b72d63 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -470,13 +470,10 @@ pub fn take() -> Result<sync::MutexGuard<'static, Manager>, Error> {
 /// [`ConcurrentAccessError`]: struct.Error.html#variant.ConcurrentAccessError
 /// [`Manager`]: struct.Manager.html
 pub fn force_take() -> Result<sync::MutexGuard<'static, Manager>, Error> {
-    match take() {
-        Ok(guard) => Ok(guard),
-        Err(err) => match err {
-            Error::PoisonError(err) => Ok(err.into_inner()),
-            err => Err(err),
-        },
-    }
+    MANAGER.try_lock().or_else(|err| match err {
+        sync::TryLockError::Poisoned(err) => Ok(err.into_inner()),
+        sync::TryLockError::WouldBlock => Err(Error::ConcurrentAccessError),
+    })
 }
 
 /// List all connected Nitrokey devices.
-- 
cgit v1.2.3


From 3f402dc13530ce4de167bae843200cfbd72ed69b Mon Sep 17 00:00:00 2001
From: Robin Krahl <robin.krahl@ireas.org>
Date: Wed, 8 Jul 2020 22:22:10 +0200
Subject: Remove Error::RandError variant

Since we update rand_os to version 0.2 in commit
6c138eaa850c745b97b7e48a201db0cbaad8e1e0, the random number generation
can no longer fail.  Therefore the Error::RandError variant is no longer
needed.

As we did not want to break the public API, we still kept the RandError
variant.  This patch removes the RandError variant for good.
---
 CHANGELOG.md | 1 +
 src/error.rs | 4 ----
 2 files changed, 1 insertion(+), 4 deletions(-)

(limited to 'src')

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dddccb1..651a50e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ SPDX-License-Identifier: CC0-1.0
 # Unreleased
 - Refactor the `Error` enum so that it is `Send`, `Sync` and `'static`:
   - Remove the `sync::PoisonError` from the `PoisonError` variant.
+  - Remove `Error::RandError` variant.
 
 # v0.6.0 (2020-02-03)
 - Add `String` value to the `Error::UnexpectedError` variant.
diff --git a/src/error.rs b/src/error.rs
index e0698a2..995741b 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -22,8 +22,6 @@ pub enum Error {
     LibraryError(LibraryError),
     /// An error that occurred due to a poisoned lock.
     PoisonError,
-    /// An error that occurred during random number generation.
-    RandError(Box<dyn error::Error>),
     /// An error that is caused by an unexpected value returned by libnitrokey.
     UnexpectedError(String),
     /// An unknown error returned by libnitrokey.
@@ -101,7 +99,6 @@ impl error::Error for Error {
             Error::ConcurrentAccessError => None,
             Error::LibraryError(ref err) => Some(err),
             Error::PoisonError => None,
-            Error::RandError(ref err) => Some(err.as_ref()),
             Error::UnexpectedError(_) => None,
             Error::UnknownError(_) => None,
             Error::UnsupportedModelError => None,
@@ -118,7 +115,6 @@ impl fmt::Display for Error {
             Error::ConcurrentAccessError => write!(f, "Internal error: concurrent access"),
             Error::LibraryError(ref err) => write!(f, "Library error: {}", err),
             Error::PoisonError => write!(f, "Internal error: poisoned lock"),
-            Error::RandError(ref err) => write!(f, "RNG error: {}", err),
             Error::UnexpectedError(ref s) => write!(f, "An unexpected error occurred: {}", s),
             Error::UnknownError(ref err) => write!(f, "Unknown error: {}", err),
             Error::UnsupportedModelError => write!(f, "Unsupported Nitrokey model"),
-- 
cgit v1.2.3


From f1e83eb81879412e1de9898238ba58289bb6cb24 Mon Sep 17 00:00:00 2001
From: Robin Krahl <robin.krahl@ireas.org>
Date: Wed, 8 Jul 2020 22:58:41 +0200
Subject: Ensure Error trait implementations

The anyhow crate requires that error types are error::Error, Send, Sync
and 'static.  This patch implements a simple static assertion that our
Error type implements these traits.
---
 src/error.rs | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

(limited to 'src')

diff --git a/src/error.rs b/src/error.rs
index 995741b..1aa1793 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -267,3 +267,22 @@ impl fmt::Display for LibraryError {
         })
     }
 }
+
+// build our own static assertion that Error implements error::Error, Send, Sync, 'static
+
+struct Helper<T>(T);
+
+trait Assert {
+    fn assert() -> bool;
+}
+
+impl<T: error::Error + Send + Sync + 'static> Assert for Helper<T> {
+    fn assert() -> bool {
+        true
+    }
+}
+
+#[allow(unused)]
+fn assert_error_impl() {
+    let _ = Helper::<Error>::assert();
+}
-- 
cgit v1.2.3