11use anyhow:: Error ;
22use std:: any:: Any ;
3+ use std:: error:: Error as StdError ;
34use std:: fmt:: { Debug , Display } ;
45use std:: io:: { Error as IoError , ErrorKind } ;
56use std:: time:: { SystemTime , UNIX_EPOCH } ;
@@ -20,35 +21,35 @@ pub fn now() -> u64 {
2021 . as_secs ( )
2122}
2223
23- // E allows all StdError + Send + Sync + 'static or AnyhowError as this can only be constructed from the former
2424pub ( crate ) fn error < I , E > ( err : I ) -> E
2525where
26- I : Into < Error > + ' static ,
26+ I : Into < Box < dyn StdError + Send + Sync > > + ' static ,
2727 E : From < IoError > + Display + Debug + Send + Sync + ' static ,
2828{
29- // specialization if error is E or IoError
30- // gets optimized away at compile time
3129 let mut err = Some ( err) ;
30+
3231 if let Some ( err) = Any :: downcast_mut :: < Option < E > > ( & mut err) {
3332 return err. take ( ) . unwrap ( ) ;
3433 }
34+
3535 if let Some ( err) = Any :: downcast_mut :: < Option < IoError > > ( & mut err) {
3636 return err. take ( ) . unwrap ( ) . into ( ) ;
3737 }
3838
39- let err = err. unwrap ( ) . into ( ) ;
40-
41- let err = match err. downcast :: < E > ( ) {
42- Ok ( err) => return err,
43- Err ( err) => err,
44- } ;
45-
46- let err = match err. downcast :: < IoError > ( ) {
47- Ok ( err) => err,
48- Err ( err) => IoError :: new ( ErrorKind :: Other , err) ,
49- } ;
39+ if let Some ( err) = Any :: downcast_mut :: < Option < Error > > ( & mut err) {
40+ let err = match err. take ( ) . unwrap ( ) . downcast :: < E > ( ) {
41+ Ok ( err) => return err,
42+ Err ( err) => err,
43+ } ;
44+
45+ let err = match err. downcast :: < IoError > ( ) {
46+ Ok ( err) => err,
47+ Err ( err) => IoError :: new ( ErrorKind :: Other , err) ,
48+ } ;
49+ return err. into ( ) ;
50+ }
5051
51- err. into ( )
52+ IoError :: new ( ErrorKind :: Other , err. unwrap ( ) ) . into ( )
5253}
5354
5455pub ( crate ) fn uuid ( ) -> String {
@@ -57,7 +58,7 @@ pub(crate) fn uuid() -> String {
5758
5859#[ cfg( test) ]
5960mod tests {
60- use anyhow:: anyhow;
61+ use anyhow:: { anyhow, Error } ;
6162 use std:: io:: { Error as IoError , ErrorKind } ;
6263 use std:: thread;
6364 use std:: time:: Duration ;
@@ -108,6 +109,17 @@ mod tests {
108109 }
109110 }
110111
112+ #[ test]
113+ fn self_error_works ( ) {
114+ let expected = acme_lib:: Error :: Other ( "Test" . to_owned ( ) ) ;
115+
116+ let actual = acme_lib:: Error :: Other ( "Test" . to_owned ( ) ) ;
117+ let actual: acme_lib:: Error = error ( actual) ;
118+
119+ assert_eq ! ( format!( "{:?}" , expected) , format!( "{:?}" , actual) ) ;
120+ assert_eq ! ( format!( "{}" , expected) , format!( "{}" , actual) ) ;
121+ }
122+
111123 #[ test]
112124 fn io_error_works ( ) {
113125 let expected = IoError :: new ( ErrorKind :: InvalidData , "Hallo" ) ;
@@ -116,21 +128,48 @@ mod tests {
116128 let actual = extract_error ( error ( actual) ) ;
117129
118130 assert_eq ! ( format!( "{:?}" , expected) , format!( "{:?}" , actual) ) ;
131+ assert_eq ! ( format!( "{}" , expected) , format!( "{}" , actual) ) ;
119132 }
120133
121134 #[ test]
122- fn error_works ( ) {
123- let expected = anyhow ! ( "test" ) ;
135+ fn anyhow_works ( ) {
136+ let expected = acme_lib:: Error :: Other ( "Test" . to_owned ( ) ) ;
137+
138+ let actual = Error :: new ( acme_lib:: Error :: Other ( "Test" . to_owned ( ) ) ) ;
139+ let actual: acme_lib:: Error = error ( actual) ;
140+
141+ assert_eq ! ( format!( "{:?}" , expected) , format!( "{:?}" , actual) ) ;
142+ assert_eq ! ( format!( "{}" , expected) , format!( "{}" , actual) ) ;
143+ }
144+
145+ #[ test]
146+ fn anyhow_io_works ( ) {
147+ let expected = IoError :: from ( ErrorKind :: Other ) ;
148+
149+ let actual = Error :: new ( IoError :: from ( ErrorKind :: Other ) ) ;
150+ let actual = extract_error ( error ( actual) ) ;
151+
152+ assert_eq ! ( format!( "{:?}" , expected) , format!( "{:?}" , actual) ) ;
153+ assert_eq ! ( format!( "{}" , expected) , format!( "{}" , actual) ) ;
154+ }
124155
125- let actual = extract_error ( error ( anyhow ! ( "test" ) ) ) ;
156+ #[ test]
157+ fn anyhow_error_works ( ) {
158+ let expected = IoError :: new ( ErrorKind :: Other , anyhow ! ( "Test" ) ) ;
126159
127- assert_eq ! ( ErrorKind :: Other , actual. kind ( ) ) ;
160+ let actual = extract_error ( error ( anyhow ! ( "Test" ) ) ) ;
128161
129- // is not equal because original error gets boxed in an io error
130- assert_ne ! ( format!( "{:?}" , expected) , format!( "{:?}" , actual) ) ;
162+ assert_eq ! ( format!( "{:?}" , expected) , format!( "{:?}" , actual) ) ;
163+ assert_eq ! ( format!( "{}" , expected) , format!( "{}" , actual) ) ;
164+ }
131165
132- // here we access the actual inner error
133- let actual = actual. into_inner ( ) . expect ( "Error has no inner error" ) ;
166+ #[ test]
167+ fn error_works ( ) {
168+ let expected = IoError :: new ( ErrorKind :: Other , "Test" ) ;
169+
170+ let actual = extract_error ( error ( "Test" ) ) ;
171+
172+ assert_eq ! ( format!( "{:?}" , expected) , format!( "{:?}" , actual) ) ;
134173 assert_eq ! ( format!( "{}" , expected) , format!( "{}" , actual) ) ;
135174 }
136175}
0 commit comments