use super::function_trait::{Function, FunctionContext, FunctionError, FunctionResult};
use crate::storage::Value;
#[derive(Debug)]
pub struct ListContainsFunction;
impl ListContainsFunction {
pub fn new() -> Self {
Self
}
}
impl Function for ListContainsFunction {
fn name(&self) -> &str {
"LIST_CONTAINS"
}
fn description(&self) -> &str {
"Check if list contains the specified element"
}
fn argument_count(&self) -> usize {
2
}
fn return_type(&self) -> &str {
"Boolean"
}
fn execute(&self, context: &FunctionContext) -> FunctionResult<Value> {
if context.arguments.len() != 2 {
return Err(FunctionError::InvalidArgumentCount {
expected: 2,
actual: context.arguments.len(),
});
}
let list_arg = &context.arguments[0];
let element_arg = &context.arguments[1];
let list_values = list_arg
.as_list()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "First argument must be a list".to_string(),
})?;
let contains = list_values.iter().any(|item| item == element_arg);
Ok(Value::Boolean(contains))
}
}
#[derive(Debug)]
pub struct ListSliceFunction;
impl ListSliceFunction {
pub fn new() -> Self {
Self
}
}
impl Function for ListSliceFunction {
fn name(&self) -> &str {
"LIST_SLICE"
}
fn description(&self) -> &str {
"Extract a slice of the list from start index to end index (exclusive)"
}
fn argument_count(&self) -> usize {
3
}
fn return_type(&self) -> &str {
"List"
}
fn execute(&self, context: &FunctionContext) -> FunctionResult<Value> {
if context.arguments.len() != 3 {
return Err(FunctionError::InvalidArgumentCount {
expected: 3,
actual: context.arguments.len(),
});
}
let list_arg = &context.arguments[0];
let start_arg = &context.arguments[1];
let end_arg = &context.arguments[2];
let list_values = list_arg
.as_list()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "First argument must be a list".to_string(),
})?;
let start_idx =
start_arg
.as_integer()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "Start index must be an integer".to_string(),
})? as usize;
let end_idx = end_arg
.as_integer()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "End index must be an integer".to_string(),
})? as usize;
if start_idx >= list_values.len() {
return Ok(Value::List(Vec::new()));
}
let actual_end = end_idx.min(list_values.len());
if start_idx >= actual_end {
return Ok(Value::List(Vec::new()));
}
let slice = list_values[start_idx..actual_end].to_vec();
Ok(Value::List(slice))
}
}
#[derive(Debug)]
pub struct ListAppendFunction;
impl ListAppendFunction {
pub fn new() -> Self {
Self
}
}
impl Function for ListAppendFunction {
fn name(&self) -> &str {
"LIST_APPEND"
}
fn description(&self) -> &str {
"Append element or elements to the end of a list"
}
fn argument_count(&self) -> usize {
2
}
fn return_type(&self) -> &str {
"List"
}
fn execute(&self, context: &FunctionContext) -> FunctionResult<Value> {
if context.arguments.len() != 2 {
return Err(FunctionError::InvalidArgumentCount {
expected: 2,
actual: context.arguments.len(),
});
}
let list_arg = &context.arguments[0];
let element_arg = &context.arguments[1];
let mut list_values = list_arg
.as_list()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "First argument must be a list".to_string(),
})?
.clone();
match element_arg {
Value::List(elements) => {
list_values.extend(elements.clone());
}
element => {
list_values.push(element.clone());
}
}
Ok(Value::List(list_values))
}
}
#[derive(Debug)]
pub struct ListPrependFunction;
impl ListPrependFunction {
pub fn new() -> Self {
Self
}
}
impl Function for ListPrependFunction {
fn name(&self) -> &str {
"LIST_PREPEND"
}
fn description(&self) -> &str {
"Prepend element or elements to the beginning of a list"
}
fn argument_count(&self) -> usize {
2
}
fn return_type(&self) -> &str {
"List"
}
fn execute(&self, context: &FunctionContext) -> FunctionResult<Value> {
if context.arguments.len() != 2 {
return Err(FunctionError::InvalidArgumentCount {
expected: 2,
actual: context.arguments.len(),
});
}
let list_arg = &context.arguments[0];
let element_arg = &context.arguments[1];
let list_values = list_arg
.as_list()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "First argument must be a list".to_string(),
})?;
let mut result = Vec::new();
match element_arg {
Value::List(elements) => {
result.extend(elements.clone());
}
element => {
result.push(element.clone());
}
}
result.extend(list_values.clone());
Ok(Value::List(result))
}
}
#[derive(Debug)]
pub struct ListLengthFunction;
impl ListLengthFunction {
pub fn new() -> Self {
Self
}
}
impl Function for ListLengthFunction {
fn name(&self) -> &str {
"LIST_LENGTH"
}
fn description(&self) -> &str {
"Get the length of a list"
}
fn argument_count(&self) -> usize {
1
}
fn return_type(&self) -> &str {
"Integer"
}
fn execute(&self, context: &FunctionContext) -> FunctionResult<Value> {
if context.arguments.len() != 1 {
return Err(FunctionError::InvalidArgumentCount {
expected: 1,
actual: context.arguments.len(),
});
}
let list_arg = &context.arguments[0];
let list_values = list_arg
.as_list()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "Argument must be a list".to_string(),
})?;
Ok(Value::Number(list_values.len() as f64))
}
}
#[derive(Debug)]
pub struct ListReverseFunction;
impl ListReverseFunction {
pub fn new() -> Self {
Self
}
}
impl Function for ListReverseFunction {
fn name(&self) -> &str {
"LIST_REVERSE"
}
fn description(&self) -> &str {
"Reverse the order of elements in a list"
}
fn argument_count(&self) -> usize {
1
}
fn return_type(&self) -> &str {
"List"
}
fn execute(&self, context: &FunctionContext) -> FunctionResult<Value> {
if context.arguments.len() != 1 {
return Err(FunctionError::InvalidArgumentCount {
expected: 1,
actual: context.arguments.len(),
});
}
let list_arg = &context.arguments[0];
let list_values = list_arg
.as_list()
.ok_or_else(|| FunctionError::InvalidArgumentType {
message: "Argument must be a list".to_string(),
})?;
let mut reversed = list_values.clone();
reversed.reverse();
Ok(Value::List(reversed))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
fn create_context(args: Vec<Value>) -> FunctionContext {
FunctionContext::new(Vec::new(), HashMap::new(), args)
}
#[test]
fn test_list_contains() {
let func = ListContainsFunction::new();
let list = Value::List(vec![
Value::Number(1.0),
Value::Number(2.0),
Value::Number(3.0),
]);
let context = create_context(vec![list, Value::Number(2.0)]);
let result = func.execute(&context).unwrap();
assert_eq!(result, Value::Boolean(true));
let list = Value::List(vec![
Value::Number(1.0),
Value::Number(2.0),
Value::Number(3.0),
]);
let context = create_context(vec![list, Value::Number(4.0)]);
let result = func.execute(&context).unwrap();
assert_eq!(result, Value::Boolean(false));
}
#[test]
fn test_list_slice() {
let func = ListSliceFunction::new();
let list = Value::List(vec![
Value::Number(1.0),
Value::Number(2.0),
Value::Number(3.0),
Value::Number(4.0),
Value::Number(5.0),
]);
let context = create_context(vec![list.clone(), Value::Number(1.0), Value::Number(4.0)]);
let result = func.execute(&context).unwrap();
let expected = Value::List(vec![
Value::Number(2.0),
Value::Number(3.0),
Value::Number(4.0),
]);
assert_eq!(result, expected);
let context = create_context(vec![list.clone(), Value::Number(3.0), Value::Number(10.0)]);
let result = func.execute(&context).unwrap();
let expected = Value::List(vec![Value::Number(4.0), Value::Number(5.0)]);
assert_eq!(result, expected);
}
#[test]
fn test_list_append() {
let func = ListAppendFunction::new();
let list = Value::List(vec![Value::Number(1.0), Value::Number(2.0)]);
let context = create_context(vec![list, Value::Number(3.0)]);
let result = func.execute(&context).unwrap();
let expected = Value::List(vec![
Value::Number(1.0),
Value::Number(2.0),
Value::Number(3.0),
]);
assert_eq!(result, expected);
}
#[test]
fn test_list_prepend() {
let func = ListPrependFunction::new();
let list = Value::List(vec![Value::Number(2.0), Value::Number(3.0)]);
let context = create_context(vec![list, Value::Number(1.0)]);
let result = func.execute(&context).unwrap();
let expected = Value::List(vec![
Value::Number(1.0),
Value::Number(2.0),
Value::Number(3.0),
]);
assert_eq!(result, expected);
}
#[test]
fn test_list_length() {
let func = ListLengthFunction::new();
let list = Value::List(vec![
Value::Number(1.0),
Value::Number(2.0),
Value::Number(3.0),
]);
let context = create_context(vec![list]);
let result = func.execute(&context).unwrap();
assert_eq!(result, Value::Number(3.0));
}
#[test]
fn test_list_reverse() {
let func = ListReverseFunction::new();
let list = Value::List(vec![
Value::Number(1.0),
Value::Number(2.0),
Value::Number(3.0),
]);
let context = create_context(vec![list]);
let result = func.execute(&context).unwrap();
let expected = Value::List(vec![
Value::Number(3.0),
Value::Number(2.0),
Value::Number(1.0),
]);
assert_eq!(result, expected);
}
}