1use std::fmt as std_fmt;
4use super::{BoxError, Error};
5
6pub struct Main(BoxError);
19
20impl std_fmt::Debug for Main {
21 fn fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result {
22 let err = crate::new::wrap_ref(&*self.0);
23 write!(f, "{:+#}", err)
24 }
25}
26
27impl<E: Into<BoxError>> From<E> for Main {
28 fn from(err: E) -> Main {
29 Main(err.into())
30 }
31}
32
33pub fn fmt<'a>(err: &'a dyn Error) -> impl std_fmt::Display + 'a {
51 ::new::wrap_ref(err)
52}
53
54#[cfg(test)]
55mod tests {
56 use std::fmt;
57 use std::io;
58
59 use {BoxError, Error};
60
61 #[derive(Debug)]
62 struct Naive(Option<BoxError>);
63
64 impl fmt::Display for Naive {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 "naive".fmt(f)
67 }
68 }
69
70 impl Error for Naive {
71 fn source(&self) -> Option<&(dyn Error + 'static)> {
72 self.0.as_ref().map(|e| &**e as _)
73 }
74 }
75
76 #[test]
77 fn chain_wraps_outside_errors() {
78 let a = "a";
79
80 let err = io::Error::new(io::ErrorKind::Other, a);
82 assert_eq!(format!("{}", super::fmt(&err)), a);
83 assert_eq!(format!("{:.0}", super::fmt(&err)), a);
84 assert_eq!(format!("{:+}", super::fmt(&err)), a);
85 assert_eq!(format!("{:+.0}", super::fmt(&err)), a);
86
87 let err = Naive(Some(err.into()));
89 let naive = "naive";
90 let naive_a = "naive: a";
91 assert_eq!(format!("{}", super::fmt(&err)), naive);
92 assert_eq!(format!("{:.0}", super::fmt(&err)), naive);
93 assert_eq!(format!("{:+}", super::fmt(&err)), naive_a);
94 assert_eq!(format!("{:+.0}", super::fmt(&err)), naive);
95 assert_eq!(format!("{:+.1}", super::fmt(&err)), naive_a);
96 }
97
98 #[test]
99 fn chain_wraps_our_errors() {
100 let err = ::wrap("b", "a");
101 let b = "b";
102 let b_a = "b: a";
103 assert_eq!(format!("{}", super::fmt(&err)), b);
104 assert_eq!(format!("{:.0}", super::fmt(&err)), b);
105 assert_eq!(format!("{:+}", super::fmt(&err)), b_a);
106 assert_eq!(format!("{:+.0}", super::fmt(&err)), b);
107 assert_eq!(format!("{:+.1}", super::fmt(&err)), b_a);
108 }
109
110 #[derive(Debug)]
114 struct OneDeep(BoxError);
115
116 impl fmt::Display for OneDeep {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 if f.sign_minus() {
119 write!(f, "one deep")
120 } else {
121 write!(f, "one deep: {}", self.0)
122 }
123 }
124 }
125
126 impl Error for OneDeep {
127 fn source(&self) -> Option<&(dyn Error + 'static)> {
128 Some(&*self.0)
129 }
130 }
131
132 #[test]
133 fn one_deep_is_passed_minus() {
134 let orig = ::new("a");
135 let one_deep = OneDeep(orig.into());
136
137 assert_eq!(format!("{}", one_deep), "one deep: a");
138
139 let err = ::wrap("b", one_deep);
140 let b = "b";
141 let b_1 = "b: one deep";
142 let b_1_a = "b: one deep: a";
143 assert_eq!(format!("{}", err), b);
144 assert_eq!(format!("{:.0}", err), b);
145 assert_eq!(format!("{:+}", err), b_1_a);
146 assert_eq!(format!("{:+.0}", err), b);
147 assert_eq!(format!("{:+.1}", err), b_1);
148 }
149
150 #[test]
151 fn one_deep_opaque_is_passed_minus() {
152 let orig = ::new("a");
153 let one_deep = ::opaque(OneDeep(orig.into()));
154
155 assert_eq!(format!("{}", one_deep), "one deep: a");
156
157 let err = ::wrap("b", one_deep);
158 let b = "b";
159 let b_1 = "b: one deep";
160 let b_1_a = "b: one deep: a";
161 assert_eq!(format!("{}", err), b);
162 assert_eq!(format!("{:.0}", err), b);
163 assert_eq!(format!("{:+}", err), b_1_a);
164 assert_eq!(format!("{:+.0}", err), b);
165 assert_eq!(format!("{:+.1}", err), b_1);
166 }
167}