use std::fmt as std_fmt;
use super::{BoxError, Error};
pub struct Main(BoxError);
impl std_fmt::Debug for Main {
fn fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result {
let err = crate::new::wrap_ref(&*self.0);
write!(f, "{:+#}", err)
}
}
impl<E: Into<BoxError>> From<E> for Main {
fn from(err: E) -> Main {
Main(err.into())
}
}
pub fn fmt<'a>(err: &'a dyn Error) -> impl std_fmt::Display + 'a {
::new::wrap_ref(err)
}
#[cfg(test)]
mod tests {
use std::fmt;
use std::io;
use {BoxError, Error};
#[derive(Debug)]
struct Naive(Option<BoxError>);
impl fmt::Display for Naive {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"naive".fmt(f)
}
}
impl Error for Naive {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.0.as_ref().map(|e| &**e as _)
}
}
#[test]
fn chain_wraps_outside_errors() {
let a = "a";
let err = io::Error::new(io::ErrorKind::Other, a);
assert_eq!(format!("{}", super::fmt(&err)), a);
assert_eq!(format!("{:.0}", super::fmt(&err)), a);
assert_eq!(format!("{:+}", super::fmt(&err)), a);
assert_eq!(format!("{:+.0}", super::fmt(&err)), a);
let err = Naive(Some(err.into()));
let naive = "naive";
let naive_a = "naive: a";
assert_eq!(format!("{}", super::fmt(&err)), naive);
assert_eq!(format!("{:.0}", super::fmt(&err)), naive);
assert_eq!(format!("{:+}", super::fmt(&err)), naive_a);
assert_eq!(format!("{:+.0}", super::fmt(&err)), naive);
assert_eq!(format!("{:+.1}", super::fmt(&err)), naive_a);
}
#[test]
fn chain_wraps_our_errors() {
let err = ::wrap("b", "a");
let b = "b";
let b_a = "b: a";
assert_eq!(format!("{}", super::fmt(&err)), b);
assert_eq!(format!("{:.0}", super::fmt(&err)), b);
assert_eq!(format!("{:+}", super::fmt(&err)), b_a);
assert_eq!(format!("{:+.0}", super::fmt(&err)), b);
assert_eq!(format!("{:+.1}", super::fmt(&err)), b_a);
}
#[derive(Debug)]
struct OneDeep(BoxError);
impl fmt::Display for OneDeep {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if f.sign_minus() {
write!(f, "one deep")
} else {
write!(f, "one deep: {}", self.0)
}
}
}
impl Error for OneDeep {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&*self.0)
}
}
#[test]
fn one_deep_is_passed_minus() {
let orig = ::new("a");
let one_deep = OneDeep(orig.into());
assert_eq!(format!("{}", one_deep), "one deep: a");
let err = ::wrap("b", one_deep);
let b = "b";
let b_1 = "b: one deep";
let b_1_a = "b: one deep: a";
assert_eq!(format!("{}", err), b);
assert_eq!(format!("{:.0}", err), b);
assert_eq!(format!("{:+}", err), b_1_a);
assert_eq!(format!("{:+.0}", err), b);
assert_eq!(format!("{:+.1}", err), b_1);
}
#[test]
fn one_deep_opaque_is_passed_minus() {
let orig = ::new("a");
let one_deep = ::opaque(OneDeep(orig.into()));
assert_eq!(format!("{}", one_deep), "one deep: a");
let err = ::wrap("b", one_deep);
let b = "b";
let b_1 = "b: one deep";
let b_1_a = "b: one deep: a";
assert_eq!(format!("{}", err), b);
assert_eq!(format!("{:.0}", err), b);
assert_eq!(format!("{:+}", err), b_1_a);
assert_eq!(format!("{:+.0}", err), b);
assert_eq!(format!("{:+.1}", err), b_1);
}
}