66//! handler will be used, which will print the error to `stderr`.
77
88use std:: {
9+ error:: Error as StdError ,
910 fmt:: { self , Display } ,
1011 io, result,
1112} ;
@@ -18,6 +19,81 @@ use crate::utils::const_assert;
1819#[ cfg( feature = "multi-thread" ) ]
1920use crate :: { sink:: Task , RecordOwned } ;
2021
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+
2197/// Contains most errors of this crate.
2298#[ derive( Error , Debug ) ]
2399#[ non_exhaustive]
@@ -26,20 +102,20 @@ pub enum Error {
26102 ///
27103 /// [`Formatter`]: crate::formatter::Formatter
28104 #[ error( "format record error: {0}" ) ]
29- FormatRecord ( fmt:: Error ) ,
105+ FormatRecord ( ErasableError < fmt:: Error > ) ,
30106
31107 /// Returned by [`Sink`]s when an error occurs in writing a record to the
32108 /// target.
33109 ///
34110 /// [`Sink`]: crate::sink::Sink
35111 #[ error( "write record error: {0}" ) ]
36- WriteRecord ( io:: Error ) ,
112+ WriteRecord ( ErasableError < io:: Error > ) ,
37113
38114 /// Returned by [`Sink`]s when an error occurs in flushing the buffer.
39115 ///
40116 /// [`Sink`]: crate::sink::Sink
41117 #[ error( "flush buffer error: {0}" ) ]
42- FlushBuffer ( io:: Error ) ,
118+ FlushBuffer ( ErasableError < io:: Error > ) ,
43119
44120 /// Returned by [`Sink`]s when an error occurs in creating a directory.
45121 ///
0 commit comments