use crate::model::{BlankNodeIdParseError, IriParseError, LanguageTagParseError}; use crate::sparql::SparqlParseError; use rio_turtle::TurtleError; use rio_xml::RdfXmlError; use std::convert::Infallible; use std::error; use std::fmt; use std::io; use std::string::FromUtf8Error; /// The Oxigraph error type. /// /// The `wrap` method allows us to make this type wrap any implementation of `std::error::Error`. /// This type also avoids heap allocations for the most common cases of Oxigraph errors. #[derive(Debug)] pub struct Error { inner: ErrorKind, } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.inner { ErrorKind::Msg { msg } => write!(f, "{}", msg), ErrorKind::Io(e) => e.fmt(f), ErrorKind::FromUtf8(e) => e.fmt(f), ErrorKind::Iri(e) => e.fmt(f), ErrorKind::BlankNode(e) => e.fmt(f), ErrorKind::LanguageTag(e) => e.fmt(f), ErrorKind::Other(e) => e.fmt(f), } } } impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match &self.inner { ErrorKind::Msg { .. } => None, ErrorKind::Io(e) => Some(e), ErrorKind::FromUtf8(e) => Some(e), ErrorKind::Iri(e) => Some(e), ErrorKind::BlankNode(e) => Some(e), ErrorKind::LanguageTag(e) => Some(e), ErrorKind::Other(e) => Some(e.as_ref()), } } } impl Error { /// Wraps another error. pub fn wrap(error: impl error::Error + Send + Sync + 'static) -> Self { Self { inner: ErrorKind::Other(Box::new(error)), } } /// Builds an error from a printable error message. pub fn msg(msg: impl Into) -> Self { Self { inner: ErrorKind::Msg { msg: msg.into() }, } } } #[derive(Debug)] enum ErrorKind { Msg { msg: String }, Io(io::Error), FromUtf8(FromUtf8Error), Iri(IriParseError), BlankNode(BlankNodeIdParseError), LanguageTag(LanguageTagParseError), Other(Box), } impl From for Error { fn from(error: Infallible) -> Self { match error {} } } impl From for Error { fn from(error: io::Error) -> Self { Self { inner: ErrorKind::Io(error), } } } impl From for Error { fn from(error: FromUtf8Error) -> Self { Self { inner: ErrorKind::FromUtf8(error), } } } impl From for Error { fn from(error: IriParseError) -> Self { Self { inner: ErrorKind::Iri(error), } } } impl From for Error { fn from(error: BlankNodeIdParseError) -> Self { Self { inner: ErrorKind::BlankNode(error), } } } impl From for Error { fn from(error: LanguageTagParseError) -> Self { Self { inner: ErrorKind::LanguageTag(error), } } } impl From for Error { fn from(error: TurtleError) -> Self { Self::wrap(error) } } impl From for Error { fn from(error: RdfXmlError) -> Self { Self::wrap(error) } } impl From for Error { fn from(error: quick_xml::Error) -> Self { Self::wrap(error) } } impl From for Error { fn from(error: SparqlParseError) -> Self { Self::wrap(error) } } #[cfg(feature = "rocksdb")] impl From for Error { fn from(error: rocksdb::Error) -> Self { Self::wrap(error) } } #[cfg(feature = "sled")] impl From for Error { fn from(error: sled::Error) -> Self { Self::wrap(error) } } /// Traits that allows unwrapping only infallible results pub(crate) trait UnwrapInfallible { type Value; fn unwrap_infallible(self) -> Self::Value; } impl UnwrapInfallible for Result { type Value = T; fn unwrap_infallible(self) -> T { match self { Ok(value) => value, Err(error) => match error {}, } } }