use crate::disk::error::{clone_disk_err, DiskError}; use std::io; use tracing_error::{SpanTrace, SpanTraceStatus}; pub type StdError = Box; pub type Result = std::result::Result; #[derive(Debug)] pub struct Error { inner: Box, span_trace: SpanTrace, } impl Error { /// Create a new error from a `std::error::Error`. #[must_use] #[track_caller] pub fn new(source: T) -> Self { Self::from_std_error(source.into()) } /// Create a new error from a `std::error::Error`. #[must_use] #[track_caller] pub fn from_std_error(inner: StdError) -> Self { Self { inner, span_trace: SpanTrace::capture(), } } /// Create a new error from a string. #[must_use] #[track_caller] pub fn from_string(s: impl Into) -> Self { Self::msg(s) } /// Create a new error from a string. #[must_use] #[track_caller] pub fn msg(s: impl Into) -> Self { Self::from_std_error(s.into().into()) } /// Returns `true` if the inner type is the same as `T`. #[inline] pub fn is(&self) -> bool { self.inner.is::() } /// Returns some reference to the inner value if it is of type `T`, or /// `None` if it isn't. #[inline] pub fn downcast_ref(&self) -> Option<&T> { self.inner.downcast_ref() } /// Returns some mutable reference to the inner value if it is of type `T`, or /// `None` if it isn't. #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { self.inner.downcast_mut() } pub fn to_io_err(&self) -> Option { self.downcast_ref::() .map(|e| io::Error::new(e.kind(), e.to_string())) } } impl From for Error { fn from(e: T) -> Self { Self::new(e) } } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.inner)?; if self.span_trace.status() != SpanTraceStatus::EMPTY { write!(f, "\nspan_trace:\n{}", self.span_trace)?; } Ok(()) } } impl Clone for Error { fn clone(&self) -> Self { if let Some(e) = self.downcast_ref::() { clone_disk_err(e) } else if let Some(e) = self.downcast_ref::() { if let Some(code) = e.raw_os_error() { Error::new(io::Error::from_raw_os_error(code)) } else { Error::new(io::Error::new(e.kind(), e.to_string())) } } else { // TODO: 优化其他类型 Error::msg(self.to_string()) } } }