baseid_wallet_core/
error.rs

1//! Wallet-core error types.
2
3use baseid_core::error::ProtocolError;
4use baseid_core::language::Language;
5use baseid_core::types::CredentialId;
6
7/// Errors specific to wallet-core operations.
8#[derive(Debug, thiserror::Error)]
9pub enum WalletError {
10    #[error("credential not found: {0:?}")]
11    CredentialNotFound(CredentialId),
12    #[error("unsupported credential format: {0}")]
13    UnsupportedFormat(String),
14    #[error("credential parse error: {0}")]
15    CredentialParseError(String),
16    #[error("credential matching failed: {0}")]
17    MatchingFailed(String),
18    #[error("presentation failed: {0}")]
19    PresentationFailed(String),
20    #[error("storage error: {0}")]
21    StorageError(String),
22}
23
24impl baseid_core::error::BilingualError for WalletError {
25    fn message(&self, lang: Language) -> &str {
26        match (self, lang) {
27            (WalletError::CredentialNotFound(_), Language::Fr) => "attestation introuvable",
28            (WalletError::CredentialNotFound(_), _) => "credential not found",
29            (WalletError::UnsupportedFormat(_), Language::Fr) => {
30                "format d'attestation non pris en charge"
31            }
32            (WalletError::UnsupportedFormat(_), _) => "unsupported credential format",
33            (WalletError::CredentialParseError(_), Language::Fr) => {
34                "erreur d'analyse de l'attestation"
35            }
36            (WalletError::CredentialParseError(_), _) => "credential parse error",
37            (WalletError::MatchingFailed(_), Language::Fr) => {
38                "échec de la correspondance des attestations"
39            }
40            (WalletError::MatchingFailed(_), _) => "credential matching failed",
41            (WalletError::PresentationFailed(_), Language::Fr) => "échec de la présentation",
42            (WalletError::PresentationFailed(_), _) => "presentation failed",
43            (WalletError::StorageError(_), Language::Fr) => "erreur de stockage",
44            (WalletError::StorageError(_), _) => "storage error",
45        }
46    }
47}
48
49impl From<WalletError> for baseid_core::Error {
50    fn from(e: WalletError) -> Self {
51        match &e {
52            WalletError::CredentialNotFound(_) => ProtocolError::General.into(),
53            WalletError::UnsupportedFormat(_) => ProtocolError::General.into(),
54            WalletError::CredentialParseError(_) => ProtocolError::InvalidResponse.into(),
55            WalletError::MatchingFailed(_) => ProtocolError::General.into(),
56            WalletError::PresentationFailed(_) => ProtocolError::General.into(),
57            WalletError::StorageError(_) => ProtocolError::Transport.into(),
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn error_display_all_variants() {
68        let variants: Vec<WalletError> = vec![
69            WalletError::CredentialNotFound(CredentialId("id-1".into())),
70            WalletError::UnsupportedFormat("unknown".into()),
71            WalletError::CredentialParseError("bad json".into()),
72            WalletError::MatchingFailed("no match".into()),
73            WalletError::PresentationFailed("signing failed".into()),
74            WalletError::StorageError("disk full".into()),
75        ];
76        for v in &variants {
77            assert!(!v.to_string().is_empty());
78        }
79    }
80
81    #[test]
82    fn bilingual_error_en_fr() {
83        use baseid_core::error::BilingualError;
84        let e = WalletError::CredentialNotFound(CredentialId("x".into()));
85        assert_eq!(e.message(Language::En), "credential not found");
86        assert_eq!(e.message(Language::Fr), "attestation introuvable");
87    }
88
89    #[test]
90    fn error_conversion_all_variants() {
91        let variants: Vec<WalletError> = vec![
92            WalletError::CredentialNotFound(CredentialId("a".into())),
93            WalletError::UnsupportedFormat("b".into()),
94            WalletError::CredentialParseError("c".into()),
95            WalletError::MatchingFailed("d".into()),
96            WalletError::PresentationFailed("e".into()),
97            WalletError::StorageError("f".into()),
98        ];
99        for v in variants {
100            let core_err: baseid_core::Error = v.into();
101            assert!(!format!("{core_err}").is_empty());
102        }
103    }
104}