use {
crate::{Cast, CastWithRules, Convert, Result, Value, ValueError},
chrono::NaiveDateTime,
uuid::Uuid,
};
macro_rules! expect_arguments {
($arguments: expr, $expect: expr) => {
match $arguments.len() {
$expect => (),
found => {
return Err(ValueError::NumberOfFunctionParamsNotMatching {
expected: $expect,
found,
}
.into())
}
}
};
}
macro_rules! optional_expect_arguments {
($arguments: expr, $min: expr, $max: expr) => {
match $arguments.len() {
len if ($min..=$max).contains(&len) => (),
found => {
return Err(ValueError::NumberOfFunctionParamsNotMatching {
expected: $min,
found,
}
.into())
}
}
};
}
impl Value {
pub fn function_if_null(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 2);
Ok(arguments.remove(0).if_null(arguments.remove(0)))
}
pub fn function_null_if(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 2);
arguments.remove(0).null_if(arguments.remove(0))
}
pub fn function_iif(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 3);
arguments
.remove(0)
.iif(arguments.remove(0), arguments.remove(0))
}
pub fn function_to_lowercase(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 1);
arguments.remove(0).to_lowercase()
}
pub fn function_to_uppercase(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 1);
arguments.remove(0).to_uppercase()
}
pub fn function_left(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 2);
arguments.remove(0).left(arguments.remove(0))
}
pub fn function_right(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 2);
arguments.remove(0).right(arguments.remove(0))
}
pub fn function_length(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 1);
arguments.remove(0).length()
}
pub fn function_concat(mut arguments: Vec<Self>) -> Result<Self> {
arguments.remove(0).concat(arguments)
}
pub fn function_replace(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 3);
arguments
.remove(0)
.replace(arguments.remove(0), arguments.remove(0))
}
pub fn function_round(mut arguments: Vec<Self>) -> Result<Self> {
optional_expect_arguments!(arguments, 1, 2);
let value = arguments.remove(0);
let places = if !arguments.is_empty() {
arguments.remove(0)
} else {
Self::I64(0)
};
value.round(places)
}
pub fn function_rand(arguments: Vec<Self>) -> Result<Self> {
match arguments.len() {
0 => Self::function_random_float(arguments),
2 => Self::function_random_int(arguments),
found => {
Err(ValueError::NumberOfFunctionParamsNotMatching { expected: 0, found }.into())
}
}
}
pub fn function_random_float(arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 0);
Ok(Self::F64(fastrand::f64()))
}
pub fn function_random_int(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 2);
let min: i64 = arguments.remove(0).cast()?;
let max: i64 = arguments.remove(0).cast()?;
Ok(Self::I64(fastrand::i64(min..=max)))
}
pub fn function_uuid(arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 0);
Ok(Self::Str(Uuid::new_v4().to_hyphenated().to_string())) }
pub fn function_pow(mut arguments: Vec<Self>) -> Result<Self> {
expect_arguments!(arguments, 2);
arguments.remove(0).pow(arguments.remove(0))
}
pub fn function_convert(mut arguments: Vec<Self>) -> Result<Self> {
optional_expect_arguments!(arguments, 2, 3);
let datatype: String = arguments.remove(0).convert()?;
let value = arguments.remove(0);
let rule = if !arguments.is_empty() {
arguments.remove(0)
} else {
Self::I64(0)
};
Ok(match datatype.to_uppercase().as_str() {
"BOOLEAN" => Value::Bool(value.cast_with_rule(rule)?),
"INTEGER" => Value::I64(value.cast_with_rule(rule)?),
"FLOAT" => Value::F64(value.cast_with_rule(rule)?),
"TEXT" => Value::Str(value.cast_with_rule(rule)?),
"TIMESTAMP" => {
let datetime: NaiveDateTime = value.cast_with_rule(rule)?;
Value::I64(datetime.timestamp())
}
_ => return Err(ValueError::UnimplementedConvert.into()),
})
}
pub fn function_try_convert(arguments: Vec<Self>) -> Result<Self> {
Ok(Value::function_convert(arguments).unwrap_or(Value::Null))
}
}