1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! Error types for this crate.

use std::fmt;

/// [`std::result::Result`] with the error type filled in.
pub type Result<T> = std::result::Result<T, Error>;

/// Indicates the type of an error that can occur during JWS processing.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
	/// A required header parameter is missing.
	MissingHeaderParam,

	/// A header param was found but it's value is invalid.
	InvalidHeaderParam,

	/// The MAC algorithm indicates by the JWS header is not supported by the used [`crate::Verifier`].
	UnsupportedMacAlgorithm,

	/// The message being processed is not valid.
	InvalidMessage,

	/// The signature of a message being verified is invalid.
	InvalidSignature,

	/// An error that doesn't match any of the other types.
	Other,
}

/// An error that can occur during JWS processing.
///
/// An error consists of an [`ErrorKind`] indicating the type of error,
/// and a human readable message.
///
/// The message is purely for human consumption.
/// It should not be used by error handling code to change handling logic.
#[derive(Clone, Debug)]
pub struct Error{
	kind:    ErrorKind,
	message: String,
}

impl ErrorKind {
	fn with_message(self, message: impl Into<String>) -> Error {
		Error{kind: self, message: message.into()}
	}
}

impl Error {
	#![allow(non_upper_case_globals)]

	pub const Other                   : ErrorKind = ErrorKind::Other;
	pub const MissingHeaderParam      : ErrorKind = ErrorKind::MissingHeaderParam;
	pub const InvalidHeaderParam      : ErrorKind = ErrorKind::InvalidHeaderParam;
	pub const UnsupportedMacAlgorithm : ErrorKind = ErrorKind::UnsupportedMacAlgorithm;
	pub const InvalidMessage          : ErrorKind = ErrorKind::InvalidMessage;
	pub const InvalidSignature        : ErrorKind = ErrorKind::InvalidSignature;

	/// Get the kind of error.
	pub fn kind(&self) -> ErrorKind {
		self.kind
	}

	/// Get the error message.
	pub fn message(&self) -> &str {
		&self.message
	}

	/// Create a new error of type [`ErrorKind::Other`] with a given message.
	pub fn other(message: impl Into<String>) -> Self {
		ErrorKind::Other.with_message(message)
	}

	/// Create a new error of type [`ErrorKind::MissingHeaderParam`] with a given message.
	pub fn missing_header_param(message: impl Into<String>) -> Self {
		ErrorKind::MissingHeaderParam.with_message(message)
	}

	/// Create a new error of type [`ErrorKind::InvalidHeaderParam`] with a given message.
	pub fn invalid_header_param(message: impl Into<String>) -> Self {
		ErrorKind::InvalidHeaderParam.with_message(message)
	}

	/// Create a new error of type [`ErrorKind::UnsupportedMacAlgorithm`] with a given message.
	pub fn unsupported_mac_algorithm(message: impl Into<String>) -> Self {
		ErrorKind::UnsupportedMacAlgorithm.with_message(message)
	}

	/// Create a new error of type [`ErrorKind::InvalidMessage`] with a given message.
	pub fn invalid_message(message: impl Into<String>) -> Self {
		ErrorKind::InvalidMessage.with_message(message)
	}

	/// Create a new error of type [`ErrorKind::InvalidSignature`] with a given message.
	pub fn invalid_signature(message: impl Into<String>) -> Self {
		ErrorKind::InvalidSignature.with_message(message)
	}
}


impl fmt::Display for ErrorKind {
	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		match self {
			ErrorKind::Other                   => write!(formatter, "unspecified error"),
			ErrorKind::MissingHeaderParam      => write!(formatter, "missing header parameter"),
			ErrorKind::InvalidHeaderParam      => write!(formatter, "invalid header parameter"),
			ErrorKind::UnsupportedMacAlgorithm => write!(formatter, "unsupported MAC algorithm"),
			ErrorKind::InvalidMessage          => write!(formatter, "invalid message"),
			ErrorKind::InvalidSignature        => write!(formatter, "invalid signature"),
		}
	}
}

impl fmt::Display for Error {
	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		if self.message.is_empty() {
			write!(formatter, "{}", self.kind)
		} else {
			write!(formatter, "{}: {}", self.kind, self.message)
		}
	}
}