From ea50e6dccb9e13ee175699de0c371cc3b6a23fc8 Mon Sep 17 00:00:00 2001 From: davidj-lb <83679554+davidj-lb@users.noreply.github.com> Date: Thu, 27 May 2021 15:55:42 -0700 Subject: [PATCH] feat(core): Added error downcasting in the style of the master branch (#1252) --- sqlx-core/src/error/database.rs | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/sqlx-core/src/error/database.rs b/sqlx-core/src/error/database.rs index a665fea8..2a436d96 100644 --- a/sqlx-core/src/error/database.rs +++ b/sqlx-core/src/error/database.rs @@ -9,4 +9,65 @@ use std::error::Error as StdError; pub trait DatabaseError: 'static + StdError + Send + Sync { /// Returns the primary, human-readable error message. fn message(&self) -> &str; + + #[doc(hidden)] + fn as_error(&self) -> &(dyn StdError + Send + Sync + 'static); + + #[doc(hidden)] + fn as_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static); + + #[doc(hidden)] + fn into_error(self: Box) -> Box; } + +impl dyn DatabaseError { + /// Downcast a reference to this generic database error to a specific + /// database error type. + /// + /// # Panics + /// + /// Panics if the database error type is not `E`. This is a deliberate contrast from + /// `Error::downcast_ref` which returns `Option<&E>`. In normal usage, you should know the + /// specific error type. In other cases, use `try_downcast_ref`. + pub fn downcast_ref(&self) -> &E { + self.try_downcast_ref().unwrap_or_else(|| { + panic!( + "downcast to wrong DatabaseError type; original error: {}", + self + ) + }) + } + + /// Downcast this generic database error to a specific database error type. + /// + /// # Panics + /// + /// Panics if the database error type is not `E`. This is a deliberate contrast from + /// `Error::downcast` which returns `Option`. In normal usage, you should know the + /// specific error type. In other cases, use `try_downcast`. + pub fn downcast(self: Box) -> Box { + self.try_downcast().unwrap_or_else(|e| { + panic!( + "downcast to wrong DatabaseError type; original error: {}", + e + ) + }) + } + + /// Downcast a reference to this generic database error to a specific + /// database error type. + #[inline] + pub fn try_downcast_ref(&self) -> Option<&E> { + self.as_error().downcast_ref() + } + + /// Downcast this generic database error to a specific database error type. + #[inline] + pub fn try_downcast(self: Box) -> std::result::Result, Box> { + if self.as_error().is::() { + Ok(self.into_error().downcast().unwrap()) + } else { + Err(self) + } + } +} \ No newline at end of file