1use serde::{Deserialize, Serialize};
38use std::collections::HashMap;
39
40#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79#[serde(rename_all = "camelCase")]
80pub struct AstPattern {
81 pub subject: AstSubject,
83
84 pub elements: Vec<AstPattern>,
86}
87
88#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct AstSubject {
114 pub identity: String,
116
117 pub labels: Vec<String>,
119
120 pub properties: HashMap<String, serde_json::Value>,
126}
127
128impl AstPattern {
129 pub fn empty() -> Self {
133 AstPattern {
134 subject: AstSubject {
135 identity: String::new(),
136 labels: Vec::new(),
137 properties: HashMap::new(),
138 },
139 elements: Vec::new(),
140 }
141 }
142}
143
144use pattern_core::{Pattern, Subject, Value};
146
147impl AstPattern {
148 pub fn from_pattern(pattern: &Pattern<Subject>) -> Self {
170 let subject = pattern.value();
171
172 AstPattern {
173 subject: AstSubject {
174 identity: subject.identity.0.clone(),
175 labels: subject.labels.iter().cloned().collect(),
176 properties: subject
177 .properties
178 .iter()
179 .map(|(k, v)| (k.clone(), value_to_json(v)))
180 .collect(),
181 },
182 elements: pattern
183 .elements()
184 .iter()
185 .map(AstPattern::from_pattern)
186 .collect(),
187 }
188 }
189}
190
191fn value_to_json(value: &Value) -> serde_json::Value {
205 match value {
206 Value::VInteger(i) => serde_json::Value::Number((*i).into()),
208
209 Value::VDecimal(d) => {
210 serde_json::Number::from_f64(*d)
212 .map(serde_json::Value::Number)
213 .unwrap_or_else(|| serde_json::Value::Null)
214 }
215
216 Value::VBoolean(b) => serde_json::Value::Bool(*b),
217
218 Value::VString(s) => serde_json::Value::String(s.clone()),
219
220 Value::VArray(arr) => serde_json::Value::Array(arr.iter().map(value_to_json).collect()),
221
222 Value::VMap(map) => serde_json::Value::Object(
223 map.iter()
224 .map(|(k, v)| (k.clone(), value_to_json(v)))
225 .collect(),
226 ),
227
228 Value::VSymbol(sym) => serde_json::json!({
231 "type": "symbol",
232 "value": sym.clone()
233 }),
234
235 Value::VRange(range) => serde_json::json!({
236 "type": "range",
237 "lower": range.lower,
238 "upper": range.upper
239 }),
240
241 Value::VMeasurement { unit, value } => serde_json::json!({
242 "type": "measurement",
243 "unit": unit,
244 "value": value
245 }),
246
247 Value::VTaggedString { tag, content } => serde_json::json!({
248 "type": "tagged",
249 "tag": tag,
250 "content": content
251 }),
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258 use pattern_core::{Pattern, Subject, Symbol};
259 use std::collections::{HashMap, HashSet};
260
261 #[test]
262 fn test_empty_pattern() {
263 let pattern = AstPattern::empty();
264 assert_eq!(pattern.subject.identity, "");
265 assert_eq!(pattern.subject.labels.len(), 0);
266 assert_eq!(pattern.subject.properties.len(), 0);
267 assert_eq!(pattern.elements.len(), 0);
268 }
269
270 #[test]
271 fn test_json_serialization() {
272 let pattern = AstPattern {
273 subject: AstSubject {
274 identity: "alice".to_string(),
275 labels: vec!["Person".to_string()],
276 properties: {
277 let mut props = HashMap::new();
278 props.insert("name".to_string(), serde_json::json!("Alice"));
279 props
280 },
281 },
282 elements: vec![],
283 };
284
285 let json = serde_json::to_string(&pattern).unwrap();
287 assert!(json.contains("alice"));
288 assert!(json.contains("Person"));
289
290 let deserialized: AstPattern = serde_json::from_str(&json).unwrap();
292 assert_eq!(deserialized, pattern);
293 }
294
295 #[test]
296 fn test_nested_patterns() {
297 let child1 = AstPattern {
298 subject: AstSubject {
299 identity: "child1".to_string(),
300 labels: vec![],
301 properties: HashMap::new(),
302 },
303 elements: vec![],
304 };
305
306 let child2 = AstPattern {
307 subject: AstSubject {
308 identity: "child2".to_string(),
309 labels: vec![],
310 properties: HashMap::new(),
311 },
312 elements: vec![],
313 };
314
315 let parent = AstPattern {
316 subject: AstSubject {
317 identity: "parent".to_string(),
318 labels: vec![],
319 properties: HashMap::new(),
320 },
321 elements: vec![child1, child2],
322 };
323
324 assert_eq!(parent.elements.len(), 2);
325 assert_eq!(parent.elements[0].subject.identity, "child1");
326 assert_eq!(parent.elements[1].subject.identity, "child2");
327
328 let json = serde_json::to_string(&parent).unwrap();
330 let deserialized: AstPattern = serde_json::from_str(&json).unwrap();
331 assert_eq!(deserialized.elements.len(), 2);
332 }
333
334 #[test]
335 fn test_from_pattern_simple() {
336 let subject = Subject {
337 identity: Symbol("alice".to_string()),
338 labels: {
339 let mut labels = HashSet::new();
340 labels.insert("Person".to_string());
341 labels
342 },
343 properties: HashMap::new(),
344 };
345 let pattern = Pattern::point(subject);
346
347 let ast = AstPattern::from_pattern(&pattern);
348
349 assert_eq!(ast.subject.identity, "alice");
350 assert_eq!(ast.subject.labels, vec!["Person"]);
351 assert_eq!(ast.elements.len(), 0);
352 }
353
354 #[test]
355 fn test_from_pattern_with_properties() {
356 let subject = Subject {
357 identity: Symbol("alice".to_string()),
358 labels: HashSet::new(),
359 properties: {
360 let mut props = HashMap::new();
361 props.insert("name".to_string(), Value::VString("Alice".to_string()));
362 props.insert("age".to_string(), Value::VInteger(30));
363 props
364 },
365 };
366 let pattern = Pattern::point(subject);
367
368 let ast = AstPattern::from_pattern(&pattern);
369
370 assert_eq!(ast.subject.identity, "alice");
371 assert_eq!(ast.subject.properties.len(), 2);
372
373 assert_eq!(ast.subject.properties.get("name").unwrap(), "Alice");
375
376 let age_value = ast.subject.properties.get("age").unwrap();
378 assert_eq!(age_value, 30); }
380
381 #[test]
382 fn test_value_serialization_simple_types() {
383 let v = value_to_json(&Value::VInteger(42));
385 assert_eq!(v, serde_json::json!(42));
386 assert!(v.is_number());
387
388 let v = value_to_json(&Value::VDecimal(3.14));
390 assert_eq!(v, serde_json::json!(3.14));
391 assert!(v.is_number());
392
393 let v = value_to_json(&Value::VBoolean(true));
395 assert_eq!(v, serde_json::Value::Bool(true));
396
397 let v = value_to_json(&Value::VString("hello".to_string()));
399 assert_eq!(v, serde_json::Value::String("hello".to_string()));
400
401 let v = value_to_json(&Value::VArray(vec![Value::VInteger(1), Value::VInteger(2)]));
403 assert!(v.is_array());
404 assert_eq!(v.as_array().unwrap().len(), 2);
405 assert_eq!(v.as_array().unwrap()[0], serde_json::json!(1));
406 assert_eq!(v.as_array().unwrap()[1], serde_json::json!(2));
407 }
408
409 #[test]
410 fn test_value_serialization_tagged_types() {
411 let v = value_to_json(&Value::VSymbol("user123".to_string()));
413 assert_eq!(v["type"], "symbol");
414 assert_eq!(v["value"], "user123");
415
416 let v = value_to_json(&Value::VRange(pattern_core::RangeValue {
418 lower: Some(1.0),
419 upper: Some(10.0),
420 }));
421 assert_eq!(v["type"], "range");
422 assert_eq!(v["lower"], 1.0);
423 assert_eq!(v["upper"], 10.0);
424
425 let v = value_to_json(&Value::VMeasurement {
427 unit: "cm".to_string(),
428 value: 168.0,
429 });
430 assert_eq!(v["type"], "measurement");
431 assert_eq!(v["value"], 168.0);
432 assert_eq!(v["unit"], "cm");
433
434 let v = value_to_json(&Value::VTaggedString {
436 tag: "date".to_string(),
437 content: "2024-01-09".to_string(),
438 });
439 assert_eq!(v["type"], "tagged");
440 assert_eq!(v["tag"], "date");
441 assert_eq!(v["content"], "2024-01-09");
442 }
443
444 #[test]
445 fn test_value_serialization_map() {
446 let mut map = HashMap::new();
447 map.insert("key1".to_string(), Value::VString("value1".to_string()));
448 map.insert("key2".to_string(), Value::VInteger(42));
449
450 let v = value_to_json(&Value::VMap(map));
451
452 assert!(v.is_object());
453 assert_eq!(v["key1"], "value1");
454 assert_eq!(v["key2"], 42);
456 }
457}