use std::ops::RangeInclusive;
use crate::{
token::PartialToken,
value::{
numeric_types::{default_numeric_types::DefaultNumericTypes, EvalexprNumericTypes},
value_type::ValueType,
},
};
use crate::{operator::Operator, value::Value};
#[cfg(not(tarpaulin_include))]
mod display;
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum EvalexprError<NumericTypes: EvalexprNumericTypes = DefaultNumericTypes> {
WrongOperatorArgumentAmount {
expected: usize,
actual: usize,
},
WrongFunctionArgumentAmount {
expected: RangeInclusive<usize>,
actual: usize,
},
ExpectedString {
actual: Value<NumericTypes>,
},
ExpectedInt {
actual: Value<NumericTypes>,
},
ExpectedFloat {
actual: Value<NumericTypes>,
},
ExpectedNumber {
actual: Value<NumericTypes>,
},
ExpectedNumberOrString {
actual: Value<NumericTypes>,
},
ExpectedBoolean {
actual: Value<NumericTypes>,
},
ExpectedTuple {
actual: Value<NumericTypes>,
},
ExpectedFixedLengthTuple {
expected_length: usize,
actual: Value<NumericTypes>,
},
ExpectedRangedLengthTuple {
expected_length: RangeInclusive<usize>,
actual: Value<NumericTypes>,
},
ExpectedEmpty {
actual: Value<NumericTypes>,
},
AppendedToLeafNode,
PrecedenceViolation,
VariableIdentifierNotFound(String),
FunctionIdentifierNotFound(String),
TypeError {
expected: Vec<ValueType>,
actual: Value<NumericTypes>,
},
WrongTypeCombination {
operator: Operator<NumericTypes>,
actual: Vec<ValueType>,
},
UnmatchedLBrace,
UnmatchedRBrace,
UnmatchedDoubleQuote,
MissingOperatorOutsideOfBrace,
UnmatchedPartialToken {
first: PartialToken<NumericTypes>,
second: Option<PartialToken<NumericTypes>>,
},
AdditionError {
augend: Value<NumericTypes>,
addend: Value<NumericTypes>,
},
SubtractionError {
minuend: Value<NumericTypes>,
subtrahend: Value<NumericTypes>,
},
NegationError {
argument: Value<NumericTypes>,
},
MultiplicationError {
multiplicand: Value<NumericTypes>,
multiplier: Value<NumericTypes>,
},
DivisionError {
dividend: Value<NumericTypes>,
divisor: Value<NumericTypes>,
},
ModulationError {
dividend: Value<NumericTypes>,
divisor: Value<NumericTypes>,
},
InvalidRegex {
regex: String,
message: String,
},
ContextNotMutable,
IllegalEscapeSequence(String),
BuiltinFunctionsCannotBeEnabled,
BuiltinFunctionsCannotBeDisabled,
OutOfBoundsAccess,
IntFromUsize {
usize_int: usize,
},
IntIntoUsize {
int: NumericTypes::Int,
},
RandNotEnabled,
CustomMessage(String),
}
impl<NumericTypes: EvalexprNumericTypes> EvalexprError<NumericTypes> {
pub fn wrong_operator_argument_amount(actual: usize, expected: usize) -> Self {
EvalexprError::WrongOperatorArgumentAmount { actual, expected }
}
pub fn wrong_function_argument_amount(actual: usize, expected: usize) -> Self {
EvalexprError::WrongFunctionArgumentAmount {
actual,
expected: expected..=expected,
}
}
pub fn wrong_function_argument_amount_range(
actual: usize,
expected: RangeInclusive<usize>,
) -> Self {
EvalexprError::WrongFunctionArgumentAmount { actual, expected }
}
pub fn type_error(actual: Value<NumericTypes>, expected: Vec<ValueType>) -> Self {
EvalexprError::TypeError { actual, expected }
}
pub fn wrong_type_combination(
operator: Operator<NumericTypes>,
actual: Vec<ValueType>,
) -> Self {
EvalexprError::WrongTypeCombination { operator, actual }
}
pub fn expected_string(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedString { actual }
}
pub fn expected_int(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedInt { actual }
}
pub fn expected_float(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedFloat { actual }
}
pub fn expected_number(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedNumber { actual }
}
pub fn expected_number_or_string(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedNumberOrString { actual }
}
pub fn expected_boolean(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedBoolean { actual }
}
pub fn expected_tuple(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedTuple { actual }
}
pub fn expected_fixed_len_tuple(expected_len: usize, actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedFixedLengthTuple {
expected_length: expected_len,
actual,
}
}
pub fn expected_ranged_len_tuple(
expected_len: RangeInclusive<usize>,
actual: Value<NumericTypes>,
) -> Self {
EvalexprError::ExpectedRangedLengthTuple {
expected_length: expected_len,
actual,
}
}
pub fn expected_empty(actual: Value<NumericTypes>) -> Self {
EvalexprError::ExpectedEmpty { actual }
}
pub(crate) fn expected_type(
expected: &Value<NumericTypes>,
actual: Value<NumericTypes>,
) -> 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),
ValueType::Empty => Self::expected_empty(actual),
}
}
pub(crate) fn unmatched_partial_token(
first: PartialToken<NumericTypes>,
second: Option<PartialToken<NumericTypes>>,
) -> Self {
EvalexprError::UnmatchedPartialToken { first, second }
}
pub(crate) fn addition_error(augend: Value<NumericTypes>, addend: Value<NumericTypes>) -> Self {
EvalexprError::AdditionError { augend, addend }
}
pub(crate) fn subtraction_error(
minuend: Value<NumericTypes>,
subtrahend: Value<NumericTypes>,
) -> Self {
EvalexprError::SubtractionError {
minuend,
subtrahend,
}
}
pub(crate) fn negation_error(argument: Value<NumericTypes>) -> Self {
EvalexprError::NegationError { argument }
}
pub(crate) fn multiplication_error(
multiplicand: Value<NumericTypes>,
multiplier: Value<NumericTypes>,
) -> Self {
EvalexprError::MultiplicationError {
multiplicand,
multiplier,
}
}
pub(crate) fn division_error(
dividend: Value<NumericTypes>,
divisor: Value<NumericTypes>,
) -> Self {
EvalexprError::DivisionError { dividend, divisor }
}
pub(crate) fn modulation_error(
dividend: Value<NumericTypes>,
divisor: Value<NumericTypes>,
) -> Self {
EvalexprError::ModulationError { dividend, divisor }
}
pub fn invalid_regex(regex: String, message: String) -> Self {
EvalexprError::InvalidRegex { regex, message }
}
}
pub(crate) fn expect_operator_argument_amount<NumericTypes: EvalexprNumericTypes>(
actual: usize,
expected: usize,
) -> EvalexprResult<(), NumericTypes> {
if actual == expected {
Ok(())
} else {
Err(EvalexprError::wrong_operator_argument_amount(
actual, expected,
))
}
}
pub fn expect_function_argument_amount<NumericTypes: EvalexprNumericTypes>(
actual: usize,
expected: usize,
) -> EvalexprResult<(), NumericTypes> {
if actual == expected {
Ok(())
} else {
Err(EvalexprError::wrong_function_argument_amount(
actual, expected,
))
}
}
pub fn expect_number_or_string<NumericTypes: EvalexprNumericTypes>(
actual: &Value<NumericTypes>,
) -> EvalexprResult<(), NumericTypes> {
match actual {
Value::String(_) | Value::Float(_) | Value::Int(_) => Ok(()),
_ => Err(EvalexprError::expected_number_or_string(actual.clone())),
}
}
impl<NumericTypes: EvalexprNumericTypes> std::error::Error for EvalexprError<NumericTypes> {}
pub type EvalexprResult<T, NumericTypes = DefaultNumericTypes> =
Result<T, EvalexprError<NumericTypes>>;
pub type EvalexprResultValue<NumericTypes = DefaultNumericTypes> =
EvalexprResult<Value<NumericTypes>, NumericTypes>;
#[cfg(test)]
mod tests {
use crate::{
value::numeric_types::default_numeric_types::DefaultNumericTypes, EvalexprError, Value,
ValueType,
};
#[test]
fn trivial_coverage_tests() {
assert_eq!(
EvalexprError::type_error(
Value::<DefaultNumericTypes>::Int(3),
vec![ValueType::String]
),
EvalexprError::TypeError {
actual: Value::Int(3),
expected: vec![ValueType::String]
}
);
assert_eq!(
EvalexprError::expected_type(
&Value::<DefaultNumericTypes>::String("abc".to_string()),
Value::Empty
),
EvalexprError::expected_string(Value::Empty)
);
assert_eq!(
EvalexprError::expected_type(
&Value::<DefaultNumericTypes>::Boolean(false),
Value::Empty
),
EvalexprError::expected_boolean(Value::Empty)
);
assert_eq!(
EvalexprError::expected_type(
&Value::<DefaultNumericTypes>::Tuple(vec![]),
Value::Empty
),
EvalexprError::expected_tuple(Value::Empty)
);
assert_eq!(
EvalexprError::expected_type(
&Value::<DefaultNumericTypes>::Empty,
Value::String("abc".to_string())
),
EvalexprError::expected_empty(Value::String("abc".to_string()))
);
}
}