use crate::script_engine::instruction::{
InstructionData, InstructionHandler, InstructionMetadata, ScriptError,
};
use crate::script_engine::VMContext;
#[derive(Debug, Clone)]
pub struct ModeParams {
pub key: String,
pub value: String,
}
pub struct ModeHandler;
impl InstructionHandler for ModeHandler {
fn name(&self) -> &str {
"mode"
}
fn parse(&self, args: &[&str]) -> Result<InstructionData, ScriptError> {
if args.len() != 2 {
return Err(ScriptError::ParseError(
"Invalid parameters. Usage: mode <key> <value>".into(),
));
}
let key = args[0].to_string();
let value = args[1].to_string();
if key.is_empty() || value.is_empty() {
return Err(ScriptError::ParseError(
"Key and value cannot be empty".into(),
));
}
Ok(InstructionData::Custom(Box::new(ModeParams { key, value })))
}
fn execute(
&self,
vm: &mut VMContext,
data: &InstructionData,
_metadata: Option<&InstructionMetadata>,
) -> Result<(), ScriptError> {
let params = data.extract_custom::<ModeParams>("Invalid mode parameters")?;
vm.set_persistent_state(¶ms.key, params.value.clone());
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_mode_input_mode_post() {
let handler = ModeHandler;
let result = handler.parse(&["input_mode", "post"]).unwrap();
match result {
InstructionData::Custom(boxed) => {
let params = boxed.downcast_ref::<ModeParams>().unwrap();
assert_eq!(params.key, "input_mode");
assert_eq!(params.value, "post");
}
_ => panic!("Expected Custom data"),
}
}
#[test]
fn test_parse_mode_input_mode_send() {
let handler = ModeHandler;
let result = handler.parse(&["input_mode", "send"]).unwrap();
match result {
InstructionData::Custom(boxed) => {
let params = boxed.downcast_ref::<ModeParams>().unwrap();
assert_eq!(params.key, "input_mode");
assert_eq!(params.value, "send");
}
_ => panic!("Expected Custom data"),
}
}
#[test]
fn test_parse_mode_missing_parameters() {
let handler = ModeHandler;
let result = handler.parse(&[]);
assert!(result.is_err());
let result = handler.parse(&["input_mode"]);
assert!(result.is_err());
let result = handler.parse(&["input_mode", "post", "extra"]);
assert!(result.is_err());
}
#[test]
fn test_execute_mode_configuration() {
let handler = ModeHandler;
let mut vm = VMContext::new();
let data = handler.parse(&["input_mode", "post"]).unwrap();
handler.execute(&mut vm, &data, None).unwrap();
let mode = vm.get_persistent_state::<String>("input_mode").cloned();
assert_eq!(mode, Some("post".to_string()));
let data = handler.parse(&["input_mode", "send"]).unwrap();
handler.execute(&mut vm, &data, None).unwrap();
let mode = vm.get_persistent_state::<String>("input_mode").cloned();
assert_eq!(mode, Some("send".to_string()));
}
#[test]
fn test_mode_independence_between_keys() {
let handler = ModeHandler;
let mut vm = VMContext::new();
let data1 = handler.parse(&["input_mode", "post"]).unwrap();
handler.execute(&mut vm, &data1, None).unwrap();
let data2 = handler.parse(&["debug_level", "verbose"]).unwrap();
handler.execute(&mut vm, &data2, None).unwrap();
let input_mode = vm.get_persistent_state::<String>("input_mode").cloned();
let debug_level = vm.get_persistent_state::<String>("debug_level").cloned();
assert_eq!(input_mode, Some("post".to_string()));
assert_eq!(debug_level, Some("verbose".to_string()));
}
#[test]
fn test_mode_overwrite_same_key() {
let handler = ModeHandler;
let mut vm = VMContext::new();
let data1 = handler.parse(&["input_mode", "post"]).unwrap();
handler.execute(&mut vm, &data1, None).unwrap();
let data2 = handler.parse(&["input_mode", "send"]).unwrap();
handler.execute(&mut vm, &data2, None).unwrap();
let mode = vm.get_persistent_state::<String>("input_mode").cloned();
assert_eq!(mode, Some("send".to_string()));
}
}