From fe854e8b8cc02db36d899e9ee787dc05d9b86f8d Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Fri, 8 Dec 2023 17:49:10 +0200 Subject: [PATCH 1/3] Make `expected` number of function arguments a range. --- src/error/display.rs | 17 ++++++++++++----- src/error/mod.rs | 21 ++++++++++++++++++--- tests/integration.rs | 2 +- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/error/display.rs b/src/error/display.rs index 9c2815f..9089a32 100644 --- a/src/error/display.rs +++ b/src/error/display.rs @@ -11,11 +11,18 @@ impl fmt::Display for EvalexprError { "An operator expected {} arguments, but got {}.", expected, actual ), - WrongFunctionArgumentAmount { expected, actual } => write!( - f, - "A function expected {} arguments, but got {}.", - expected, actual - ), + WrongFunctionArgumentAmount { expected, actual } => { + let expected_arguments = if expected.start() == expected.end() { + format!("{}", expected.start()) + } else { + format!("{} to {}", expected.start(), expected.end()) + }; + write!( + f, + "A function expected {} arguments, but got {}.", + expected_arguments, actual + ) + }, ExpectedString { actual } => { write!(f, "Expected a Value::String, but got {:?}.", actual) }, diff --git a/src/error/mod.rs b/src/error/mod.rs index c1e4726..561c837 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -5,6 +5,8 @@ //! 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. +use std::ops::RangeInclusive; + use crate::{token::PartialToken, value::value_type::ValueType}; use crate::{operator::Operator, value::Value}; @@ -28,7 +30,7 @@ pub enum EvalexprError { /// A function was called with a wrong amount of arguments. WrongFunctionArgumentAmount { /// The expected amount of arguments. - expected: usize, + expected: RangeInclusive, /// The actual amount of arguments. actual: usize, }, @@ -217,11 +219,24 @@ pub enum EvalexprError { } impl EvalexprError { - pub(crate) fn wrong_operator_argument_amount(actual: usize, expected: usize) -> Self { + /// Construct a `WrongOperatorArgumentAmount` error. + pub fn wrong_operator_argument_amount(actual: usize, expected: usize) -> Self { EvalexprError::WrongOperatorArgumentAmount { actual, expected } } - pub(crate) fn wrong_function_argument_amount(actual: usize, expected: usize) -> Self { + /// Construct a `WrongFunctionArgumentAmount` error for a function with a fixed amount of arguments. + pub fn wrong_function_argument_amount(actual: usize, expected: usize) -> Self { + EvalexprError::WrongFunctionArgumentAmount { + actual, + expected: expected..=expected, + } + } + + /// Construct a `WrongFunctionArgumentAmount` error for a function with a range of possible amounts of arguments. + pub fn wrong_function_argument_amount_range( + actual: usize, + expected: RangeInclusive, + ) -> Self { EvalexprError::WrongFunctionArgumentAmount { actual, expected } } diff --git a/tests/integration.rs b/tests/integration.rs index 2c0978f..5a66dfe 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1737,7 +1737,7 @@ fn test_error_constructors() { assert_eq!( expect_function_argument_amount(2, 3), Err(EvalexprError::WrongFunctionArgumentAmount { - expected: 3, + expected: 3..=3, actual: 2 }) ); From cc7156c860b43c59ef3fe60b09ba396991375aa1 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Fri, 8 Dec 2023 17:52:23 +0200 Subject: [PATCH 2/3] Use `as_fixed_len_tuple` in regex builtin functions. --- src/function/builtin.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 7105743..0839671 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -223,7 +223,7 @@ pub fn builtin_function(identifier: &str) -> Option { // String functions #[cfg(feature = "regex_support")] "str::regex_matches" => Some(Function::new(|argument| { - let arguments = argument.as_tuple()?; + let arguments = argument.as_fixed_len_tuple(2)?; let subject = arguments[0].as_string()?; let re_str = arguments[1].as_string()?; @@ -237,7 +237,7 @@ pub fn builtin_function(identifier: &str) -> Option { })), #[cfg(feature = "regex_support")] "str::regex_replace" => Some(Function::new(|argument| { - let arguments = argument.as_tuple()?; + let arguments = argument.as_fixed_len_tuple(3)?; let subject = arguments[0].as_string()?; let re_str = arguments[1].as_string()?; From ca67b0937c59cedff521b8acef63bc3dd60e4322 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Fri, 8 Dec 2023 17:54:19 +0200 Subject: [PATCH 3/3] Update changelog. --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d37077d..31740f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,12 @@ ### Changed + * The error type `WrongFunctionArgumentAmount` now expects a range of argument amounts instead of a single one (#159) + ### Fixed * Minor error in README. + * Regex functions do not silently ignore superfluous arguments anymore. ### Deprecated