2019-04-07 06:10:36 +00:00
|
|
|
#[cfg(feature = "regex_support")]
|
|
|
|
use regex::Regex;
|
|
|
|
|
2019-08-29 07:02:05 +00:00
|
|
|
use crate::{
|
|
|
|
value::{FloatType, IntType},
|
2019-08-29 08:10:54 +00:00
|
|
|
EvalexprError, Function, Value, ValueType,
|
2019-08-29 07:02:05 +00:00
|
|
|
};
|
2019-03-19 18:08:23 +00:00
|
|
|
|
|
|
|
pub fn builtin_function(identifier: &str) -> Option<Function> {
|
|
|
|
match identifier {
|
2019-05-04 11:54:19 +00:00
|
|
|
"min" => Some(Function::new(Box::new(|argument| {
|
2019-08-29 05:56:49 +00:00
|
|
|
let arguments = argument.as_tuple()?;
|
2019-05-04 11:54:19 +00:00
|
|
|
let mut min_int = IntType::max_value();
|
|
|
|
let mut min_float = 1.0f64 / 0.0f64;
|
|
|
|
debug_assert!(min_float.is_infinite());
|
2019-03-19 18:08:23 +00:00
|
|
|
|
2019-05-04 11:54:19 +00:00
|
|
|
for argument in arguments {
|
|
|
|
if let Value::Float(float) = argument {
|
2019-08-29 05:56:49 +00:00
|
|
|
min_float = min_float.min(float);
|
2019-05-04 11:54:19 +00:00
|
|
|
} else if let Value::Int(int) = argument {
|
2019-08-29 05:56:49 +00:00
|
|
|
min_int = min_int.min(int);
|
2019-03-19 18:08:23 +00:00
|
|
|
} else {
|
2021-05-28 06:07:26 +00:00
|
|
|
return Err(EvalexprError::expected_number(argument));
|
2019-03-19 18:08:23 +00:00
|
|
|
}
|
2019-05-04 11:54:19 +00:00
|
|
|
}
|
2019-03-19 18:08:23 +00:00
|
|
|
|
2019-05-04 11:54:19 +00:00
|
|
|
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| {
|
2019-08-29 05:56:49 +00:00
|
|
|
let arguments = argument.as_tuple()?;
|
2019-05-04 11:54:19 +00:00
|
|
|
let mut max_int = IntType::min_value();
|
|
|
|
let mut max_float = -1.0f64 / 0.0f64;
|
|
|
|
debug_assert!(max_float.is_infinite());
|
2019-03-19 18:08:23 +00:00
|
|
|
|
2019-05-04 11:54:19 +00:00
|
|
|
for argument in arguments {
|
|
|
|
if let Value::Float(float) = argument {
|
2019-08-29 05:56:49 +00:00
|
|
|
max_float = max_float.max(float);
|
2019-05-04 11:54:19 +00:00
|
|
|
} else if let Value::Int(int) = argument {
|
2019-08-29 05:56:49 +00:00
|
|
|
max_int = max_int.max(int);
|
2019-03-19 18:08:23 +00:00
|
|
|
} else {
|
2021-05-28 06:07:26 +00:00
|
|
|
return Err(EvalexprError::expected_number(argument));
|
2019-03-19 18:08:23 +00:00
|
|
|
}
|
2019-05-04 11:54:19 +00:00
|
|
|
}
|
2019-04-07 06:10:36 +00:00
|
|
|
|
2019-05-04 11:54:19 +00:00
|
|
|
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| {
|
2019-08-29 08:10:54 +00:00
|
|
|
if let Ok(subject) = argument.as_string() {
|
|
|
|
Ok(Value::from(subject.len() as i64))
|
|
|
|
} else if let Ok(subject) = argument.as_tuple() {
|
|
|
|
Ok(Value::from(subject.len() as i64))
|
|
|
|
} else {
|
|
|
|
Err(EvalexprError::type_error(
|
|
|
|
argument.clone(),
|
|
|
|
vec![ValueType::String, ValueType::Tuple],
|
|
|
|
))
|
|
|
|
}
|
2019-05-04 11:54:19 +00:00
|
|
|
}))),
|
2019-04-12 21:13:37 +00:00
|
|
|
|
|
|
|
// string functions
|
2019-04-07 06:10:36 +00:00
|
|
|
#[cfg(feature = "regex_support")]
|
2019-05-04 11:54:19 +00:00
|
|
|
"str::regex_matches" => Some(Function::new(Box::new(|argument| {
|
2019-08-29 05:56:49 +00:00
|
|
|
let arguments = argument.as_tuple()?;
|
2019-05-04 11:43:29 +00:00
|
|
|
|
2019-08-29 05:56:49 +00:00
|
|
|
let subject = arguments[0].as_string()?;
|
|
|
|
let re_str = arguments[1].as_string()?;
|
|
|
|
match Regex::new(&re_str) {
|
|
|
|
Ok(re) => Ok(Value::Boolean(re.is_match(&subject))),
|
2019-05-04 11:54:19 +00:00
|
|
|
Err(err) => Err(EvalexprError::invalid_regex(
|
|
|
|
re_str.to_string(),
|
|
|
|
format!("{}", err),
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}))),
|
2019-04-07 06:10:36 +00:00
|
|
|
#[cfg(feature = "regex_support")]
|
2019-05-04 11:54:19 +00:00
|
|
|
"str::regex_replace" => Some(Function::new(Box::new(|argument| {
|
2019-08-29 05:56:49 +00:00
|
|
|
let arguments = argument.as_tuple()?;
|
2019-05-04 11:43:29 +00:00
|
|
|
|
2019-08-29 05:56:49 +00:00
|
|
|
let subject = arguments[0].as_string()?;
|
|
|
|
let re_str = arguments[1].as_string()?;
|
|
|
|
let repl = arguments[2].as_string()?;
|
|
|
|
match Regex::new(&re_str) {
|
2019-08-29 07:02:05 +00:00
|
|
|
Ok(re) => Ok(Value::String(
|
|
|
|
re.replace_all(&subject, repl.as_str()).to_string(),
|
|
|
|
)),
|
2019-05-04 11:54:19 +00:00
|
|
|
Err(err) => Err(EvalexprError::invalid_regex(
|
|
|
|
re_str.to_string(),
|
|
|
|
format!("{}", err),
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}))),
|
|
|
|
"str::to_lowercase" => Some(Function::new(Box::new(|argument| {
|
2019-08-29 05:56:49 +00:00
|
|
|
let subject = argument.as_string()?;
|
2019-05-04 11:54:19 +00:00
|
|
|
Ok(Value::from(subject.to_lowercase()))
|
|
|
|
}))),
|
|
|
|
"str::to_uppercase" => Some(Function::new(Box::new(|argument| {
|
2019-08-29 05:56:49 +00:00
|
|
|
let subject = argument.as_string()?;
|
2019-05-04 11:54:19 +00:00
|
|
|
Ok(Value::from(subject.to_uppercase()))
|
|
|
|
}))),
|
|
|
|
"str::trim" => Some(Function::new(Box::new(|argument| {
|
2019-08-29 05:56:49 +00:00
|
|
|
let subject = argument.as_string()?;
|
2019-05-04 11:54:19 +00:00
|
|
|
Ok(Value::from(subject.trim()))
|
|
|
|
}))),
|
2019-03-19 18:08:23 +00:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|