mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 07:22:23 -04:00
split search errors into separate file
This commit is contained in:
parent
094e4ad461
commit
f14a631f68
2 changed files with 136 additions and 128 deletions
|
@ -1,11 +1,14 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
mod search;
|
||||||
|
|
||||||
|
pub use search::{ParseError, SearchErrorKind};
|
||||||
|
|
||||||
use crate::i18n::I18n;
|
use crate::i18n::I18n;
|
||||||
pub use failure::{Error, Fail};
|
pub use failure::{Error, Fail};
|
||||||
use nom::error::{ErrorKind as NomErrorKind, ParseError as NomParseError};
|
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use std::{io, num::ParseIntError, str::Utf8Error};
|
use std::{io, str::Utf8Error};
|
||||||
use tempfile::PathPersistError;
|
use tempfile::PathPersistError;
|
||||||
|
|
||||||
pub type Result<T, E = AnkiError> = std::result::Result<T, E>;
|
pub type Result<T, E = AnkiError> = std::result::Result<T, E>;
|
||||||
|
@ -128,67 +131,7 @@ impl AnkiError {
|
||||||
DbErrorKind::Locked => "Anki already open, or media currently syncing.".into(),
|
DbErrorKind::Locked => "Anki already open, or media currently syncing.".into(),
|
||||||
_ => format!("{:?}", self),
|
_ => format!("{:?}", self),
|
||||||
},
|
},
|
||||||
AnkiError::SearchError(kind) => {
|
AnkiError::SearchError(kind) => kind.localized_description(&tr),
|
||||||
let reason = match kind {
|
|
||||||
SearchErrorKind::MisplacedAnd => tr.search_misplaced_and(),
|
|
||||||
SearchErrorKind::MisplacedOr => tr.search_misplaced_or(),
|
|
||||||
SearchErrorKind::EmptyGroup => tr.search_empty_group(),
|
|
||||||
SearchErrorKind::UnopenedGroup => tr.search_unopened_group(),
|
|
||||||
SearchErrorKind::UnclosedGroup => tr.search_unclosed_group(),
|
|
||||||
SearchErrorKind::EmptyQuote => tr.search_empty_quote(),
|
|
||||||
SearchErrorKind::UnclosedQuote => tr.search_unclosed_quote(),
|
|
||||||
SearchErrorKind::MissingKey => tr.search_missing_key(),
|
|
||||||
SearchErrorKind::UnknownEscape(ctx) => {
|
|
||||||
tr.search_unknown_escape(ctx.replace('`', "'"))
|
|
||||||
}
|
|
||||||
SearchErrorKind::InvalidState(state) => {
|
|
||||||
tr.search_invalid_argument("is:", state.replace('`', "'"))
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchErrorKind::InvalidFlag => tr.search_invalid_flag(),
|
|
||||||
SearchErrorKind::InvalidPropProperty(prop) => {
|
|
||||||
tr.search_invalid_argument("prop:", prop.replace('`', "'"))
|
|
||||||
}
|
|
||||||
SearchErrorKind::InvalidPropOperator(ctx) => {
|
|
||||||
tr.search_invalid_prop_operator(ctx.as_str())
|
|
||||||
}
|
|
||||||
SearchErrorKind::Regex(text) => {
|
|
||||||
format!("<pre>`{}`</pre>", text.replace('`', "'")).into()
|
|
||||||
}
|
|
||||||
SearchErrorKind::Other(Some(info)) => info.into(),
|
|
||||||
SearchErrorKind::Other(None) => tr.search_invalid_other(),
|
|
||||||
SearchErrorKind::InvalidNumber { provided, context } => tr
|
|
||||||
.search_invalid_number(
|
|
||||||
context.replace('`', "'"),
|
|
||||||
provided.replace('`', "'"),
|
|
||||||
),
|
|
||||||
|
|
||||||
SearchErrorKind::InvalidWholeNumber { provided, context } => tr
|
|
||||||
.search_invalid_whole_number(
|
|
||||||
context.replace('`', "'"),
|
|
||||||
provided.replace('`', "'"),
|
|
||||||
),
|
|
||||||
|
|
||||||
SearchErrorKind::InvalidPositiveWholeNumber { provided, context } => tr
|
|
||||||
.search_invalid_positive_whole_number(
|
|
||||||
context.replace('`', "'"),
|
|
||||||
provided.replace('`', "'"),
|
|
||||||
),
|
|
||||||
|
|
||||||
SearchErrorKind::InvalidNegativeWholeNumber { provided, context } => tr
|
|
||||||
.search_invalid_negative_whole_number(
|
|
||||||
context.replace('`', "'"),
|
|
||||||
provided.replace('`', "'"),
|
|
||||||
),
|
|
||||||
|
|
||||||
SearchErrorKind::InvalidAnswerButton { provided, context } => tr
|
|
||||||
.search_invalid_answer_button(
|
|
||||||
context.replace('`', "'"),
|
|
||||||
provided.replace('`', "'"),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
tr.search_invalid_search(reason).into()
|
|
||||||
}
|
|
||||||
AnkiError::InvalidInput { info } => {
|
AnkiError::InvalidInput { info } => {
|
||||||
if info.is_empty() {
|
if info.is_empty() {
|
||||||
tr.errors_invalid_input_empty().into()
|
tr.errors_invalid_input_empty().into()
|
||||||
|
@ -414,71 +357,6 @@ impl From<PathPersistError> for AnkiError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum ParseError<'a> {
|
|
||||||
Anki(&'a str, SearchErrorKind),
|
|
||||||
Nom(&'a str, NomErrorKind),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum SearchErrorKind {
|
|
||||||
MisplacedAnd,
|
|
||||||
MisplacedOr,
|
|
||||||
EmptyGroup,
|
|
||||||
UnopenedGroup,
|
|
||||||
UnclosedGroup,
|
|
||||||
EmptyQuote,
|
|
||||||
UnclosedQuote,
|
|
||||||
MissingKey,
|
|
||||||
UnknownEscape(String),
|
|
||||||
InvalidState(String),
|
|
||||||
InvalidFlag,
|
|
||||||
InvalidPropProperty(String),
|
|
||||||
InvalidPropOperator(String),
|
|
||||||
InvalidNumber { provided: String, context: String },
|
|
||||||
InvalidWholeNumber { provided: String, context: String },
|
|
||||||
InvalidPositiveWholeNumber { provided: String, context: String },
|
|
||||||
InvalidNegativeWholeNumber { provided: String, context: String },
|
|
||||||
InvalidAnswerButton { provided: String, context: String },
|
|
||||||
Regex(String),
|
|
||||||
Other(Option<String>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ParseError<'_>> for AnkiError {
|
|
||||||
fn from(err: ParseError) -> Self {
|
|
||||||
match err {
|
|
||||||
ParseError::Anki(_, kind) => AnkiError::SearchError(kind),
|
|
||||||
ParseError::Nom(_, _) => AnkiError::SearchError(SearchErrorKind::Other(None)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<nom::Err<ParseError<'_>>> for AnkiError {
|
|
||||||
fn from(err: nom::Err<ParseError<'_>>) -> Self {
|
|
||||||
match err {
|
|
||||||
nom::Err::Error(e) => e.into(),
|
|
||||||
nom::Err::Failure(e) => e.into(),
|
|
||||||
nom::Err::Incomplete(_) => AnkiError::SearchError(SearchErrorKind::Other(None)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> NomParseError<&'a str> for ParseError<'a> {
|
|
||||||
fn from_error_kind(input: &'a str, kind: NomErrorKind) -> Self {
|
|
||||||
ParseError::Nom(input, kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append(_: &str, _: NomErrorKind, other: Self) -> Self {
|
|
||||||
other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ParseIntError> for AnkiError {
|
|
||||||
fn from(_err: ParseIntError) -> Self {
|
|
||||||
AnkiError::ParseNumError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<regex::Error> for AnkiError {
|
impl From<regex::Error> for AnkiError {
|
||||||
fn from(_err: regex::Error) -> Self {
|
fn from(_err: regex::Error) -> Self {
|
||||||
AnkiError::InvalidInput {
|
AnkiError::InvalidInput {
|
||||||
|
|
130
rslib/src/error/search.rs
Normal file
130
rslib/src/error/search.rs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
use super::AnkiError;
|
||||||
|
|
||||||
|
use anki_i18n::I18n;
|
||||||
|
use nom::error::{ErrorKind as NomErrorKind, ParseError as NomParseError};
|
||||||
|
use std::num::ParseIntError;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum ParseError<'a> {
|
||||||
|
Anki(&'a str, SearchErrorKind),
|
||||||
|
Nom(&'a str, NomErrorKind),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum SearchErrorKind {
|
||||||
|
MisplacedAnd,
|
||||||
|
MisplacedOr,
|
||||||
|
EmptyGroup,
|
||||||
|
UnopenedGroup,
|
||||||
|
UnclosedGroup,
|
||||||
|
EmptyQuote,
|
||||||
|
UnclosedQuote,
|
||||||
|
MissingKey,
|
||||||
|
UnknownEscape(String),
|
||||||
|
InvalidState(String),
|
||||||
|
InvalidFlag,
|
||||||
|
InvalidPropProperty(String),
|
||||||
|
InvalidPropOperator(String),
|
||||||
|
InvalidNumber { provided: String, context: String },
|
||||||
|
InvalidWholeNumber { provided: String, context: String },
|
||||||
|
InvalidPositiveWholeNumber { provided: String, context: String },
|
||||||
|
InvalidNegativeWholeNumber { provided: String, context: String },
|
||||||
|
InvalidAnswerButton { provided: String, context: String },
|
||||||
|
Regex(String),
|
||||||
|
Other(Option<String>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParseError<'_>> for AnkiError {
|
||||||
|
fn from(err: ParseError) -> Self {
|
||||||
|
match err {
|
||||||
|
ParseError::Anki(_, kind) => AnkiError::SearchError(kind),
|
||||||
|
ParseError::Nom(_, _) => AnkiError::SearchError(SearchErrorKind::Other(None)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<nom::Err<ParseError<'_>>> for AnkiError {
|
||||||
|
fn from(err: nom::Err<ParseError<'_>>) -> Self {
|
||||||
|
match err {
|
||||||
|
nom::Err::Error(e) => e.into(),
|
||||||
|
nom::Err::Failure(e) => e.into(),
|
||||||
|
nom::Err::Incomplete(_) => AnkiError::SearchError(SearchErrorKind::Other(None)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> NomParseError<&'a str> for ParseError<'a> {
|
||||||
|
fn from_error_kind(input: &'a str, kind: NomErrorKind) -> Self {
|
||||||
|
ParseError::Nom(input, kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append(_: &str, _: NomErrorKind, other: Self) -> Self {
|
||||||
|
other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParseIntError> for AnkiError {
|
||||||
|
fn from(_err: ParseIntError) -> Self {
|
||||||
|
AnkiError::ParseNumError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SearchErrorKind {
|
||||||
|
pub fn localized_description(&self, tr: &I18n) -> String {
|
||||||
|
let reason = match self {
|
||||||
|
SearchErrorKind::MisplacedAnd => tr.search_misplaced_and(),
|
||||||
|
SearchErrorKind::MisplacedOr => tr.search_misplaced_or(),
|
||||||
|
SearchErrorKind::EmptyGroup => tr.search_empty_group(),
|
||||||
|
SearchErrorKind::UnopenedGroup => tr.search_unopened_group(),
|
||||||
|
SearchErrorKind::UnclosedGroup => tr.search_unclosed_group(),
|
||||||
|
SearchErrorKind::EmptyQuote => tr.search_empty_quote(),
|
||||||
|
SearchErrorKind::UnclosedQuote => tr.search_unclosed_quote(),
|
||||||
|
SearchErrorKind::MissingKey => tr.search_missing_key(),
|
||||||
|
SearchErrorKind::UnknownEscape(ctx) => tr.search_unknown_escape(ctx.replace('`', "'")),
|
||||||
|
SearchErrorKind::InvalidState(state) => {
|
||||||
|
tr.search_invalid_argument("is:", state.replace('`', "'"))
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchErrorKind::InvalidFlag => tr.search_invalid_flag(),
|
||||||
|
SearchErrorKind::InvalidPropProperty(prop) => {
|
||||||
|
tr.search_invalid_argument("prop:", prop.replace('`', "'"))
|
||||||
|
}
|
||||||
|
SearchErrorKind::InvalidPropOperator(ctx) => {
|
||||||
|
tr.search_invalid_prop_operator(ctx.as_str())
|
||||||
|
}
|
||||||
|
SearchErrorKind::Regex(text) => {
|
||||||
|
format!("<pre>`{}`</pre>", text.replace('`', "'")).into()
|
||||||
|
}
|
||||||
|
SearchErrorKind::Other(Some(info)) => info.into(),
|
||||||
|
SearchErrorKind::Other(None) => tr.search_invalid_other(),
|
||||||
|
SearchErrorKind::InvalidNumber { provided, context } => {
|
||||||
|
tr.search_invalid_number(context.replace('`', "'"), provided.replace('`', "'"))
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchErrorKind::InvalidWholeNumber { provided, context } => tr
|
||||||
|
.search_invalid_whole_number(context.replace('`', "'"), provided.replace('`', "'")),
|
||||||
|
|
||||||
|
SearchErrorKind::InvalidPositiveWholeNumber { provided, context } => tr
|
||||||
|
.search_invalid_positive_whole_number(
|
||||||
|
context.replace('`', "'"),
|
||||||
|
provided.replace('`', "'"),
|
||||||
|
),
|
||||||
|
|
||||||
|
SearchErrorKind::InvalidNegativeWholeNumber { provided, context } => tr
|
||||||
|
.search_invalid_negative_whole_number(
|
||||||
|
context.replace('`', "'"),
|
||||||
|
provided.replace('`', "'"),
|
||||||
|
),
|
||||||
|
|
||||||
|
SearchErrorKind::InvalidAnswerButton { provided, context } => tr
|
||||||
|
.search_invalid_answer_button(
|
||||||
|
context.replace('`', "'"),
|
||||||
|
provided.replace('`', "'"),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
tr.search_invalid_search(reason).into()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue