diff --git a/src/function/builtin.rs b/src/function/builtin.rs index f1c92c1..0d46512 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -9,114 +9,98 @@ use Value; pub fn builtin_function(identifier: &str) -> Option { match identifier { - "min" => Some(Function::new( - Box::new(|argument| { - let arguments = expect_tuple(argument)?; - let mut min_int = IntType::max_value(); - let mut min_float = 1.0f64 / 0.0f64; - debug_assert!(min_float.is_infinite()); + "min" => Some(Function::new(Box::new(|argument| { + let arguments = expect_tuple(argument)?; + let mut min_int = IntType::max_value(); + let mut min_float = 1.0f64 / 0.0f64; + debug_assert!(min_float.is_infinite()); - for argument in arguments { - if let Value::Float(float) = argument { - min_float = min_float.min(*float); - } else if let Value::Int(int) = argument { - min_int = min_int.min(*int); - } else { - return Err(EvalexprError::expected_number(argument.clone())); - } - } - - if (min_int as FloatType) < min_float { - Ok(Value::Int(min_int)) + for argument in arguments { + if let Value::Float(float) = argument { + min_float = min_float.min(*float); + } else if let Value::Int(int) = argument { + min_int = min_int.min(*int); } else { - Ok(Value::Float(min_float)) + return Err(EvalexprError::expected_number(argument.clone())); } - }), - )), - "max" => Some(Function::new( - Box::new(|argument| { - let arguments = expect_tuple(argument)?; - let mut max_int = IntType::min_value(); - let mut max_float = -1.0f64 / 0.0f64; - debug_assert!(max_float.is_infinite()); + } - for argument in arguments { - if let Value::Float(float) = argument { - max_float = max_float.max(*float); - } else if let Value::Int(int) = argument { - max_int = max_int.max(*int); - } else { - return Err(EvalexprError::expected_number(argument.clone())); - } - } + if (min_int as FloatType) < min_float { + Ok(Value::Int(min_int)) + } else { + Ok(Value::Float(min_float)) + } + }))), + "max" => Some(Function::new(Box::new(|argument| { + let arguments = expect_tuple(argument)?; + let mut max_int = IntType::min_value(); + let mut max_float = -1.0f64 / 0.0f64; + debug_assert!(max_float.is_infinite()); - if (max_int as FloatType) > max_float { - Ok(Value::Int(max_int)) + for argument in arguments { + if let Value::Float(float) = argument { + max_float = max_float.max(*float); + } else if let Value::Int(int) = argument { + max_int = max_int.max(*int); } else { - Ok(Value::Float(max_float)) + return Err(EvalexprError::expected_number(argument.clone())); } - }), - )), + } - "len" => Some(Function::new( - Box::new(|argument| { - let subject = expect_string(argument)?; - Ok(Value::from(subject.len() as i64)) - }), - )), + if (max_int as FloatType) > max_float { + Ok(Value::Int(max_int)) + } else { + Ok(Value::Float(max_float)) + } + }))), + + "len" => Some(Function::new(Box::new(|argument| { + let subject = expect_string(argument)?; + Ok(Value::from(subject.len() as i64)) + }))), // string functions #[cfg(feature = "regex_support")] - "str::regex_matches" => Some(Function::new( - Box::new(|argument| { - let arguments = expect_tuple(argument)?; + "str::regex_matches" => Some(Function::new(Box::new(|argument| { + let arguments = expect_tuple(argument)?; - let subject = expect_string(&arguments[0])?; - let re_str = expect_string(&arguments[1])?; - match Regex::new(re_str) { - Ok(re) => Ok(Value::Boolean(re.is_match(subject))), - Err(err) => Err(EvalexprError::invalid_regex( - re_str.to_string(), - format!("{}", err), - )), - } - }), - )), + let subject = expect_string(&arguments[0])?; + let re_str = expect_string(&arguments[1])?; + match Regex::new(re_str) { + Ok(re) => Ok(Value::Boolean(re.is_match(subject))), + Err(err) => Err(EvalexprError::invalid_regex( + re_str.to_string(), + format!("{}", err), + )), + } + }))), #[cfg(feature = "regex_support")] - "str::regex_replace" => Some(Function::new( - Box::new(|argument| { - let arguments = expect_tuple(argument)?; + "str::regex_replace" => Some(Function::new(Box::new(|argument| { + let arguments = expect_tuple(argument)?; - let subject = expect_string(&arguments[0])?; - let re_str = expect_string(&arguments[1])?; - let repl = expect_string(&arguments[2])?; - match Regex::new(re_str) { - Ok(re) => Ok(Value::String(re.replace_all(subject, repl).to_string())), - Err(err) => Err(EvalexprError::invalid_regex( - re_str.to_string(), - format!("{}", err), - )), - } - }), - )), - "str::to_lowercase" => Some(Function::new( - Box::new(|argument| { - let subject = expect_string(argument)?; - Ok(Value::from(subject.to_lowercase())) - }), - )), - "str::to_uppercase" => Some(Function::new( - Box::new(|argument| { - let subject = expect_string(argument)?; - Ok(Value::from(subject.to_uppercase())) - }), - )), - "str::trim" => Some(Function::new( - Box::new(|argument| { - let subject = expect_string(argument)?; - Ok(Value::from(subject.trim())) - }), - )), + let subject = expect_string(&arguments[0])?; + let re_str = expect_string(&arguments[1])?; + let repl = expect_string(&arguments[2])?; + match Regex::new(re_str) { + Ok(re) => Ok(Value::String(re.replace_all(subject, repl).to_string())), + Err(err) => Err(EvalexprError::invalid_regex( + re_str.to_string(), + format!("{}", err), + )), + } + }))), + "str::to_lowercase" => Some(Function::new(Box::new(|argument| { + let subject = expect_string(argument)?; + Ok(Value::from(subject.to_lowercase())) + }))), + "str::to_uppercase" => Some(Function::new(Box::new(|argument| { + let subject = expect_string(argument)?; + Ok(Value::from(subject.to_uppercase())) + }))), + "str::trim" => Some(Function::new(Box::new(|argument| { + let subject = expect_string(argument)?; + Ok(Value::from(subject.trim())) + }))), _ => None, } } diff --git a/src/function/mod.rs b/src/function/mod.rs index ccab8f0..0f9ad9f 100644 --- a/src/function/mod.rs +++ b/src/function/mod.rs @@ -1,6 +1,6 @@ use std::fmt; -use error::{EvalexprResult}; +use error::EvalexprResult; use value::Value; pub(crate) mod builtin; @@ -27,12 +27,8 @@ impl Function { /// Creates a user-defined function. /// /// The `function` is a boxed function that takes a `Value` and returns a `EvalexprResult`. - pub fn new( - function: Box EvalexprResult>, - ) -> Self { - Self { - function, - } + pub fn new(function: Box EvalexprResult>) -> Self { + Self { function } } pub(crate) fn call(&self, argument: &Value) -> EvalexprResult { @@ -42,9 +38,6 @@ impl Function { impl fmt::Debug for Function { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - f, - "Function {{ [...] }}" - ) + write!(f, "Function {{ [...] }}") } } diff --git a/src/operator/mod.rs b/src/operator/mod.rs index bb675dc..a8ddda6 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -420,9 +420,7 @@ impl Operator { Ok(Value::Boolean(false)) } }, - Tuple => { - Ok(Value::Tuple(arguments.into())) - }, + Tuple => Ok(Value::Tuple(arguments.into())), Assign => Err(EvalexprError::ContextNotManipulable), Chain => { if arguments.is_empty() { diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 55c5b79..9ae775b 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -410,11 +410,16 @@ impl Node { } } -fn collapse_root_stack_to(root_stack: &mut Vec, mut root: Node, collapse_goal: &Node) -> EvalexprResult { +fn collapse_root_stack_to( + root_stack: &mut Vec, + mut root: Node, + collapse_goal: &Node, +) -> EvalexprResult { loop { if let Some(mut potential_higher_root) = root_stack.pop() { // TODO I'm not sure about this >, as I have no example for different sequence operators with the same precedence - if potential_higher_root.operator().precedence() > collapse_goal.operator().precedence() { + if potential_higher_root.operator().precedence() > collapse_goal.operator().precedence() + { potential_higher_root.children.push(root); root = potential_higher_root; } else { @@ -569,7 +574,7 @@ pub(crate) fn tokens_to_operator_tree(tokens: Vec) -> EvalexprResult Ok(Value::from(tuple.len() as IntType)), - Value::Empty => Ok(Value::from(0)), - _ => Ok(Value::from(1)), - } - }), - ), + Function::new(Box::new(|arguments| match arguments { + Value::Tuple(tuple) => Ok(Value::from(tuple.len() as IntType)), + Value::Empty => Ok(Value::from(0)), + _ => Ok(Value::from(1)), + })), ) .unwrap(); context .set_value("five".to_string(), Value::Int(5)) .unwrap(); - context.set_function("function_four".into(), Function::new(Box::new(|_| {Ok(Value::Int(4))}))).unwrap(); + context + .set_function( + "function_four".into(), + Function::new(Box::new(|_| Ok(Value::Int(4)))), + ) + .unwrap(); assert_eq!(eval_with_context("avg(7, 5)", &context), Ok(Value::Int(6))); assert_eq!( @@ -264,13 +257,19 @@ fn test_n_ary_functions() { Ok(Value::Int(14)) ); assert_eq!(eval_with_context("count()", &context), Ok(Value::Int(0))); - assert_eq!(eval_with_context("count((1, 2, 3))", &context), Ok(Value::Int(3))); + assert_eq!( + eval_with_context("count((1, 2, 3))", &context), + Ok(Value::Int(3)) + ); assert_eq!( eval_with_context("count(3, 5.5, 2)", &context), Ok(Value::Int(3)) ); assert_eq!(eval_with_context("count 5", &context), Ok(Value::Int(1))); - assert_eq!(eval_with_context("function_four()", &context), Ok(Value::Int(4))); + assert_eq!( + eval_with_context("function_four()", &context), + Ok(Value::Int(4)) + ); } #[test]