use std::sync::LazyLock;
use regex::Regex;
use crate::msodde::field_parser::DdeField;
static RE_CSV_DDE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r#"(?m)^["']?[=+\-@].*\|.*!"#).unwrap()
});
pub fn process_csv(data: &[u8]) -> Vec<DdeField> {
let text = String::from_utf8_lossy(data);
let mut fields = Vec::new();
for mat in RE_CSV_DDE.find_iter(&text) {
let matched = mat.as_str().trim();
let formula = matched.trim_start_matches(['"', '\'']);
fields.push(DdeField {
field_instruction: formula.to_string(),
command: formula.to_string(),
source: extract_dde_source(formula),
quote_decoded: None,
});
}
fields
}
fn extract_dde_source(formula: &str) -> String {
let stripped = formula.trim_start_matches(|c: char| "=+-@".contains(c));
if let Some(pipe_pos) = stripped.find('|') {
stripped[..pipe_pos].trim().to_string()
} else {
String::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_csv_dde_formula() {
let csv = b"Name,Value\n=cmd|'/c calc'!A0,test\n";
let fields = process_csv(csv);
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].source, "cmd");
}
#[test]
fn test_csv_dde_plus() {
let csv = b"+cmd|'/c whoami'!A0\n";
let fields = process_csv(csv);
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].source, "cmd");
}
#[test]
fn test_csv_dde_minus() {
let csv = b"-cmd|'/c dir'!A0\n";
let fields = process_csv(csv);
assert_eq!(fields.len(), 1);
}
#[test]
fn test_csv_dde_at() {
let csv = b"@SUM(cmd|'/c calc'!A0)\n";
let fields = process_csv(csv);
assert_eq!(fields.len(), 1);
}
#[test]
fn test_csv_no_dde() {
let csv = b"Name,Value\nAlice,100\nBob,200\n";
let fields = process_csv(csv);
assert!(fields.is_empty());
}
#[test]
fn test_csv_normal_formula() {
let csv = b"=A1+B1\n=SUM(A1:A10)\n";
let fields = process_csv(csv);
assert!(fields.is_empty(), "Normal formulas without pipe should not match");
}
#[test]
fn test_csv_empty() {
let fields = process_csv(b"");
assert!(fields.is_empty());
}
#[test]
fn test_extract_dde_source() {
assert_eq!(extract_dde_source("=cmd|'/c calc'!A0"), "cmd");
assert_eq!(extract_dde_source("+MSEXCEL|'Sheet1'!A1"), "MSEXCEL");
assert_eq!(extract_dde_source("=no_pipe"), "");
}
}