basic_msgpack/
basic_msgpack.rs

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