2024-01-01 08:52:25 -05:00
|
|
|
mod string;
|
|
|
|
|
2024-01-01 07:46:47 -05:00
|
|
|
use std::fs::read_to_string;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
2024-01-01 07:46:47 -05:00
|
|
|
use rand::{random, thread_rng, Rng};
|
2024-01-01 04:59:27 -05:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
use crate::{Error, Map, Result, Type, Value};
|
|
|
|
|
2024-01-01 08:52:25 -05:00
|
|
|
pub use string::{string_functions, StringFunction};
|
|
|
|
|
2024-01-01 04:59:27 -05:00
|
|
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
pub enum BuiltInFunction {
|
|
|
|
AssertEqual,
|
|
|
|
FsRead,
|
2024-01-01 07:46:47 -05:00
|
|
|
JsonParse,
|
|
|
|
Length,
|
2024-01-01 04:59:27 -05:00
|
|
|
Output,
|
|
|
|
RandomBoolean,
|
2024-01-01 07:46:47 -05:00
|
|
|
RandomFloat,
|
|
|
|
RandomFrom,
|
|
|
|
RandomInteger,
|
2024-01-01 08:52:25 -05:00
|
|
|
String(StringFunction),
|
2024-01-01 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BuiltInFunction {
|
|
|
|
pub fn name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
BuiltInFunction::AssertEqual => "assert_equal",
|
2024-01-01 07:46:47 -05:00
|
|
|
BuiltInFunction::FsRead => "read",
|
|
|
|
BuiltInFunction::JsonParse => "parse",
|
|
|
|
BuiltInFunction::Length => "length",
|
2024-01-01 04:59:27 -05:00
|
|
|
BuiltInFunction::Output => "output",
|
|
|
|
BuiltInFunction::RandomBoolean => "boolean",
|
2024-01-01 07:46:47 -05:00
|
|
|
BuiltInFunction::RandomFloat => "float",
|
|
|
|
BuiltInFunction::RandomFrom => "from",
|
|
|
|
BuiltInFunction::RandomInteger => "integer",
|
2024-01-01 08:52:25 -05:00
|
|
|
BuiltInFunction::String(string_function) => string_function.name(),
|
2024-01-01 04:59:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn r#type(&self) -> Type {
|
|
|
|
match self {
|
|
|
|
BuiltInFunction::AssertEqual => Type::function(vec![Type::Any, Type::Any], Type::None),
|
|
|
|
BuiltInFunction::FsRead => Type::function(vec![Type::String], Type::String),
|
2024-01-01 07:46:47 -05:00
|
|
|
BuiltInFunction::JsonParse => Type::function(vec![Type::String], Type::Any),
|
|
|
|
BuiltInFunction::Length => Type::function(vec![Type::Collection], Type::Integer),
|
2024-01-01 04:59:27 -05:00
|
|
|
BuiltInFunction::Output => Type::function(vec![Type::Any], Type::None),
|
|
|
|
BuiltInFunction::RandomBoolean => Type::function(vec![], Type::Boolean),
|
2024-01-01 07:46:47 -05:00
|
|
|
BuiltInFunction::RandomFloat => Type::function(vec![], Type::Float),
|
|
|
|
BuiltInFunction::RandomFrom => Type::function(vec![Type::Collection], Type::Any),
|
|
|
|
BuiltInFunction::RandomInteger => Type::function(vec![], Type::Integer),
|
2024-01-01 08:52:25 -05:00
|
|
|
BuiltInFunction::String(string_function) => string_function.r#type(),
|
2024-01-01 04:59:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn call(&self, arguments: &[Value], _source: &str, _outer_context: &Map) -> Result<Value> {
|
|
|
|
match self {
|
|
|
|
BuiltInFunction::AssertEqual => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 2, arguments.len())?;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
|
|
|
let left = arguments.get(0).unwrap();
|
|
|
|
let right = arguments.get(1).unwrap();
|
|
|
|
|
|
|
|
Ok(Value::Boolean(left == right))
|
|
|
|
}
|
|
|
|
BuiltInFunction::FsRead => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
|
|
|
let path = arguments.first().unwrap().as_string()?;
|
2024-01-01 12:39:03 -05:00
|
|
|
let file_content = read_to_string(path.as_str())?;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
2024-01-01 12:39:03 -05:00
|
|
|
Ok(Value::string(file_content))
|
2024-01-01 04:59:27 -05:00
|
|
|
}
|
2024-01-01 07:46:47 -05:00
|
|
|
BuiltInFunction::JsonParse => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
2024-01-01 07:46:47 -05:00
|
|
|
let string = arguments.first().unwrap().as_string()?;
|
|
|
|
let value = serde_json::from_str(&string)?;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
2024-01-01 07:46:47 -05:00
|
|
|
Ok(value)
|
2024-01-01 04:59:27 -05:00
|
|
|
}
|
|
|
|
BuiltInFunction::Length => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
2024-01-01 05:20:11 -05:00
|
|
|
let value = arguments.first().unwrap();
|
|
|
|
let length = if let Ok(list) = value.as_list() {
|
|
|
|
list.items().len()
|
|
|
|
} else if let Ok(map) = value.as_map() {
|
|
|
|
map.variables()?.len()
|
2024-01-01 12:39:03 -05:00
|
|
|
} else if let Ok(str) = value.as_string() {
|
|
|
|
str.chars().count()
|
2024-01-01 05:20:11 -05:00
|
|
|
} else {
|
|
|
|
return Err(Error::ExpectedCollection {
|
|
|
|
actual: value.clone(),
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Value::Integer(length as i64))
|
2024-01-01 04:59:27 -05:00
|
|
|
}
|
2024-01-01 07:46:47 -05:00
|
|
|
BuiltInFunction::Output => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
2024-01-01 04:59:27 -05:00
|
|
|
|
2024-01-01 07:46:47 -05:00
|
|
|
let value = arguments.first().unwrap();
|
|
|
|
|
|
|
|
println!("{value}");
|
|
|
|
|
|
|
|
Ok(Value::none())
|
|
|
|
}
|
|
|
|
BuiltInFunction::RandomBoolean => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 0, arguments.len())?;
|
2024-01-01 07:46:47 -05:00
|
|
|
|
|
|
|
Ok(Value::Boolean(random()))
|
|
|
|
}
|
|
|
|
BuiltInFunction::RandomFloat => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 0, arguments.len())?;
|
2024-01-01 07:46:47 -05:00
|
|
|
|
|
|
|
Ok(Value::Float(random()))
|
|
|
|
}
|
|
|
|
BuiltInFunction::RandomFrom => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
|
2024-01-01 07:46:47 -05:00
|
|
|
|
|
|
|
let value = arguments.first().unwrap();
|
|
|
|
|
|
|
|
if let Ok(list) = value.as_list() {
|
|
|
|
let items = list.items();
|
|
|
|
|
|
|
|
if items.len() == 0 {
|
|
|
|
Ok(Value::none())
|
|
|
|
} else {
|
|
|
|
let random_index = thread_rng().gen_range(0..items.len());
|
|
|
|
let random_value = items.get(random_index).cloned().unwrap_or_default();
|
|
|
|
|
|
|
|
Ok(random_value)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BuiltInFunction::RandomInteger => {
|
2024-01-01 08:52:25 -05:00
|
|
|
Error::expect_argument_amount(self.name(), 0, arguments.len())?;
|
2024-01-01 07:46:47 -05:00
|
|
|
|
|
|
|
Ok(Value::Integer(random()))
|
|
|
|
}
|
2024-01-01 08:52:25 -05:00
|
|
|
BuiltInFunction::String(string_function) => {
|
|
|
|
string_function.call(arguments, _source, _outer_context)
|
|
|
|
}
|
2024-01-01 07:46:47 -05:00
|
|
|
}
|
2024-01-01 04:59:27 -05:00
|
|
|
}
|
2023-11-28 17:54:17 -05:00
|
|
|
}
|