basic_parsed/
basic_parsed.rs1mod common;
2
3use std::fs;
4use std::path::Path;
5use std::sync::Arc;
6use std::time::Instant;
7use json_eval_rs::{JSONEval, ParsedSchema};
8use serde_json::{Map, Value};
9
10fn print_help(program_name: &str) {
11 println!("\nš JSON Evaluation - Basic Example (ParsedSchema)\n");
12 println!("USAGE:");
13 println!(" {} [OPTIONS] [FILTER]\n", program_name);
14 println!("OPTIONS:");
15 println!(" -h, --help Show this help message");
16 println!(" --compare Enable comparison with expected results");
17 println!(" --timing Show detailed internal timing breakdown\n");
18 println!("ARGUMENTS:");
19 println!(" [FILTER] Optional filter to match scenario names\n");
20 println!("DESCRIPTION:");
21 println!(" Evaluates schemas using ParsedSchema for efficient caching.");
22 println!(" Schema is parsed once and reused with Arc<ParsedSchema>.\n");
23 println!("EXAMPLES:");
24 println!(" {} # Run all scenarios with ParsedSchema", program_name);
25 println!(" {} zcc # Run scenarios matching 'zcc'", program_name);
26 println!(" {} --compare # Run with comparison enabled", program_name);
27 println!(" {} zcc --timing # Run with detailed timing breakdown", program_name);
28}
29
30fn main() {
31 let args: Vec<String> = std::env::args().collect();
32 let program_name = args.get(0).map(|s| s.as_str()).unwrap_or("basic_parsed");
33
34 let mut scenario_filter: Option<String> = None;
35 let mut enable_comparison = false;
36 let mut show_timing = false;
37 let mut i = 1;
38
39 while i < args.len() {
41 let arg = &args[i];
42
43 if arg == "-h" || arg == "--help" {
44 print_help(program_name);
45 return;
46 } else if arg == "--compare" {
47 enable_comparison = true;
48 } else if arg == "--timing" {
49 show_timing = true;
50 } else if !arg.starts_with('-') {
51 scenario_filter = Some(arg.clone());
52 } else {
53 eprintln!("Error: unknown option '{}'", arg);
54 print_help(program_name);
55 return;
56 }
57
58 i += 1;
59 }
60
61 println!("\nš JSON Evaluation - Basic Example (ParsedSchema)\n");
62 println!("š¦ Using Arc<ParsedSchema> for efficient caching\n");
63
64 if enable_comparison {
65 println!("š Comparison: enabled");
66 }
67 if show_timing {
68 println!("ā±ļø Internal timing: enabled");
69 }
70 if enable_comparison || show_timing {
71 println!();
72 }
73
74 let samples_dir = Path::new("samples");
75 let mut scenarios = common::discover_scenarios(samples_dir);
76
77 if let Some(ref filter) = scenario_filter {
79 scenarios.retain(|s| s.name.contains(filter));
80 println!("š Filtering scenarios matching: '{}'\n", filter);
81 }
82
83 if scenarios.is_empty() {
84 if let Some(filter) = scenario_filter {
85 println!(
86 "ā¹ļø No scenarios found matching '{}' in `{}`.",
87 filter,
88 samples_dir.display()
89 );
90 } else {
91 println!(
92 "ā¹ļø No scenarios discovered in `{}`. Add files like `name.json` and `name-data.json`.",
93 samples_dir.display()
94 );
95 }
96 return;
97 }
98
99 println!("š Found {} scenario(s)\n", scenarios.len());
100
101 let mut total_parse_time = std::time::Duration::ZERO;
102 let mut total_eval_time = std::time::Duration::ZERO;
103 let mut successful_scenarios = 0;
104 let mut comparison_failures = 0;
105
106 for scenario in &scenarios {
107 println!("==============================");
108 println!("Scenario: {}", scenario.name);
109 println!("Schema: {} ({})",
110 scenario.schema_path.display(),
111 if scenario.is_msgpack { "MessagePack" } else { "JSON" }
112 );
113 println!("Data: {}\n", scenario.data_path.display());
114
115 if show_timing {
117 json_eval_rs::enable_timing();
118 json_eval_rs::clear_timing_data();
119 }
120
121 let data_str = fs::read_to_string(&scenario.data_path)
122 .unwrap_or_else(|e| panic!("failed to read {}: {}", scenario.data_path.display(), e));
123
124 let parse_start = Instant::now();
126 let parsed_schema = if scenario.is_msgpack {
127 let schema_msgpack = fs::read(&scenario.schema_path)
128 .unwrap_or_else(|e| panic!("failed to read {}: {}", scenario.schema_path.display(), e));
129 println!(" š¦ MessagePack schema size: {} bytes", schema_msgpack.len());
130 Arc::new(ParsedSchema::parse_msgpack(&schema_msgpack)
131 .unwrap_or_else(|e| panic!("failed to parse MessagePack schema: {}", e)))
132 } else {
133 let schema_str = fs::read_to_string(&scenario.schema_path)
134 .unwrap_or_else(|e| panic!("failed to read {}: {}", scenario.schema_path.display(), e));
135 Arc::new(ParsedSchema::parse(&schema_str)
136 .unwrap_or_else(|e| panic!("failed to parse schema: {}", e)))
137 };
138 let parse_time = parse_start.elapsed();
139 println!(" š Schema parsing: {:?}", parse_time);
140
141 let eval_start = Instant::now();
143 let mut eval = JSONEval::with_parsed_schema(
144 parsed_schema.clone(), Some("{}"),
146 Some(&data_str)
147 ).unwrap_or_else(|e| panic!("failed to create JSONEval: {}", e));
148
149 eval.evaluate(&data_str, Some("{}"))
150 .unwrap_or_else(|e| panic!("evaluation failed: {}", e));
151
152 let evaluated_schema = eval.get_evaluated_schema(false);
153 let eval_time = eval_start.elapsed();
154
155 println!(" ā” Eval: {:?}", eval_time);
156 println!(" ā±ļø Total: {:?}\n", parse_time + eval_time);
157
158 if show_timing {
160 json_eval_rs::print_timing_summary();
161 }
162
163 total_parse_time += parse_time;
164 total_eval_time += eval_time;
165 successful_scenarios += 1;
166
167 let evaluated_path = samples_dir.join(format!("{}-evaluated-schema.json", scenario.name));
169 let parsed_path = samples_dir.join(format!("{}-parsed-schema.json", scenario.name));
170
171 fs::write(&evaluated_path, common::pretty_json(&evaluated_schema))
172 .unwrap_or_else(|e| panic!("failed to write {}: {}", evaluated_path.display(), e));
173
174 let mut metadata_obj = Map::new();
175 metadata_obj.insert("dependencies".to_string(), serde_json::to_value(&*eval.dependencies).unwrap());
176 metadata_obj.insert("evaluations".to_string(), serde_json::to_value(&*eval.evaluations).unwrap());
177 metadata_obj.insert("sorted_evaluations".to_string(), serde_json::to_value(&*eval.sorted_evaluations).unwrap());
178
179 fs::write(&parsed_path, common::pretty_json(&Value::Object(metadata_obj)))
180 .unwrap_or_else(|e| panic!("failed to write {}: {}", parsed_path.display(), e));
181
182 println!("ā
Results saved:");
183 println!(" - {}", evaluated_path.display());
184 println!(" - {}\n", parsed_path.display());
185
186 if enable_comparison {
188 if let Some(comp_path) = &scenario.comparison_path {
189 if common::compare_with_expected(&evaluated_schema, comp_path).is_err() {
190 comparison_failures += 1;
191 }
192 println!();
193 }
194 }
195 }
196
197 println!("{}", "=".repeat(50));
199 println!("š Summary");
200 println!("{}", "=".repeat(50));
201 println!("Total scenarios run: {}", successful_scenarios);
202 println!("Total parsing time: {:?}", total_parse_time);
203 println!("Total evaluation time: {:?}", total_eval_time);
204 println!("Total time: {:?}", total_parse_time + total_eval_time);
205
206 if successful_scenarios > 1 {
207 println!("\nAverage per scenario:");
208 println!(" Parsing: {:?}", total_parse_time / successful_scenarios as u32);
209 println!(" Evaluation: {:?}", total_eval_time / successful_scenarios as u32);
210 }
211
212 if enable_comparison {
213 println!("\nComparison failures: {}", comparison_failures);
214 }
215
216 println!("\nā
All scenarios completed!\n");
217}