use std::error::Error as StdError;
use std::fmt;
pub type Result<T> = std::result::Result<T, Error>;
pub struct Error {
inner: Box<Inner>,
}
pub(crate) type Source = Box<dyn StdError + Send + Sync>;
struct Inner {
kind: Kind,
source: Option<Source>,
}
impl Error {
pub(crate) fn new(kind: Kind) -> Error {
Error {
inner: Box::new(Inner { kind, source: None }),
}
}
pub(crate) fn with<S: Into<Source>>(mut self, source: S) -> Error {
self.inner.source = Some(source.into());
self
}
pub fn kind(&self) -> &Kind {
&self.inner.kind
}
pub fn invalid_document<E: Into<Source>>(error: E) -> Error {
Error::new(Kind::InvalidDocument).with(error)
}
}
impl fmt::Debug for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut builder = fmt.debug_struct("mongod::Error");
builder.field("kind", &self.inner.kind);
if let Some(ref source) = self.inner.source {
builder.field("source", source);
}
builder.finish()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let desc = match self.inner.kind {
Kind::Bson => "bson error",
Kind::Builder => "builder error",
Kind::Mongodb => "mongodb error",
Kind::InvalidDocument => "invalid document",
Kind::Runtime => "runtime error",
};
if let Some(ref source) = self.inner.source {
write!(f, "{}: {}", desc, source)
} else {
f.write_str(desc)
}
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.inner.source.as_ref().map(|e| &**e as _)
}
}
impl From<crate::ext::bson::de::Error> for Error {
fn from(de: crate::ext::bson::de::Error) -> Self {
Error::invalid_document(de)
}
}
impl From<crate::ext::bson::ser::Error> for Error {
fn from(ser: crate::ext::bson::ser::Error) -> Self {
Error::invalid_document(ser)
}
}
#[derive(Debug)]
pub enum Kind {
Bson,
Builder,
Mongodb,
Runtime,
InvalidDocument,
}
#[allow(dead_code)]
pub(crate) fn bson<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Bson).with(e)
}
#[allow(dead_code)]
pub(crate) fn builder<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Builder).with(e)
}
#[allow(dead_code)]
pub(crate) fn mongodb<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Mongodb).with(e)
}
#[cfg(feature = "blocking")]
pub(crate) fn runtime<E: Into<Source>>(e: E) -> Error {
Error::new(Kind::Runtime).with(e)
}