6
6
//! handler will be used, which will print the error to `stderr`.
7
7
8
8
use std:: {
9
+ error:: Error as StdError ,
9
10
fmt:: { self , Display } ,
10
11
io, result,
11
12
} ;
@@ -18,6 +19,81 @@ use crate::utils::const_assert;
18
19
#[ cfg( feature = "multi-thread" ) ]
19
20
use crate :: { sink:: Task , RecordOwned } ;
20
21
22
+ /// Stores an error that can either be typed or erased.
23
+ ///
24
+ /// This wrapper is mainly used for returning arbitrary errors from downstream
25
+ /// implementors.
26
+ ///
27
+ /// # Examples
28
+ ///
29
+ /// ```
30
+ /// use std::{error::Error, fmt, io};
31
+ ///
32
+ /// use spdlog::{error::ErasableError, formatter::Formatter, prelude::*, sink::Sink, Record};
33
+ ///
34
+ /// #[derive(Debug)]
35
+ /// struct MyError;
36
+ ///
37
+ /// impl Error for MyError {}
38
+ ///
39
+ /// impl fmt::Display for MyError {
40
+ /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41
+ /// write!(f, "MyError")
42
+ /// }
43
+ /// }
44
+ ///
45
+ /// struct MySink;
46
+ ///
47
+ /// impl Sink for MySink {
48
+ /// fn log(&self, record: &Record) -> spdlog::Result<()> {
49
+ /// let err: MyError = /* Something went wrong */
50
+ /// # MyError;
51
+ /// // `err` can not be converted to `io::Error`, so we use `Erased`
52
+ /// Err(spdlog::Error::WriteRecord(ErasableError::erase(MyError)))
53
+ /// }
54
+ ///
55
+ /// fn flush(&self) -> spdlog::Result<()> {
56
+ /// let err: io::Error = /* Something went wrong */
57
+ /// # io::Error::new(io::ErrorKind::NotFound, "");
58
+ /// // `err` is a `io::Error`, so we use `Typed`
59
+ /// Err(spdlog::Error::FlushBuffer(err.into()))
60
+ /// }
61
+ ///
62
+ /// fn level_filter(&self) -> LevelFilter /* ... */
63
+ /// # { unimplemented!() }
64
+ /// fn set_level_filter(&self, level_filter: LevelFilter) /* ... */
65
+ /// # { unimplemented!() }
66
+ /// fn set_formatter(&self, formatter: Box<dyn Formatter>) /* ... */
67
+ /// # { unimplemented!() }
68
+ /// fn set_error_handler(&self, handler: Option<spdlog::ErrorHandler>) /* ... */
69
+ /// # { unimplemented!() }
70
+ /// }
71
+ /// ```
72
+ #[ derive( Error , Debug ) ]
73
+ pub enum ErasableError < E : StdError > {
74
+ /// A concrete error type is held, and the user can access it.
75
+ #[ error( "{0}" ) ]
76
+ Typed ( E ) ,
77
+ /// The concrete type may not match, thus it is erased to a basic
78
+ /// `dyn std::error::Error`.
79
+ #[ error( "{0}" ) ]
80
+ Erased ( Box < dyn StdError > ) ,
81
+ }
82
+
83
+ impl < E : StdError > ErasableError < E > {
84
+ /// Erase a typed error to a basic `Box<dyn std::error::Error>`.
85
+ #[ must_use]
86
+ pub fn erase < R : StdError + ' static > ( err : R ) -> ErasableError < E > {
87
+ ErasableError :: Erased ( Box :: new ( err) )
88
+ }
89
+ }
90
+
91
+ impl < E : StdError > From < E > for ErasableError < E > {
92
+ fn from ( err : E ) -> Self {
93
+ Self :: Typed ( err)
94
+ }
95
+ }
96
+
21
97
/// Contains most errors of this crate.
22
98
#[ derive( Error , Debug ) ]
23
99
#[ non_exhaustive]
@@ -26,20 +102,20 @@ pub enum Error {
26
102
///
27
103
/// [`Formatter`]: crate::formatter::Formatter
28
104
#[ error( "format record error: {0}" ) ]
29
- FormatRecord ( fmt:: Error ) ,
105
+ FormatRecord ( ErasableError < fmt:: Error > ) ,
30
106
31
107
/// Returned by [`Sink`]s when an error occurs in writing a record to the
32
108
/// target.
33
109
///
34
110
/// [`Sink`]: crate::sink::Sink
35
111
#[ error( "write record error: {0}" ) ]
36
- WriteRecord ( io:: Error ) ,
112
+ WriteRecord ( ErasableError < io:: Error > ) ,
37
113
38
114
/// Returned by [`Sink`]s when an error occurs in flushing the buffer.
39
115
///
40
116
/// [`Sink`]: crate::sink::Sink
41
117
#[ error( "flush buffer error: {0}" ) ]
42
- FlushBuffer ( io:: Error ) ,
118
+ FlushBuffer ( ErasableError < io:: Error > ) ,
43
119
44
120
/// Returned by [`Sink`]s when an error occurs in creating a directory.
45
121
///
0 commit comments