use crate::mark_fail;
use mumu::{
parser::interpreter::Interpreter,
parser::types::Value,
};
use std::{
fs,
sync::{Arc, Mutex},
};
fn file_contents_equal_bridge_fn(
_interp: &mut Interpreter,
mut args: Vec<Value>
) -> Result<Value, String> {
if args.len() != 2 {
return Err(format!(
"file_contents_equal => expected 2 arguments => (filename, string), got {}",
args.len()
));
}
let filename_val = args.remove(0);
let filename_str = match filename_val {
Value::SingleString(s) => s,
Value::StrArray(a) if a.len() == 1 => a[0].clone(),
other => {
mark_fail(&format!(
"file_contents_equal => first argument must be a single string (filename), got {:?}",
other
));
return Ok(Value::Bool(true));
}
};
let expected_val = args.remove(0);
let expected_str = match expected_val {
Value::SingleString(s) => s,
Value::StrArray(a) if a.len() == 1 => a[0].clone(),
other => {
mark_fail(&format!(
"file_contents_equal => second argument must be single string, got {:?}",
other
));
return Ok(Value::Bool(true));
}
};
match fs::read_to_string(&filename_str) {
Ok(file_str) => {
if file_str != expected_str {
mark_fail(&format!(
"file_contents_equal fail: file='{}', actual=SingleString({}), expected=SingleString({})",
filename_str,
file_str,
expected_str
));
}
}
Err(e) => {
mark_fail(&format!(
"file_contents_equal => cannot read '{}': {}",
filename_str,
e
));
}
}
Ok(Value::Bool(true))
}
fn file_contents_not_equal_bridge_fn(
_interp: &mut Interpreter,
mut args: Vec<Value>
) -> Result<Value, String> {
if args.len() != 2 {
return Err(format!(
"file_contents_not_equal => expected 2 arguments => (filename, string), got {}",
args.len()
));
}
let filename_val = args.remove(0);
let filename_str = match filename_val {
Value::SingleString(s) => s,
Value::StrArray(a) if a.len() == 1 => a[0].clone(),
other => {
mark_fail(&format!(
"file_contents_not_equal => first argument must be single string (filename), got {:?}",
other
));
return Ok(Value::Bool(true));
}
};
let compare_val = args.remove(0);
let compare_str = match compare_val {
Value::SingleString(s) => s,
Value::StrArray(a) if a.len() == 1 => a[0].clone(),
other => {
mark_fail(&format!(
"file_contents_not_equal => second argument must be single string, got {:?}",
other
));
return Ok(Value::Bool(true));
}
};
match fs::read_to_string(&filename_str) {
Ok(file_str) => {
if file_str == compare_str {
mark_fail(&format!(
"file_contents_not_equal fail: file='{}', actual=SingleString({}), not_expected=SingleString({})",
filename_str,
file_str,
compare_str
));
}
}
Err(e) => {
mark_fail(&format!(
"file_contents_not_equal => cannot read '{}': {}",
filename_str, e
));
}
}
Ok(Value::Bool(true))
}
fn file_contents_length_equal_bridge_fn(
_interp: &mut Interpreter,
mut args: Vec<Value>
) -> Result<Value, String> {
if args.len() != 2 {
return Err(format!(
"file_contents_length_equal => expected 2 arguments => (filename, length), got {}",
args.len()
));
}
let filename_val = args.remove(0);
let filename_str = match filename_val {
Value::SingleString(s) => s,
Value::StrArray(a) if a.len() == 1 => a[0].clone(),
other => {
mark_fail(&format!(
"file_contents_length_equal => first argument must be single string (filename), got {:?}",
other
));
return Ok(Value::Bool(true));
}
};
let length_val = args.remove(0);
let expected_len = match length_val {
Value::Int(n) if n >= 0 => n as usize,
Value::IntArray(a) if a.len() == 1 && a[0] >= 0 => a[0] as usize,
other => {
mark_fail(&format!(
"file_contents_length_equal => second argument must be a non-negative int, got {:?}",
other
));
return Ok(Value::Bool(true));
}
};
match fs::read_to_string(&filename_str) {
Ok(file_str) => {
let actual_len = file_str.len();
if actual_len != expected_len {
mark_fail(&format!(
"file_contents_length_equal => file='{}' => length mismatch => actual={}, expected={}",
filename_str,
actual_len,
expected_len
));
}
}
Err(e) => {
mark_fail(&format!(
"file_contents_length_equal => cannot read '{}': {}",
filename_str,
e
));
}
}
Ok(Value::Bool(true))
}
pub fn register_file_asserts(interp: &mut Interpreter) {
use mumu::parser::interpreter::DynamicFn;
use mumu::parser::types::FunctionValue;
let eq_fn: DynamicFn = Arc::new(Mutex::new(file_contents_equal_bridge_fn));
interp.register_dynamic_function("file_contents_equal", eq_fn);
interp.set_variable(
"file_contents_equal",
Value::Function(Box::new(FunctionValue::Named("file_contents_equal".to_string())))
);
let neq_fn: DynamicFn = Arc::new(Mutex::new(file_contents_not_equal_bridge_fn));
interp.register_dynamic_function("file_contents_not_equal", neq_fn);
interp.set_variable(
"file_contents_not_equal",
Value::Function(Box::new(FunctionValue::Named("file_contents_not_equal".to_string())))
);
let len_eq_fn: DynamicFn = Arc::new(Mutex::new(file_contents_length_equal_bridge_fn));
interp.register_dynamic_function("file_contents_length_equal", len_eq_fn);
interp.set_variable(
"file_contents_length_equal",
Value::Function(Box::new(FunctionValue::Named("file_contents_length_equal".to_string())))
);
}