autofill/
error.rs
1use error_support::{ErrorHandling, GetErrorHandling};
7use interrupt_support::Interrupted;
8
9pub type ApiResult<T> = std::result::Result<T, AutofillApiError>;
11
12pub type Result<T> = std::result::Result<T, Error>;
14
15#[derive(Debug, thiserror::Error)]
17pub enum AutofillApiError {
18 #[error("Error executing SQL: {reason}")]
19 SqlError { reason: String },
20
21 #[error("Operation interrupted")]
22 InterruptedError,
23
24 #[error("Crypto Error: {reason}")]
25 CryptoError { reason: String },
26
27 #[error("No record with guid exists: {guid}")]
28 NoSuchRecord { guid: String },
29
30 #[error("Unexpected Error: {reason}")]
31 UnexpectedAutofillApiError { reason: String },
32}
33
34#[derive(Debug, thiserror::Error)]
35pub enum Error {
36 #[error("Error opening database: {0}")]
37 OpenDatabaseError(#[from] sql_support::open_database::Error),
38
39 #[error("Error executing SQL: {0}")]
40 SqlError(#[from] rusqlite::Error),
41
42 #[error("IO error: {0}")]
43 IoError(#[from] std::io::Error),
44
45 #[error("Operation interrupted")]
46 InterruptedError(#[from] Interrupted),
47
48 #[error("Illegal database path: {0:?}")]
52 IllegalDatabasePath(std::path::PathBuf),
53
54 #[error("JSON Error: {0}")]
55 JsonError(#[from] serde_json::Error),
56
57 #[error("Invalid sync payload: {0}")]
58 InvalidSyncPayload(String),
59
60 #[error("Crypto Error: {0}")]
61 CryptoError(#[from] jwcrypto::JwCryptoError),
62
63 #[error("Missing local encryption key")]
64 MissingEncryptionKey,
65
66 #[error("No record with guid exists: {0}")]
67 NoSuchRecord(String),
68}
69
70impl GetErrorHandling for Error {
73 type ExternalError = AutofillApiError;
74
75 fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {
76 match self {
77 Self::OpenDatabaseError(e) => ErrorHandling::convert(AutofillApiError::SqlError {
78 reason: e.to_string(),
79 })
80 .report_error("autofill-open-database-error"),
81
82 Self::SqlError(e) => ErrorHandling::convert(AutofillApiError::SqlError {
83 reason: e.to_string(),
84 })
85 .report_error("autofill-sql-error"),
86
87 Self::IoError(e) => {
88 ErrorHandling::convert(AutofillApiError::UnexpectedAutofillApiError {
89 reason: e.to_string(),
90 })
91 .report_error("autofill-io-error")
92 }
93
94 Self::InterruptedError(_) => ErrorHandling::convert(AutofillApiError::InterruptedError),
95
96 Self::IllegalDatabasePath(path) => ErrorHandling::convert(AutofillApiError::SqlError {
97 reason: format!("Path not found: {}", path.to_string_lossy()),
98 })
99 .report_error("autofill-illegal-database-path"),
100
101 Self::JsonError(e) => {
102 ErrorHandling::convert(AutofillApiError::UnexpectedAutofillApiError {
103 reason: e.to_string(),
104 })
105 .report_error("autofill-json-error")
106 }
107
108 Self::InvalidSyncPayload(reason) => {
109 ErrorHandling::convert(AutofillApiError::UnexpectedAutofillApiError {
110 reason: reason.clone(),
111 })
112 .report_error("autofill-invalid-sync-payload")
113 }
114
115 Self::CryptoError(e) => ErrorHandling::convert(AutofillApiError::CryptoError {
116 reason: e.to_string(),
117 })
118 .report_error("autofill-crypto-error"),
119
120 Self::MissingEncryptionKey => ErrorHandling::convert(AutofillApiError::CryptoError {
121 reason: "Missing encryption key".to_string(),
122 })
123 .report_error("autofill-missing-encryption-key"),
124
125 Self::NoSuchRecord(guid) => {
126 ErrorHandling::convert(AutofillApiError::NoSuchRecord { guid: guid.clone() })
127 .log_warning()
128 }
129 }
130 }
131}