| 1 | use std::convert::Infallible; |
| 2 | use std::fmt::{self, Display}; |
| 3 | |
| 4 | /// The [`Result`](std::result::Result) type with [`Error`] as default error type |
| 5 | pub type Result<I, E = Error> = std::result::Result<I, E>; |
| 6 | |
| 7 | /// rinja error type |
| 8 | /// |
| 9 | /// # Feature Interaction |
| 10 | /// |
| 11 | /// If the feature `serde_json` is enabled an |
| 12 | /// additional error variant `Json` is added. |
| 13 | /// |
| 14 | /// # Why not `failure`/`error-chain`? |
| 15 | /// |
| 16 | /// Error from `error-chain` are not `Sync` which |
| 17 | /// can lead to problems e.g. when this is used |
| 18 | /// by a crate which use `failure`. Implementing |
| 19 | /// `Fail` on the other hand prevents the implementation |
| 20 | /// of `std::error::Error` until specialization lands |
| 21 | /// on stable. While errors impl. `Fail` can be |
| 22 | /// converted to a type impl. `std::error::Error` |
| 23 | /// using a adapter the benefits `failure` would |
| 24 | /// bring to this crate are small, which is why |
| 25 | /// `std::error::Error` was used. |
| 26 | #[non_exhaustive ] |
| 27 | #[derive (Debug)] |
| 28 | pub enum Error { |
| 29 | /// formatting error |
| 30 | Fmt, |
| 31 | /// an error raised by using `?` in a template |
| 32 | Custom(Box<dyn std::error::Error + Send + Sync>), |
| 33 | /// json conversion error |
| 34 | #[cfg (feature = "serde_json" )] |
| 35 | Json(serde_json::Error), |
| 36 | } |
| 37 | |
| 38 | impl std::error::Error for Error { |
| 39 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { |
| 40 | match *self { |
| 41 | Error::Fmt => None, |
| 42 | Error::Custom(ref err: &Box) => Some(err.as_ref()), |
| 43 | #[cfg (feature = "serde_json" )] |
| 44 | Error::Json(ref err) => Some(err), |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | impl Display for Error { |
| 50 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 51 | match self { |
| 52 | Error::Fmt => write!(formatter, "formatting error" ), |
| 53 | Error::Custom(err: &Box) => write!(formatter, " {err}" ), |
| 54 | #[cfg (feature = "serde_json" )] |
| 55 | Error::Json(err) => write!(formatter, "json conversion error: {err}" ), |
| 56 | } |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | impl From<fmt::Error> for Error { |
| 61 | #[inline ] |
| 62 | fn from(_: fmt::Error) -> Self { |
| 63 | Error::Fmt |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | #[cfg (feature = "serde_json" )] |
| 68 | impl From<serde_json::Error> for Error { |
| 69 | #[inline ] |
| 70 | fn from(err: serde_json::Error) -> Self { |
| 71 | Error::Json(err) |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | impl From<Infallible> for Error { |
| 76 | #[inline ] |
| 77 | fn from(value: Infallible) -> Self { |
| 78 | match value {} |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | #[cfg (test)] |
| 83 | mod tests { |
| 84 | use super::Error; |
| 85 | |
| 86 | #[allow (dead_code)] |
| 87 | trait AssertSendSyncStatic: Send + Sync + 'static {} |
| 88 | impl AssertSendSyncStatic for Error {} |
| 89 | } |
| 90 | |