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