2019-03-20 09:32:49 +00:00
//! The `error` module contains the `Error` enum that contains all error types used by this crate.
//!
//! The `Error` enum implements constructors for its struct variants, because those are ugly to construct.
//!
//! The module also contains some helper functions starting with `expect_` that check for a condition and return `Err(_)` if the condition is not fulfilled.
//! They are meant as shortcuts to not write the same error checking code everywhere.
2019-08-29 08:10:54 +00:00
use crate ::{ token ::PartialToken , value ::value_type ::ValueType } ;
2016-11-16 16:12:26 +00:00
2019-08-29 10:49:56 +00:00
use crate ::{ operator ::Operator , value ::Value } ;
2019-03-27 15:33:46 +00:00
2021-07-13 10:39:47 +00:00
// Exclude error display code from test coverage, as the code does not make sense to test.
#[ cfg(not(tarpaulin_include)) ]
2019-03-23 12:27:44 +00:00
mod display ;
2019-03-20 09:32:49 +00:00
/// Errors used in this crate.
2019-03-15 15:11:31 +00:00
#[ derive(Debug, PartialEq) ]
2022-01-13 12:50:38 +00:00
#[ non_exhaustive ]
2019-03-27 15:33:46 +00:00
pub enum EvalexprError {
2019-03-20 09:32:49 +00:00
/// An operator was called with a wrong amount of arguments.
2019-03-19 14:54:52 +00:00
WrongOperatorArgumentAmount {
2019-03-20 09:42:17 +00:00
/// The expected amount of arguments.
2019-03-19 14:54:52 +00:00
expected : usize ,
2019-03-20 09:42:17 +00:00
/// The actual amount of arguments.
2019-03-19 14:54:52 +00:00
actual : usize ,
} ,
2019-03-20 09:32:49 +00:00
/// A function was called with a wrong amount of arguments.
2019-03-19 14:54:52 +00:00
WrongFunctionArgumentAmount {
2019-03-20 09:42:17 +00:00
/// The expected amount of arguments.
2019-03-15 15:11:31 +00:00
expected : usize ,
2019-03-20 09:42:17 +00:00
/// The actual amount of arguments.
2019-03-15 15:11:31 +00:00
actual : usize ,
} ,
2019-03-20 09:32:49 +00:00
2019-03-20 14:29:50 +00:00
/// A string value was expected.
ExpectedString {
/// The actual value.
actual : Value ,
} ,
2019-03-20 09:42:17 +00:00
/// An integer value was expected.
ExpectedInt {
/// The actual value.
actual : Value ,
} ,
/// A float value was expected.
ExpectedFloat {
/// The actual value.
actual : Value ,
} ,
2019-03-20 09:32:49 +00:00
/// A numeric value was expected.
/// Numeric values are the variants `Value::Int` and `Value::Float`.
2019-03-15 15:11:31 +00:00
ExpectedNumber {
2019-03-20 09:42:17 +00:00
/// The actual value.
2019-03-15 15:11:31 +00:00
actual : Value ,
} ,
2019-03-20 09:32:49 +00:00
2019-04-05 21:07:54 +00:00
/// A numeric or string value was expected.
/// Numeric values are the variants `Value::Int` and `Value::Float`.
ExpectedNumberOrString {
/// The actual value.
actual : Value ,
} ,
2019-03-20 09:32:49 +00:00
/// A boolean value was expected.
2019-03-15 17:19:59 +00:00
ExpectedBoolean {
2019-03-20 09:42:17 +00:00
/// The actual value.
2019-03-15 17:19:59 +00:00
actual : Value ,
} ,
2016-11-16 16:12:26 +00:00
2019-03-20 14:29:50 +00:00
/// A tuple value was expected.
ExpectedTuple {
/// The actual value.
actual : Value ,
} ,
2019-08-29 05:56:49 +00:00
/// A tuple value of a certain length was expected.
ExpectedFixedLenTuple {
/// The expected len
expected_len : usize ,
/// The actual value.
actual : Value ,
} ,
2019-03-28 08:56:30 +00:00
/// An empty value was expected.
ExpectedEmpty {
/// The actual value.
actual : Value ,
} ,
2019-03-15 15:11:31 +00:00
/// Tried to append a child to a leaf node.
/// Leaf nodes cannot have children.
AppendedToLeafNode ,
/// Tried to append a child to a node such that the precedence of the child is not higher.
2019-03-27 15:38:59 +00:00
/// This error should never occur.
/// If it does, please file a bug report.
2019-03-15 15:11:31 +00:00
PrecedenceViolation ,
2019-03-27 17:09:20 +00:00
/// A `VariableIdentifier` operation did not find its value in the context.
2019-03-18 17:21:07 +00:00
VariableIdentifierNotFound ( String ) ,
2019-03-27 17:09:20 +00:00
/// A `FunctionIdentifier` operation did not find its value in the context.
2019-03-18 17:21:07 +00:00
FunctionIdentifierNotFound ( String ) ,
2019-03-15 15:40:38 +00:00
2019-03-20 09:42:17 +00:00
/// A value has the wrong type.
/// Only use this if there is no other error that describes the expected and provided types in more detail.
TypeError {
/// The expected types.
2019-08-29 08:10:54 +00:00
expected : Vec < ValueType > ,
2019-03-20 09:42:17 +00:00
/// The actual value.
actual : Value ,
} ,
2019-03-15 16:27:10 +00:00
2019-08-29 10:49:56 +00:00
/// An operator is used with a wrong combination of types.
WrongTypeCombination {
/// The operator that whose evaluation caused the error.
operator : Operator ,
/// The types that were used in the operator causing it to fail.
actual : Vec < ValueType > ,
} ,
2019-03-15 16:27:10 +00:00
/// An opening brace without a matching closing brace was found.
UnmatchedLBrace ,
/// A closing brace without a matching opening brace was found.
UnmatchedRBrace ,
2019-03-15 17:19:59 +00:00
2022-01-13 12:50:38 +00:00
/// Left of an opening brace or right of a closing brace is a token that does not expect the brace next to it.
/// For example, writing `4(5)` would yield this error, as the `4` does not have any operands.
MissingOperatorOutsideOfBrace ,
2019-03-20 09:32:49 +00:00
/// A `PartialToken` is unmatched, such that it cannot be combined into a full `Token`.
/// This happens if for example a single `=` is found, surrounded by whitespace.
/// It is not a token, but it is part of the string representation of some tokens.
2019-03-15 17:19:59 +00:00
UnmatchedPartialToken {
2019-03-20 09:32:49 +00:00
/// The unmatched partial token.
2019-03-15 17:19:59 +00:00
first : PartialToken ,
2019-03-20 09:32:49 +00:00
/// The token that follows the unmatched partial token and that cannot be matched to the partial token, or `None`, if `first` is the last partial token in the stream.
2019-03-15 17:19:59 +00:00
second : Option < PartialToken > ,
} ,
2019-03-20 10:52:07 +00:00
/// An addition operation performed by Rust failed.
AdditionError {
/// The first argument of the addition.
augend : Value ,
/// The second argument of the addition.
addend : Value ,
} ,
/// A subtraction operation performed by Rust failed.
SubtractionError {
/// The first argument of the subtraction.
minuend : Value ,
/// The second argument of the subtraction.
subtrahend : Value ,
} ,
/// A negation operation performed by Rust failed.
NegationError {
/// The argument of the negation.
argument : Value ,
} ,
/// A multiplication operation performed by Rust failed.
MultiplicationError {
/// The first argument of the multiplication.
multiplicand : Value ,
/// The second argument of the multiplication.
multiplier : Value ,
} ,
/// A division operation performed by Rust failed.
DivisionError {
/// The first argument of the division.
dividend : Value ,
/// The second argument of the division.
divisor : Value ,
} ,
/// A modulation operation performed by Rust failed.
ModulationError {
/// The first argument of the modulation.
dividend : Value ,
/// The second argument of the modulation.
divisor : Value ,
} ,
2019-03-23 13:20:43 +00:00
2019-04-12 21:03:13 +00:00
/// A regular expression could not be parsed
2019-04-07 06:10:36 +00:00
InvalidRegex {
/// The invalid regular expression
regex : String ,
/// Failure message from the regex engine
message : String ,
} ,
2019-03-28 10:12:47 +00:00
/// A modification was attempted on a `Context` that does not allow modifications.
2021-05-28 07:27:32 +00:00
ContextNotMutable ,
2019-03-27 15:38:59 +00:00
2019-03-30 10:54:19 +00:00
/// An escape sequence within a string literal is illegal.
IllegalEscapeSequence ( String ) ,
2019-03-23 13:20:43 +00:00
/// A custom error explained by its message.
2019-03-23 13:29:50 +00:00
CustomMessage ( String ) ,
2019-03-15 15:11:31 +00:00
}
2019-03-27 15:33:46 +00:00
impl EvalexprError {
2019-03-20 09:32:49 +00:00
pub ( crate ) fn wrong_operator_argument_amount ( actual : usize , expected : usize ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::WrongOperatorArgumentAmount { actual , expected }
2019-03-19 14:54:52 +00:00
}
2019-03-20 09:32:49 +00:00
pub ( crate ) fn wrong_function_argument_amount ( actual : usize , expected : usize ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::WrongFunctionArgumentAmount { actual , expected }
2019-03-15 15:11:31 +00:00
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::TypeError{actual, expected}`.
2019-08-29 08:10:54 +00:00
pub fn type_error ( actual : Value , expected : Vec < ValueType > ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::TypeError { actual , expected }
2019-03-20 09:42:17 +00:00
}
2019-08-29 13:36:35 +00:00
/// Constructs `EvalexprError::WrongTypeCombination{operator, actual}`.
pub fn wrong_type_combination ( operator : Operator , actual : Vec < ValueType > ) -> Self {
EvalexprError ::WrongTypeCombination { operator , actual }
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedString{actual}`.
2019-03-20 14:29:50 +00:00
pub fn expected_string ( actual : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::ExpectedString { actual }
2019-03-20 14:29:50 +00:00
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedInt{actual}`.
2019-03-20 09:42:17 +00:00
pub fn expected_int ( actual : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::ExpectedInt { actual }
2019-03-20 09:42:17 +00:00
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedFloat{actual}`.
2019-03-20 09:42:17 +00:00
pub fn expected_float ( actual : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::ExpectedFloat { actual }
2019-03-20 09:42:17 +00:00
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedNumber{actual}`.
2019-03-15 15:11:31 +00:00
pub fn expected_number ( actual : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::ExpectedNumber { actual }
2019-03-15 15:11:31 +00:00
}
2019-03-15 17:19:59 +00:00
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedNumberOrString{actual}`.
2019-04-05 21:07:54 +00:00
pub fn expected_number_or_string ( actual : Value ) -> Self {
EvalexprError ::ExpectedNumberOrString { actual }
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedBoolean{actual}`.
2019-03-15 17:19:59 +00:00
pub fn expected_boolean ( actual : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::ExpectedBoolean { actual }
2019-03-15 17:19:59 +00:00
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedTuple{actual}`.
2019-03-20 14:29:50 +00:00
pub fn expected_tuple ( actual : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::ExpectedTuple { actual }
2019-03-20 14:29:50 +00:00
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedFixedLenTuple{expected_len, actual}`.
2019-08-29 05:56:49 +00:00
pub fn expected_fixed_len_tuple ( expected_len : usize , actual : Value ) -> Self {
2019-08-29 07:02:05 +00:00
EvalexprError ::ExpectedFixedLenTuple {
expected_len ,
actual ,
}
2019-08-29 05:56:49 +00:00
}
2019-08-29 13:10:16 +00:00
/// Constructs `EvalexprError::ExpectedEmpty{actual}`.
2019-03-28 08:56:30 +00:00
pub fn expected_empty ( actual : Value ) -> Self {
EvalexprError ::ExpectedEmpty { actual }
}
2019-03-27 15:38:59 +00:00
/// Constructs an error that expresses that the type of `expected` was expected, but `actual` was found.
pub ( crate ) fn expected_type ( expected : & Value , actual : Value ) -> Self {
match ValueType ::from ( expected ) {
ValueType ::String = > Self ::expected_string ( actual ) ,
ValueType ::Int = > Self ::expected_int ( actual ) ,
ValueType ::Float = > Self ::expected_float ( actual ) ,
ValueType ::Boolean = > Self ::expected_boolean ( actual ) ,
ValueType ::Tuple = > Self ::expected_tuple ( actual ) ,
2019-03-28 08:56:30 +00:00
ValueType ::Empty = > Self ::expected_empty ( actual ) ,
2019-03-27 15:38:59 +00:00
}
}
2019-03-20 09:32:49 +00:00
pub ( crate ) fn unmatched_partial_token (
first : PartialToken ,
second : Option < PartialToken > ,
) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::UnmatchedPartialToken { first , second }
2019-03-15 17:19:59 +00:00
}
2019-03-20 10:52:07 +00:00
pub ( crate ) fn addition_error ( augend : Value , addend : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::AdditionError { augend , addend }
2019-03-20 10:52:07 +00:00
}
pub ( crate ) fn subtraction_error ( minuend : Value , subtrahend : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::SubtractionError {
2019-03-20 10:52:07 +00:00
minuend ,
subtrahend ,
}
}
pub ( crate ) fn negation_error ( argument : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::NegationError { argument }
2019-03-20 10:52:07 +00:00
}
pub ( crate ) fn multiplication_error ( multiplicand : Value , multiplier : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::MultiplicationError {
2019-03-20 10:52:07 +00:00
multiplicand ,
multiplier ,
}
}
pub ( crate ) fn division_error ( dividend : Value , divisor : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::DivisionError { dividend , divisor }
2019-03-20 10:52:07 +00:00
}
pub ( crate ) fn modulation_error ( dividend : Value , divisor : Value ) -> Self {
2019-03-27 15:33:46 +00:00
EvalexprError ::ModulationError { dividend , divisor }
2019-03-20 10:52:07 +00:00
}
2019-04-07 06:10:36 +00:00
/// Constructs `EvalexprError::InvalidRegex(regex)`
pub fn invalid_regex ( regex : String , message : String ) -> Self {
2019-04-14 14:54:35 +00:00
EvalexprError ::InvalidRegex { regex , message }
2019-04-07 06:10:36 +00:00
}
2019-03-15 15:11:31 +00:00
}
2019-03-20 09:32:49 +00:00
/// Returns `Ok(())` if the actual and expected parameters are equal, and `Err(Error::WrongOperatorArgumentAmount)` otherwise.
2019-03-27 15:38:59 +00:00
pub ( crate ) fn expect_operator_argument_amount (
actual : usize ,
expected : usize ,
2019-03-27 18:08:47 +00:00
) -> EvalexprResult < ( ) > {
2019-03-19 14:54:52 +00:00
if actual = = expected {
Ok ( ( ) )
} else {
2019-03-27 15:38:59 +00:00
Err ( EvalexprError ::wrong_operator_argument_amount (
actual , expected ,
) )
2019-03-19 14:54:52 +00:00
}
}
2019-03-20 09:32:49 +00:00
/// Returns `Ok(())` if the actual and expected parameters are equal, and `Err(Error::WrongFunctionArgumentAmount)` otherwise.
2019-04-14 14:54:35 +00:00
pub fn expect_function_argument_amount ( actual : usize , expected : usize ) -> EvalexprResult < ( ) > {
2019-03-15 15:11:31 +00:00
if actual = = expected {
Ok ( ( ) )
} else {
2019-03-27 15:38:59 +00:00
Err ( EvalexprError ::wrong_function_argument_amount (
actual , expected ,
) )
2019-03-15 15:11:31 +00:00
}
}
2019-04-12 21:04:40 +00:00
/// Returns `Ok(())` if the given value is a string or a numeric
2019-04-05 21:07:54 +00:00
pub fn expect_number_or_string ( actual : & Value ) -> EvalexprResult < ( ) > {
match actual {
Value ::String ( _ ) | Value ::Float ( _ ) | Value ::Int ( _ ) = > Ok ( ( ) ) ,
_ = > Err ( EvalexprError ::expected_number_or_string ( actual . clone ( ) ) ) ,
}
}
2019-03-27 15:33:46 +00:00
impl std ::error ::Error for EvalexprError { }
2019-03-27 15:38:59 +00:00
/// Standard result type used by this crate.
pub type EvalexprResult < T > = Result < T , EvalexprError > ;
2022-01-13 13:18:06 +00:00
#[ cfg(test) ]
mod tests {
use crate ::{ EvalexprError , Value , ValueType } ;
/// Tests whose only use is to bring test coverage of trivial lines up, like trivial constructors.
#[ test ]
fn trivial_coverage_tests ( ) {
assert_eq! (
EvalexprError ::type_error ( Value ::Int ( 3 ) , vec! [ ValueType ::String ] ) ,
EvalexprError ::TypeError {
actual : Value ::Int ( 3 ) ,
expected : vec ! [ ValueType ::String ]
}
) ;
assert_eq! (
EvalexprError ::expected_type ( & Value ::String ( " abc " . to_string ( ) ) , Value ::Empty ) ,
EvalexprError ::expected_string ( Value ::Empty )
) ;
assert_eq! (
EvalexprError ::expected_type ( & Value ::Boolean ( false ) , Value ::Empty ) ,
EvalexprError ::expected_boolean ( Value ::Empty )
) ;
assert_eq! (
EvalexprError ::expected_type ( & Value ::Tuple ( vec! [ ] ) , Value ::Empty ) ,
EvalexprError ::expected_tuple ( Value ::Empty )
) ;
assert_eq! (
EvalexprError ::expected_type ( & Value ::Empty , Value ::String ( " abc " . to_string ( ) ) ) ,
EvalexprError ::expected_empty ( Value ::String ( " abc " . to_string ( ) ) )
) ;
}
}