1use baseid_core::error::ProtocolError;
4use baseid_core::language::Language;
5
6#[derive(Debug, thiserror::Error)]
8pub enum Oid4vciError {
9 #[error("metadata discovery failed: {0}")]
10 MetadataDiscovery(String),
11 #[error("token request failed: {0}")]
12 TokenRequestFailed(String),
13 #[error("credential request failed: {0}")]
14 CredentialRequestFailed(String),
15 #[error("unsupported grant type")]
16 UnsupportedGrantType,
17 #[error("invalid proof of possession")]
18 InvalidProof,
19 #[error("server error: {error} - {error_description}")]
20 ServerError {
21 error: String,
22 error_description: String,
23 },
24}
25
26impl baseid_core::error::BilingualError for Oid4vciError {
27 fn message(&self, lang: Language) -> &str {
28 match (self, lang) {
29 (Oid4vciError::MetadataDiscovery(_), Language::Fr) => {
30 "échec de la découverte des métadonnées"
31 }
32 (Oid4vciError::MetadataDiscovery(_), _) => "metadata discovery failed",
33 (Oid4vciError::TokenRequestFailed(_), Language::Fr) => "échec de la demande de jeton",
34 (Oid4vciError::TokenRequestFailed(_), _) => "token request failed",
35 (Oid4vciError::CredentialRequestFailed(_), Language::Fr) => {
36 "échec de la demande d'attestation"
37 }
38 (Oid4vciError::CredentialRequestFailed(_), _) => "credential request failed",
39 (Oid4vciError::UnsupportedGrantType, Language::Fr) => {
40 "type d'autorisation non pris en charge"
41 }
42 (Oid4vciError::UnsupportedGrantType, _) => "unsupported grant type",
43 (Oid4vciError::InvalidProof, Language::Fr) => "preuve de possession invalide",
44 (Oid4vciError::InvalidProof, _) => "invalid proof of possession",
45 (Oid4vciError::ServerError { .. }, Language::Fr) => "erreur du serveur",
46 (Oid4vciError::ServerError { .. }, _) => "server error",
47 }
48 }
49}
50
51impl From<Oid4vciError> for baseid_core::Error {
52 fn from(e: Oid4vciError) -> Self {
53 match &e {
54 Oid4vciError::MetadataDiscovery(_) | Oid4vciError::TokenRequestFailed(_) => {
55 ProtocolError::InvalidResponse.into()
56 }
57 Oid4vciError::CredentialRequestFailed(_) | Oid4vciError::ServerError { .. } => {
58 ProtocolError::InvalidResponse.into()
59 }
60 Oid4vciError::UnsupportedGrantType | Oid4vciError::InvalidProof => {
61 ProtocolError::General.into()
62 }
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn error_display_metadata_discovery() {
73 let e = Oid4vciError::MetadataDiscovery("network timeout".to_string());
74 assert!(e.to_string().contains("network timeout"));
75 }
76
77 #[test]
78 fn error_display_server_error() {
79 let e = Oid4vciError::ServerError {
80 error: "invalid_grant".to_string(),
81 error_description: "expired".to_string(),
82 };
83 let msg = e.to_string();
84 assert!(msg.contains("invalid_grant"));
85 assert!(msg.contains("expired"));
86 }
87
88 #[test]
89 fn error_conversion_metadata() {
90 let e: baseid_core::Error = Oid4vciError::MetadataDiscovery("x".to_string()).into();
91 let _ = format!("{e}");
93 }
94
95 #[test]
96 fn error_conversion_unsupported_grant() {
97 let e: baseid_core::Error = Oid4vciError::UnsupportedGrantType.into();
98 let _ = format!("{e}");
99 }
100
101 #[test]
102 fn error_conversion_invalid_proof() {
103 let e: baseid_core::Error = Oid4vciError::InvalidProof.into();
104 let _ = format!("{e}");
105 }
106
107 #[test]
108 fn bilingual_error_en() {
109 use baseid_core::error::BilingualError;
110 let e = Oid4vciError::UnsupportedGrantType;
111 assert_eq!(
112 e.message(baseid_core::language::Language::En),
113 "unsupported grant type"
114 );
115 }
116
117 #[test]
118 fn bilingual_error_fr() {
119 use baseid_core::error::BilingualError;
120 let e = Oid4vciError::UnsupportedGrantType;
121 assert_eq!(
122 e.message(baseid_core::language::Language::Fr),
123 "type d'autorisation non pris en charge"
124 );
125 }
126
127 #[test]
128 fn error_conversion_all_variants() {
129 let variants: Vec<Oid4vciError> = vec![
131 Oid4vciError::MetadataDiscovery("a".into()),
132 Oid4vciError::TokenRequestFailed("b".into()),
133 Oid4vciError::CredentialRequestFailed("c".into()),
134 Oid4vciError::UnsupportedGrantType,
135 Oid4vciError::InvalidProof,
136 Oid4vciError::ServerError {
137 error: "e".into(),
138 error_description: "f".into(),
139 },
140 ];
141 for v in variants {
142 let core_err: baseid_core::Error = v.into();
143 assert!(!format!("{core_err}").is_empty());
144 }
145 }
146}