Anki/rslib/src/backend/error.rs
RumovZ c521753057
Refactor error handling (#2136)
* Add crate snafu

* Replace all inline structs in AnkiError

* Derive Snafu on AnkiError

* Use snafu for card type errors

* Use snafu whatever error for InvalidInput

* Use snafu for NotFoundError and improve message

* Use snafu for FileIoError to attach context

Remove IoError.
Add some context-attaching helpers to replace code returning bare
io::Errors.

* Add more context-attaching io helpers

* Add message, context and backtrace to new snafus

* Utilize error context and backtrace on frontend

* Rename LocalizedError -> BackendError.
* Remove DocumentedError.
* Have all backend exceptions inherit BackendError.

* Rename localized(_description) -> message

* Remove accidentally committed experimental trait

* invalid_input_context -> ok_or_invalid

* ensure_valid_input! -> require!

* Always return `Err` from `invalid_input!`

Instead of a Result to unwrap, the macro accepts a source error now.

* new_tempfile_in_parent -> new_tempfile_in_parent_of

* ok_or_not_found -> or_not_found

* ok_or_invalid -> or_invalid

* Add crate convert_case

* Use unqualified lowercase type name

* Remove uses of snafu::ensure

* Allow public construction of InvalidInputErrors (dae)

Needed to port the AnkiDroid changes.

* Make into_protobuf() public (dae)

Also required for AnkiDroid. Not sure why it worked previously - possible
bug in older Rust version?
2022-10-21 18:02:12 +10:00

63 lines
2.5 KiB
Rust

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{
error::{AnkiError, SyncErrorKind},
pb,
pb::backend_error::Kind,
prelude::*,
};
impl AnkiError {
pub fn into_protobuf(self, tr: &I18n) -> pb::BackendError {
let message = self.message(tr);
let help_page = self.help_page().map(|page| page as i32);
let context = self.context();
let backtrace = self.backtrace();
let kind = match self {
AnkiError::InvalidInput { .. } => Kind::InvalidInput,
AnkiError::TemplateError { .. } => Kind::TemplateParse,
AnkiError::DbError { .. } => Kind::DbError,
AnkiError::NetworkError { .. } => Kind::NetworkError,
AnkiError::SyncError { source } => source.kind.into(),
AnkiError::Interrupted => Kind::Interrupted,
AnkiError::CollectionNotOpen => Kind::InvalidInput,
AnkiError::CollectionAlreadyOpen => Kind::InvalidInput,
AnkiError::JsonError { .. } => Kind::JsonError,
AnkiError::ProtoError { .. } => Kind::ProtoError,
AnkiError::NotFound { .. } => Kind::NotFoundError,
AnkiError::Deleted => Kind::Deleted,
AnkiError::Existing => Kind::Exists,
AnkiError::FilteredDeckError { .. } => Kind::FilteredDeckError,
AnkiError::SearchError { .. } => Kind::SearchError,
AnkiError::CardTypeError { .. } => Kind::CardTypeError,
AnkiError::ParseNumError => Kind::InvalidInput,
AnkiError::InvalidRegex { .. } => Kind::InvalidInput,
AnkiError::UndoEmpty => Kind::UndoEmpty,
AnkiError::MultipleNotetypesSelected => Kind::InvalidInput,
AnkiError::DatabaseCheckRequired => Kind::InvalidInput,
AnkiError::CustomStudyError { .. } => Kind::CustomStudyError,
AnkiError::ImportError { .. } => Kind::ImportError,
AnkiError::FileIoError { .. } => Kind::IoError,
AnkiError::MediaCheckRequired => Kind::InvalidInput,
AnkiError::InvalidId => Kind::InvalidInput,
};
pb::BackendError {
kind: kind as i32,
message,
help_page,
context,
backtrace,
}
}
}
impl From<SyncErrorKind> for Kind {
fn from(err: SyncErrorKind) -> Self {
match err {
SyncErrorKind::AuthFailed => Kind::SyncAuthError,
_ => Kind::SyncOtherError,
}
}
}