api_keys_simplified/
error.rs1use thiserror::Error;
2
3#[derive(Debug, Error)]
9pub enum Error {
10 #[error("Invalid input")]
12 InvalidFormat,
13
14 #[error("Operation failed")]
23 OperationFailed(
24 #[source]
25 #[from]
26 OperationError,
27 ),
28}
29
30#[derive(Debug, Error)]
32pub enum ConfigError {
33 #[error("Prefix must be between 1 and 20 characters")]
34 InvalidPrefixLength,
35
36 #[error("Prefix must contain only alphanumeric characters or underscores")]
37 InvalidPrefixCharacters,
38
39 #[error("Prefix must not contain {0} substring")]
40 InvalidPrefixSubstring(String),
41
42 #[error("Prefix cannot look like a version number (e.g., 'v1', 'v2', 'v42')")]
43 InvalidPrefixVersionLike,
44
45 #[error("String must not be empty")]
46 EmptyString,
47
48 #[error("Entropy must be at least 16 bytes (128 bits)")]
49 EntropyTooLow,
50
51 #[error("Entropy cannot exceed 64 bytes (512 bits)")]
52 EntropyTooHigh,
53
54 #[error("Invalid Argon2 parameters")]
55 InvalidHashParams,
56
57 #[error("Invalid Argon2 hash. Please raise an issue at https://github.com/gpmcp/api-keys-simplified/issues/new"
58 )]
59 InvalidArgon2Hash,
60
61 #[error("Minium checksum length should be 32 bits")]
62 ChecksumLenTooSmall,
63
64 #[error("Checksum length should be at MOST 128 bits")]
65 ChecksumLenTooLarge,
66}
67
68#[derive(Debug, Error)]
70pub enum OperationError {
71 #[error("Key generation failed: {0}")]
72 Generation(String),
73
74 #[error("Hashing failed: {0}")]
75 Hashing(String),
76
77 #[error("Verification failed: {0}")]
78 Verification(String),
79}
80
81pub type Result<T> = std::result::Result<T, Error>;
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test_display_is_generic() {
89 let err =
90 Error::OperationFailed(OperationError::Hashing("detailed salt error".to_string()));
91 assert_eq!(err.to_string(), "Operation failed");
93
94 let debug_str = format!("{:?}", err);
96 assert!(debug_str.contains("Hashing"));
97 assert!(debug_str.contains("salt"));
98 }
99
100 #[test]
101 fn test_error_chaining() {
102 let err = Error::OperationFailed(OperationError::Verification(
103 "argon2 param error".to_string(),
104 ));
105 if let Error::OperationFailed(source) = err {
107 assert!(source.to_string().contains("argon2"));
108 }
109 }
110
111 #[test]
112 fn test_format_errors_are_generic() {
113 let err = Error::InvalidFormat;
114 assert_eq!(err.to_string(), "Invalid input");
115 }
116}