jwk_simple/
error.rs

1//! Error types for JWK/JWKS operations.
2//!
3//! This module provides a comprehensive error type that covers all failure
4//! modes in the library. All public functions return `Result<T, Error>` to
5//! maintain the no-panic guarantee.
6
7use std::fmt;
8
9/// The main error type for this crate.
10///
11/// All public functions return `Result<T, Error>` to ensure no panics occur
12/// in library code.
13#[derive(Debug)]
14pub enum Error {
15    /// Failed to parse JSON.
16    Parse(ParseError),
17
18    /// Key validation failed.
19    Validation(ValidationError),
20
21    /// Base64 decoding failed.
22    Base64(base64ct::Error),
23
24    /// Key type mismatch during conversion.
25    KeyTypeMismatch {
26        /// The expected key type.
27        expected: &'static str,
28        /// The actual key type found.
29        actual: String,
30    },
31
32    /// Algorithm mismatch during conversion.
33    AlgorithmMismatch {
34        /// The expected algorithm.
35        expected: &'static str,
36        /// The actual algorithm found.
37        actual: Option<String>,
38    },
39
40    /// Curve mismatch during conversion.
41    CurveMismatch {
42        /// The expected curve.
43        expected: &'static str,
44        /// The actual curve found.
45        actual: String,
46    },
47
48    /// Missing required field.
49    MissingField {
50        /// The name of the missing field.
51        field: &'static str,
52    },
53
54    /// Private key parameters missing when required.
55    MissingPrivateKey,
56
57    /// I/O error (file operations).
58    Io(std::io::Error),
59
60    /// HTTP request error.
61    #[cfg(feature = "http")]
62    Http(reqwest::Error),
63
64    /// Other error (for platform-specific or miscellaneous errors).
65    Other(String),
66}
67
68impl fmt::Display for Error {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        match self {
71            Error::Parse(e) => write!(f, "parse error: {}", e),
72            Error::Validation(e) => write!(f, "validation error: {}", e),
73            Error::Base64(e) => write!(f, "base64 decoding error: {:?}", e),
74            Error::KeyTypeMismatch { expected, actual } => {
75                write!(f, "key type mismatch: expected {}, got {}", expected, actual)
76            }
77            Error::AlgorithmMismatch { expected, actual } => {
78                write!(
79                    f,
80                    "algorithm mismatch: expected {}, got {:?}",
81                    expected, actual
82                )
83            }
84            Error::CurveMismatch { expected, actual } => {
85                write!(f, "curve mismatch: expected {}, got {}", expected, actual)
86            }
87            Error::MissingField { field } => {
88                write!(f, "missing required field: {}", field)
89            }
90            Error::MissingPrivateKey => {
91                write!(f, "private key parameters required but not present")
92            }
93            Error::Io(e) => write!(f, "I/O error: {}", e),
94            #[cfg(feature = "http")]
95            Error::Http(e) => write!(f, "HTTP error: {}", e),
96            Error::Other(msg) => write!(f, "{}", msg),
97        }
98    }
99}
100
101impl std::error::Error for Error {
102    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
103        match self {
104            Error::Parse(e) => Some(e),
105            Error::Validation(e) => Some(e),
106            Error::Io(e) => Some(e),
107            #[cfg(feature = "http")]
108            Error::Http(e) => Some(e),
109            _ => None,
110        }
111    }
112}
113
114impl From<base64ct::Error> for Error {
115    fn from(e: base64ct::Error) -> Self {
116        Error::Base64(e)
117    }
118}
119
120impl From<serde_json::Error> for Error {
121    fn from(e: serde_json::Error) -> Self {
122        Error::Parse(ParseError::Json(e.to_string()))
123    }
124}
125
126impl From<std::io::Error> for Error {
127    fn from(e: std::io::Error) -> Self {
128        Error::Io(e)
129    }
130}
131
132#[cfg(feature = "http")]
133impl From<reqwest::Error> for Error {
134    fn from(e: reqwest::Error) -> Self {
135        Error::Http(e)
136    }
137}
138
139/// Errors that occur during JSON parsing.
140#[derive(Debug)]
141pub enum ParseError {
142    /// Invalid JSON syntax.
143    Json(String),
144    /// Unknown key type.
145    UnknownKeyType(String),
146    /// Unknown algorithm.
147    UnknownAlgorithm(String),
148    /// Unknown curve.
149    UnknownCurve(String),
150    /// Unknown key use.
151    UnknownKeyUse(String),
152    /// Unknown key operation.
153    UnknownKeyOperation(String),
154}
155
156impl fmt::Display for ParseError {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        match self {
159            ParseError::Json(msg) => write!(f, "invalid JSON: {}", msg),
160            ParseError::UnknownKeyType(kty) => write!(f, "unknown key type: {}", kty),
161            ParseError::UnknownAlgorithm(alg) => write!(f, "unknown algorithm: {}", alg),
162            ParseError::UnknownCurve(crv) => write!(f, "unknown curve: {}", crv),
163            ParseError::UnknownKeyUse(use_) => write!(f, "unknown key use: {}", use_),
164            ParseError::UnknownKeyOperation(op) => write!(f, "unknown key operation: {}", op),
165        }
166    }
167}
168
169impl std::error::Error for ParseError {}
170
171/// Errors that occur during key validation.
172#[derive(Debug)]
173pub enum ValidationError {
174    /// Invalid key size for the specified algorithm.
175    InvalidKeySize {
176        /// Expected size in bytes.
177        expected: usize,
178        /// Actual size in bytes.
179        actual: usize,
180        /// Description of what was being validated.
181        context: &'static str,
182    },
183    /// Missing required parameter for key type.
184    MissingParameter(&'static str),
185    /// Inconsistent key parameters (e.g., public and private parts don't match).
186    InconsistentParameters(String),
187    /// Invalid parameter value.
188    InvalidParameter {
189        /// Parameter name.
190        name: &'static str,
191        /// Description of why it's invalid.
192        reason: String,
193    },
194}
195
196impl fmt::Display for ValidationError {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        match self {
199            ValidationError::InvalidKeySize {
200                expected,
201                actual,
202                context,
203            } => {
204                write!(
205                    f,
206                    "invalid key size for {}: expected {} bytes, got {}",
207                    context, expected, actual
208                )
209            }
210            ValidationError::MissingParameter(param) => {
211                write!(f, "missing required parameter: {}", param)
212            }
213            ValidationError::InconsistentParameters(msg) => {
214                write!(f, "inconsistent key parameters: {}", msg)
215            }
216            ValidationError::InvalidParameter { name, reason } => {
217                write!(f, "invalid parameter '{}': {}", name, reason)
218            }
219        }
220    }
221}
222
223impl std::error::Error for ValidationError {}
224
225/// A type alias for `Result<T, Error>`.
226pub type Result<T> = std::result::Result<T, Error>;