1use std::error::Error as StdError;
2use std::fmt;
3
4#[derive(Debug)]
5#[non_exhaustive]
6pub struct ErrorDetails {
7 desc: String,
8 src: Option<Box<dyn StdError + Send + Sync + 'static>>,
9}
10
11impl ErrorDetails {
12 pub fn new(desc: impl Into<String>) -> ErrorDetails {
13 ErrorDetails {
14 desc: desc.into(),
15 src: None,
16 }
17 }
18
19 pub fn map(
20 desc: impl Into<String>,
21 src: Box<dyn StdError + Send + Sync + 'static>,
22 ) -> ErrorDetails {
23 ErrorDetails {
24 desc: desc.into(),
25 src: Some(src),
26 }
27 }
28}
29
30impl From<String> for ErrorDetails {
31 fn from(s: String) -> Self {
32 ErrorDetails { desc: s, src: None }
33 }
34}
35
36#[derive(Debug)]
37#[non_exhaustive]
38pub enum Error {
39 InvalidInput(ErrorDetails),
41
42 AlgorithmMismatch(),
44
45 InvalidSignature(),
47
48 TokenExpiredAt(u64),
50
51 MalformedToken(ErrorDetails),
53}
54
55impl StdError for Error {
56 fn source(&self) -> Option<&(dyn StdError + 'static)> {
57 match self {
58 Error::InvalidInput(ErrorDetails { src: Some(s), .. }) => Some(s.as_ref()),
59 Error::AlgorithmMismatch() => None,
60 Error::InvalidSignature() => None,
61 Error::TokenExpiredAt(_) => None,
62 Error::MalformedToken(ErrorDetails { src: Some(s), .. }) => Some(s.as_ref()),
63 _ => None,
64 }
65 }
66}
67
68impl std::fmt::Display for Error {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 match self {
71 Error::InvalidInput(details) => write!(f, "Invalid Input: {}", details.desc),
72 Error::AlgorithmMismatch() => write!(f, "JWT Algorithm Mismatch"),
73 Error::InvalidSignature() => write!(f, "JWT Signature Invalid"),
74 Error::TokenExpiredAt(when) => write!(f, "JWT token expired at {when}"),
75 Error::MalformedToken(details) => write!(f, "JWT claims invalid: {}", details.desc),
76 }
77 }
78}