1use json_eval_rs::{ParsedSchema, ParsedSchemaCache, JSONEval, PARSED_SCHEMA_CACHE};
11use std::sync::Arc;
12use std::time::Instant;
13
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 println!("๐ ParsedSchemaCache Demo\n");
16
17 demo_local_cache()?;
19
20 println!("\n{}\n", "=".repeat(60));
21
22 demo_global_cache()?;
24
25 println!("\n{}\n", "=".repeat(60));
26
27 demo_performance_comparison()?;
29
30 println!("\n{}\n", "=".repeat(60));
31
32 demo_lazy_insertion()?;
34
35 Ok(())
36}
37
38fn demo_local_cache() -> Result<(), Box<dyn std::error::Error>> {
39 println!("๐ฆ Example 1: Local Cache Instance");
40 println!("Creating a dedicated cache for this application...\n");
41
42 let cache = ParsedSchemaCache::new();
43
44 let schema_json = r#"{
46 "$params": {
47 "rate": { "type": "number" }
48 },
49 "result": {
50 "type": "number",
51 "title": "Calculated Result",
52 "$evaluation": {
53 "logic": { "*": [{"var": "$rate"}, 100] }
54 }
55 }
56 }"#;
57
58 println!("๐ Parsing schema and caching with key 'calculation-v1'...");
60 let parsed = ParsedSchema::parse(schema_json)?;
61 cache.insert("calculation-v1".to_string(), Arc::new(parsed));
62
63 println!("โ
Schema cached successfully");
64 println!(" Cache size: {} entries", cache.len());
65 println!(" Keys: {:?}\n", cache.keys());
66
67 println!("๐ Retrieving cached schema...");
69 if let Some(cached_schema) = cache.get("calculation-v1") {
70 println!("โ
Retrieved from cache");
71
72 let mut eval = JSONEval::with_parsed_schema(cached_schema, Some(r#"{"rate": 1.5}"#), None)?;
74 eval.evaluate("{}", None)?;
75
76 let evaluated = eval.get_evaluated_schema(false);
77 let result = evaluated.pointer("/result")
78 .and_then(|v| v.as_f64())
79 .unwrap_or(0.0);
80 println!(" Evaluation result: {}\n", result);
81 }
82
83 let stats = cache.stats();
85 println!("๐ Cache Statistics: {}", stats);
86
87 println!("\n๐๏ธ Removing 'calculation-v1' from cache...");
89 cache.remove("calculation-v1");
90 println!(" Cache size after removal: {}", cache.len());
91
92 Ok(())
93}
94
95fn demo_global_cache() -> Result<(), Box<dyn std::error::Error>> {
96 println!("๐ Example 2: Global Cache Instance");
97 println!("Using the built-in PARSED_SCHEMA_CACHE...\n");
98
99 let schema_json = r#"{
100 "$params": {
101 "x": { "type": "number" },
102 "y": { "type": "number" }
103 },
104 "sum": {
105 "type": "number",
106 "$evaluation": { "+": [{"var": "$x"}, {"var": "$y"}] }
107 }
108 }"#;
109
110 println!("๐ Caching schema globally with key 'math-operations'...");
112 let parsed = ParsedSchema::parse(schema_json)?;
113 PARSED_SCHEMA_CACHE.insert("math-operations".to_string(), Arc::new(parsed));
114
115 println!("โ
Schema cached globally");
116 println!(" Global cache size: {}\n", PARSED_SCHEMA_CACHE.len());
117
118 simulate_another_function()?;
120
121 println!("\n๐งน Clearing global cache...");
123 PARSED_SCHEMA_CACHE.clear();
124 println!(" Global cache size: {}", PARSED_SCHEMA_CACHE.len());
125
126 Ok(())
127}
128
129fn simulate_another_function() -> Result<(), Box<dyn std::error::Error>> {
130 println!("๐ In another function, accessing global cache...");
131
132 if let Some(cached) = PARSED_SCHEMA_CACHE.get("math-operations") {
133 println!("โ
Retrieved schema from global cache");
134
135 let mut eval = JSONEval::with_parsed_schema(cached, Some(r#"{"x": 10, "y": 20}"#), None)?;
136 eval.evaluate("{}", None)?;
137
138 let evaluated = eval.get_evaluated_schema(false);
139 let sum = evaluated.pointer("/sum")
140 .and_then(|v| v.as_f64())
141 .unwrap_or(0.0);
142 println!(" Result: {}", sum);
143 }
144
145 Ok(())
146}
147
148fn demo_performance_comparison() -> Result<(), Box<dyn std::error::Error>> {
149 println!("โก Example 3: Performance Comparison");
150 println!("Comparing cached vs non-cached schema usage...\n");
151
152 let schema_json = r#"{
153 "$params": {
154 "value": { "type": "number" }
155 },
156 "doubled": {
157 "type": "number",
158 "$evaluation": { "*": [{"var": "$value"}, 2] }
159 },
160 "tripled": {
161 "type": "number",
162 "$evaluation": { "*": [{"var": "$value"}, 3] }
163 }
164 }"#;
165
166 let iterations = 100;
167
168 println!("๐ Without cache (parse + evaluate each time):");
170 let start = Instant::now();
171 for i in 0..iterations {
172 let context = format!(r#"{{"value": {}}}"#, i);
173 let mut eval = JSONEval::new(schema_json, Some(&context), None)?;
174 eval.evaluate("{}", None)?;
175 }
176 let without_cache = start.elapsed();
177 println!(" Time: {:?}", without_cache);
178 println!(" Avg per iteration: {:?}\n", without_cache / iterations);
179
180 println!("๐ With cache (parse once, reuse for all evaluations):");
182 let cache = ParsedSchemaCache::new();
183
184 let parse_start = Instant::now();
186 let parsed = ParsedSchema::parse(schema_json)?;
187 cache.insert("perf-test".to_string(), Arc::new(parsed));
188 let parse_time = parse_start.elapsed();
189
190 let eval_start = Instant::now();
192 for i in 0..iterations {
193 if let Some(cached) = cache.get("perf-test") {
194 let context = format!(r#"{{"value": {}}}"#, i);
195 let mut eval = JSONEval::with_parsed_schema(cached.clone(), Some(&context), None)?;
196 eval.evaluate("{}", None)?;
197 }
198 }
199 let eval_time = eval_start.elapsed();
200 let with_cache = parse_time + eval_time;
201
202 println!(" Parse time: {:?}", parse_time);
203 println!(" Eval time: {:?}", eval_time);
204 println!(" Total time: {:?}", with_cache);
205 println!(" Avg per iteration: {:?}\n", eval_time / iterations);
206
207 let speedup = without_cache.as_secs_f64() / with_cache.as_secs_f64();
208 println!("๐ Speedup: {:.2}x faster", speedup);
209
210 Ok(())
211}
212
213fn demo_lazy_insertion() -> Result<(), Box<dyn std::error::Error>> {
214 println!("๐ Example 4: Lazy Insertion with get_or_insert_with");
215 println!("Parse only if not already cached...\n");
216
217 let cache = ParsedSchemaCache::new();
218
219 let schema_json = r#"{
220 "$params": {
221 "name": { "type": "string" }
222 },
223 "greeting": {
224 "type": "string",
225 "$evaluation": {
226 "cat": ["Hello, ", {"var": "$name"}, "!"]
227 }
228 }
229 }"#;
230
231 println!("๐ First access (will parse)...");
233 let start = Instant::now();
234 let schema1 = cache.get_or_insert_with("greeting-schema", || {
235 println!(" โ๏ธ Parsing schema...");
236 Arc::new(ParsedSchema::parse(schema_json).unwrap())
237 });
238 println!(" Time: {:?}\n", start.elapsed());
239
240 println!("๐ Second access (will use cache)...");
242 let start = Instant::now();
243 let schema2 = cache.get_or_insert_with("greeting-schema", || {
244 println!(" โ๏ธ Parsing schema...");
245 Arc::new(ParsedSchema::parse(schema_json).unwrap())
246 });
247 println!(" Time: {:?}", start.elapsed());
248
249 println!("\nโ
Both accesses returned the same cached instance");
251 println!(" Same pointer: {}", Arc::ptr_eq(&schema1, &schema2));
252
253 Ok(())
254}