summaryrefslogtreecommitdiff
path: root/core/any_error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/any_error.rs')
-rw-r--r--core/any_error.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/core/any_error.rs b/core/any_error.rs
new file mode 100644
index 000000000..001ca54eb
--- /dev/null
+++ b/core/any_error.rs
@@ -0,0 +1,68 @@
+use std::any::{Any, TypeId};
+use std::convert::From;
+use std::error::Error;
+use std::fmt;
+use std::ops::Deref;
+
+// The Send and Sync traits are required because deno is multithreaded and we
+// need to beable to handle errors across threads.
+pub trait AnyError: Any + Error + Send + Sync + 'static {}
+impl<T> AnyError for T where T: Any + Error + Send + Sync + Sized + 'static {}
+
+#[derive(Debug)]
+pub struct ErrBox(Box<dyn AnyError>);
+
+impl dyn AnyError {
+ pub fn downcast_ref<T: AnyError>(&self) -> Option<&T> {
+ if Any::type_id(self) == TypeId::of::<T>() {
+ let target = self as *const Self as *const T;
+ let target = unsafe { &*target };
+ Some(target)
+ } else {
+ None
+ }
+ }
+}
+
+impl ErrBox {
+ pub fn downcast<T: AnyError>(self) -> Result<T, Self> {
+ if Any::type_id(&*self.0) == TypeId::of::<T>() {
+ let target = Box::into_raw(self.0) as *mut T;
+ let target = unsafe { Box::from_raw(target) };
+ Ok(*target)
+ } else {
+ Err(self)
+ }
+ }
+}
+
+impl AsRef<dyn AnyError> for ErrBox {
+ fn as_ref(&self) -> &dyn AnyError {
+ self.0.as_ref()
+ }
+}
+
+impl Deref for ErrBox {
+ type Target = Box<AnyError>;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T: AnyError> From<T> for ErrBox {
+ fn from(error: T) -> Self {
+ Self(Box::new(error))
+ }
+}
+
+impl From<Box<dyn AnyError>> for ErrBox {
+ fn from(boxed: Box<dyn AnyError>) -> Self {
+ Self(boxed)
+ }
+}
+
+impl fmt::Display for ErrBox {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}