use std::collections::HashMap;
use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum ContextError {
#[allow(dead_code)]
MergeError(String),
#[allow(dead_code)]
NotFound(String),
}
impl fmt::Display for ContextError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ContextError::MergeError(msg) => write!(f, "Context merge error: {}", msg),
ContextError::NotFound(var) => write!(f, "Variable not found: {}", var),
}
}
}
impl Error for ContextError {}
#[allow(dead_code)]
pub type ContextResult<T> = Result<T, ContextError>;
#[allow(dead_code)]
#[derive(Default, Debug, Clone)]
pub struct Context {
variables: HashMap<String, String>,
}
#[allow(dead_code)]
impl Context {
pub fn new() -> Self {
Self {
variables: HashMap::new(),
}
}
pub fn with_variables(variables: HashMap<String, String>) -> Self {
Self { variables }
}
pub fn add_variable(&mut self, name: String, value: String) {
self.variables.insert(name, value);
}
pub fn remove_variable(&mut self, name: &str) -> Option<String> {
self.variables.remove(name)
}
pub fn get_variable(&self, name: &str) -> Option<&String> {
self.variables.get(name)
}
pub fn has_variable(&self, name: &str) -> bool {
self.variables.contains_key(name)
}
pub fn get_variables(&self) -> &HashMap<String, String> {
&self.variables
}
pub fn get_variables_mut(&mut self) -> &mut HashMap<String, String> {
&mut self.variables
}
pub fn merge(&mut self, other: &Context) {
for (name, value) in &other.variables {
self.variables.insert(name.clone(), value.clone());
}
}
pub fn merged_with(&self, other: &Context) -> Self {
let mut result = self.clone();
result.merge(other);
result
}
pub fn create_child(&self) -> Self {
self.clone()
}
pub fn add_built_ins(&mut self) {
let now = chrono::Local::now();
self.add_variable(
"current_date".to_string(),
now.format("%Y-%m-%d").to_string(),
);
self.add_variable(
"current_time".to_string(),
now.format("%H:%M:%S").to_string(),
);
self.add_variable(
"current_datetime".to_string(),
now.format("%Y-%m-%d %H:%M:%S").to_string(),
);
let uuid = uuid::Uuid::new_v4().to_string();
self.add_variable("uuid".to_string(), uuid);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_and_get_variable() {
let mut context = Context::new();
context.add_variable("name".to_string(), "Value".to_string());
assert_eq!(context.get_variable("name"), Some(&"Value".to_string()));
assert_eq!(context.get_variable("nonexistent"), None);
}
#[test]
fn test_has_variable() {
let mut context = Context::new();
context.add_variable("name".to_string(), "Value".to_string());
assert!(context.has_variable("name"));
assert!(!context.has_variable("nonexistent"));
}
#[test]
fn test_remove_variable() {
let mut context = Context::new();
context.add_variable("name".to_string(), "Value".to_string());
let removed = context.remove_variable("name");
assert_eq!(removed, Some("Value".to_string()));
assert!(!context.has_variable("name"));
let nonexistent = context.remove_variable("nonexistent");
assert_eq!(nonexistent, None);
}
#[test]
fn test_context_merge() {
let mut context1 = Context::new();
context1.add_variable("var1".to_string(), "Value1".to_string());
context1.add_variable("common".to_string(), "OriginalValue".to_string());
let mut context2 = Context::new();
context2.add_variable("var2".to_string(), "Value2".to_string());
context2.add_variable("common".to_string(), "NewValue".to_string());
context1.merge(&context2);
assert_eq!(context1.get_variable("var1"), Some(&"Value1".to_string()));
assert_eq!(context1.get_variable("var2"), Some(&"Value2".to_string()));
assert_eq!(
context1.get_variable("common"),
Some(&"NewValue".to_string())
);
}
#[test]
fn test_merged_with() {
let mut context1 = Context::new();
context1.add_variable("var1".to_string(), "Value1".to_string());
let mut context2 = Context::new();
context2.add_variable("var2".to_string(), "Value2".to_string());
let merged = context1.merged_with(&context2);
assert_eq!(context1.get_variable("var1"), Some(&"Value1".to_string()));
assert_eq!(context1.get_variable("var2"), None);
assert_eq!(context2.get_variable("var1"), None);
assert_eq!(context2.get_variable("var2"), Some(&"Value2".to_string()));
assert_eq!(merged.get_variable("var1"), Some(&"Value1".to_string()));
assert_eq!(merged.get_variable("var2"), Some(&"Value2".to_string()));
}
#[test]
fn test_with_initial_variables() {
let mut variables = HashMap::new();
variables.insert("var1".to_string(), "Value1".to_string());
variables.insert("var2".to_string(), "Value2".to_string());
let context = Context::with_variables(variables);
assert_eq!(context.get_variable("var1"), Some(&"Value1".to_string()));
assert_eq!(context.get_variable("var2"), Some(&"Value2".to_string()));
}
#[test]
fn test_add_built_ins() {
let mut context = Context::new();
context.add_built_ins();
assert!(context.has_variable("current_date"));
assert!(context.has_variable("current_time"));
assert!(context.has_variable("current_datetime"));
assert!(context.has_variable("uuid"));
}
}