use regex::Regex;
pub trait FormulaT {
fn name(&self) -> &str;
fn body(&self) -> &str;
fn depends_on(&self) -> &[String];
}
#[derive(Debug, Clone)]
pub struct Formula {
name: String,
body: String,
depends_on: Vec<String>,
}
impl Formula {
pub fn new(name: impl Into<String>, body: impl Into<String>) -> Self {
let name = name.into();
let body = body.into();
let depends_on = Self::build_depends_on(&body);
Self {
name,
body,
depends_on,
}
}
fn build_depends_on(body: &str) -> Vec<String> {
let pattern = r"get_output_from\('([^']+)'\)";
let re = Regex::new(pattern).unwrap();
re.captures_iter(body)
.filter_map(|cap| cap.get(1).map(|m| m.as_str().to_string()))
.collect()
}
}
impl FormulaT for Formula {
fn name(&self) -> &str {
&self.name
}
fn body(&self) -> &str {
&self.body
}
fn depends_on(&self) -> &[String] {
&self.depends_on
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_formula_creation() {
let formula = Formula::new("test", "return 1 + 1");
assert_eq!(formula.name(), "test");
assert_eq!(formula.body(), "return 1 + 1");
assert_eq!(formula.depends_on().len(), 0);
}
#[test]
fn test_formula_dependencies() {
let body = "return get_output_from('formula1') + get_output_from('formula2')";
let formula = Formula::new("test", body);
assert_eq!(formula.depends_on().len(), 2);
assert!(formula.depends_on().contains(&"formula1".to_string()));
assert!(formula.depends_on().contains(&"formula2".to_string()));
}
#[test]
fn test_formula_no_dependencies() {
let formula = Formula::new("simple", "return 42");
assert_eq!(formula.depends_on().len(), 0);
}
}