swift_mt_message/validation/
mod.rs1use crate::errors::{ParseError, Result};
2use datalogic_rs::DataLogic;
3use serde_json::Value;
4use std::fs;
5use std::path::Path;
6
7#[derive(Debug)]
9pub struct ValidationResult {
10 pub rule_name: String,
11 pub passed: bool,
12 pub message: String,
13}
14
15#[derive(Debug)]
17pub struct ValidationReport {
18 pub results: Vec<ValidationResult>,
19 pub overall_valid: bool,
20}
21
22impl Default for ValidationReport {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl ValidationReport {
29 pub fn new() -> Self {
31 Self {
32 results: Vec::new(),
33 overall_valid: true,
34 }
35 }
36
37 pub fn add_result(&mut self, result: ValidationResult) {
39 if !result.passed {
40 self.overall_valid = false;
41 }
42 self.results.push(result);
43 }
44
45 pub fn failure_count(&self) -> usize {
47 self.results.iter().filter(|r| !r.passed).count()
48 }
49
50 pub fn get_failures(&self) -> Vec<&ValidationResult> {
52 self.results.iter().filter(|r| !r.passed).collect()
53 }
54}
55
56pub fn validate_mt_message_with_rules<P: AsRef<Path>>(
65 message_json: Value,
66 rules_file_path: P,
67) -> Result<ValidationReport> {
68 let mut report = ValidationReport::new();
69
70 let rules_content =
72 fs::read_to_string(rules_file_path).map_err(|e| ParseError::ValidationError {
73 message: format!("Failed to read rules file: {}", e),
74 })?;
75
76 let rules_json: Value =
78 serde_json::from_str(&rules_content).map_err(|e| ParseError::ValidationError {
79 message: format!("Failed to parse rules JSON: {}", e),
80 })?;
81
82 let rules_array = rules_json
84 .get("rules")
85 .and_then(|r| r.as_array())
86 .ok_or_else(|| ParseError::ValidationError {
87 message: "Rules file must contain a 'rules' array".to_string(),
88 })?;
89
90 let engine = DataLogic::new();
92
93 for rule in rules_array {
95 let rule_name = rule
96 .get("name")
97 .and_then(|n| n.as_str())
98 .unwrap_or("Unknown Rule")
99 .to_string();
100
101 let rule_message = rule
102 .get("message")
103 .and_then(|m| m.as_str())
104 .unwrap_or("Validation failed")
105 .to_string();
106
107 let logic = rule
109 .get("logic")
110 .ok_or_else(|| ParseError::ValidationError {
111 message: format!("Rule '{}' missing 'logic' field", rule_name),
112 })?;
113
114 let rule_result = engine
116 .evaluate_json(logic, &message_json, None)
117 .map_err(|e| ParseError::ValidationError {
118 message: format!("Failed to evaluate rule '{}': {}", rule_name, e),
119 })?;
120
121 let passed = rule_result.is_boolean() && rule_result.as_bool().unwrap();
123
124 report.add_result(ValidationResult {
125 rule_name,
126 passed,
127 message: rule_message,
128 });
129 }
130
131 Ok(report)
132}