1use error_support::{ErrorHandling, GetErrorHandling};
7use remote_settings::RemoteSettingsError;
8
9#[derive(Debug, thiserror::Error)]
13pub enum Error {
14 #[error("Error opening database: {0}")]
15 OpenDatabase(#[from] sql_support::open_database::Error),
16
17 #[error("Error executing SQL: {inner} (context: {context})")]
18 Sql {
19 inner: rusqlite::Error,
20 context: String,
21 },
22
23 #[error("Serialization error: {0}")]
24 Serialization(String),
25
26 #[error("Error from Remote Settings: {0}")]
27 RemoteSettings(#[from] RemoteSettingsError),
28
29 #[error("Remote settings record is missing an attachment (id: u64)")]
30 MissingAttachment(String),
31
32 #[error("Operation interrupted")]
33 Interrupted(#[from] interrupt_support::Interrupted),
34
35 #[error("SuggestStoreBuilder {0}")]
36 SuggestStoreBuilder(String),
37}
38
39impl Error {
40 fn sql(e: rusqlite::Error, context: impl Into<String>) -> Self {
41 Self::Sql {
42 inner: e,
43 context: context.into(),
44 }
45 }
46}
47
48impl From<rusqlite::Error> for Error {
49 fn from(e: rusqlite::Error) -> Self {
50 Self::sql(e, "<none>")
51 }
52}
53
54impl From<serde_json::Error> for Error {
55 fn from(e: serde_json::Error) -> Self {
56 Self::Serialization(e.to_string())
57 }
58}
59
60#[extend::ext(name=RusqliteResultExt)]
61pub impl<T> Result<T, rusqlite::Error> {
62 fn with_context(self, context: &str) -> Result<T, Error> {
64 self.map_err(|e| Error::sql(e, context))
65 }
66}
67
68#[derive(Debug, thiserror::Error, uniffi::Error)]
71#[non_exhaustive]
72pub enum SuggestApiError {
73 #[error("Network error: {reason}")]
74 Network { reason: String },
75 #[error("Backoff")]
77 Backoff { seconds: u64 },
78 #[error("Interrupted")]
80 Interrupted,
81 #[error("Other error: {reason}")]
82 Other { reason: String },
83}
84
85impl GetErrorHandling for Error {
88 type ExternalError = SuggestApiError;
89
90 fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {
91 match self {
92 Self::Interrupted(_) => ErrorHandling::convert(SuggestApiError::Interrupted),
94 Self::RemoteSettings(RemoteSettingsError::Network { reason }) => {
96 ErrorHandling::convert(SuggestApiError::Network {
97 reason: reason.clone(),
98 })
99 .log_warning()
100 }
101 Self::RemoteSettings(RemoteSettingsError::Backoff { seconds }) => {
105 ErrorHandling::convert(SuggestApiError::Backoff { seconds: *seconds })
106 .report_error("suggest-backoff")
107 }
108 _ => ErrorHandling::convert(SuggestApiError::Other {
109 reason: self.to_string(),
110 })
111 .report_error("suggest-unexpected"),
112 }
113 }
114}