From f14a631f682ef87c4d19418f620a8c79eabf4b08 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 1 Apr 2021 16:18:28 +1000 Subject: [PATCH] split search errors into separate file --- rslib/src/error/mod.rs | 134 ++------------------------------------ rslib/src/error/search.rs | 130 ++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 128 deletions(-) create mode 100644 rslib/src/error/search.rs diff --git a/rslib/src/error/mod.rs b/rslib/src/error/mod.rs index f09b0203d..83c0204c1 100644 --- a/rslib/src/error/mod.rs +++ b/rslib/src/error/mod.rs @@ -1,11 +1,14 @@ // Copyright: Ankitects Pty Ltd and contributors // 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; pub use failure::{Error, Fail}; -use nom::error::{ErrorKind as NomErrorKind, ParseError as NomParseError}; use reqwest::StatusCode; -use std::{io, num::ParseIntError, str::Utf8Error}; +use std::{io, str::Utf8Error}; use tempfile::PathPersistError; pub type Result = std::result::Result; @@ -128,67 +131,7 @@ impl AnkiError { DbErrorKind::Locked => "Anki already open, or media currently syncing.".into(), _ => format!("{:?}", self), }, - AnkiError::SearchError(kind) => { - 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!("
`{}`
", 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::SearchError(kind) => kind.localized_description(&tr), AnkiError::InvalidInput { info } => { if info.is_empty() { tr.errors_invalid_input_empty().into() @@ -414,71 +357,6 @@ impl From 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), -} - -impl From> for AnkiError { - fn from(err: ParseError) -> Self { - match err { - ParseError::Anki(_, kind) => AnkiError::SearchError(kind), - ParseError::Nom(_, _) => AnkiError::SearchError(SearchErrorKind::Other(None)), - } - } -} - -impl From>> for AnkiError { - fn from(err: nom::Err>) -> 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 for AnkiError { - fn from(_err: ParseIntError) -> Self { - AnkiError::ParseNumError - } -} - impl From for AnkiError { fn from(_err: regex::Error) -> Self { AnkiError::InvalidInput { diff --git a/rslib/src/error/search.rs b/rslib/src/error/search.rs new file mode 100644 index 000000000..92f6f7a3e --- /dev/null +++ b/rslib/src/error/search.rs @@ -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), +} + +impl From> for AnkiError { + fn from(err: ParseError) -> Self { + match err { + ParseError::Anki(_, kind) => AnkiError::SearchError(kind), + ParseError::Nom(_, _) => AnkiError::SearchError(SearchErrorKind::Other(None)), + } + } +} + +impl From>> for AnkiError { + fn from(err: nom::Err>) -> 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 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!("
`{}`
", 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() + } +}