Skip to main content

conjure_cp_core/parse/
example_models.rs

1// example_models with get_example_model function
2
3use std::path::PathBuf;
4
5use project_root::get_project_root;
6use walkdir::WalkDir;
7
8use crate::Model;
9use crate::parse::model_from_json;
10
11/// Searches recursively in `test-suite/tests/exhaustive` for an `.essence` file matching the given
12/// filename, then uses conjure to process it into astjson, and returns the parsed model.
13///
14/// # Arguments
15///
16/// * `filename` - A string slice that holds filename without extension
17///
18/// # Returns
19///
20/// Function returns a `Result<Value, anyhow::Error>`, where `Value` is the parsed model.
21pub fn get_example_model(filename: &str) -> Result<Model, anyhow::Error> {
22    // define relative path -> exhaustive tests dir
23    let base_dir = get_project_root()?.join("test-suite/tests/exhaustive");
24    let mut essence_path = PathBuf::new();
25
26    // walk through directory tree recursively starting at base
27    for entry in WalkDir::new(base_dir)
28        .sort_by_file_name()
29        .into_iter()
30        .filter_map(|e| e.ok())
31    {
32        let path = entry.path();
33        if path.is_file()
34            && path
35                .extension()
36                .is_some_and(|e| e == "essence" || e == "eprime")
37            && path.file_stem() == Some(std::ffi::OsStr::new(filename))
38        {
39            essence_path = path.to_path_buf();
40            break;
41        }
42    }
43
44    //println!("PATH TO FILE: {}", essence_path.display());
45
46    // return error if file not found
47    if essence_path.as_os_str().is_empty() {
48        return Err(anyhow::Error::new(std::io::Error::new(
49            std::io::ErrorKind::NotFound,
50            "ERROR: File not found in any subdirectory",
51        )));
52    }
53
54    // let path = PathBuf::from(format!("../tests/exhaustive/basic/comprehension{}.essence", filename));
55    let mut cmd = std::process::Command::new("conjure");
56    let output = cmd
57        .arg("pretty")
58        .arg("--output-format=astjson")
59        .arg(essence_path)
60        .output()?;
61
62    // convert Conjure's stdout from bytes to string
63    let astjson = String::from_utf8(output.stdout)?;
64
65    //println!("ASTJSON: {}", astjson);
66
67    // parse AST JSON from desired Model format
68    let generated_mdl = model_from_json(&astjson, Default::default())?;
69
70    Ok(generated_mdl)
71}
72
73/// Searches for an `.essence` file at the given filepath,
74/// then uses conjure to process it into astjson, and returns the parsed model.
75///
76/// # Arguments
77///
78/// * `filepath` - A string slice that holds the full file path
79///
80/// # Returns
81///
82/// Function returns a `Result<Value, anyhow::Error>`, where `Value` is the parsed model
83pub fn get_example_model_by_path(filepath: &str) -> Result<Model, anyhow::Error> {
84    let essence_path = PathBuf::from(filepath);
85
86    // return error if file not found
87    if essence_path.as_os_str().is_empty() {
88        return Err(anyhow::Error::new(std::io::Error::new(
89            std::io::ErrorKind::NotFound,
90            "ERROR: File not found in any subdirectory",
91        )));
92    }
93
94    // println!("PATH TO FILE: {}", essence_path.display());
95
96    // Command execution using 'conjure' CLI tool with provided path
97    let mut cmd = std::process::Command::new("conjure");
98    let output = cmd
99        .arg("pretty")
100        .arg("--output-format=astjson")
101        .arg(&essence_path)
102        .output()?;
103
104    // convert Conjure's stdout from bytes to string
105    let astjson = String::from_utf8(output.stdout)?;
106
107    // println!("ASTJSON: {}", astjson);
108
109    // parse AST JSON into the desired Model format
110    let generated_model = model_from_json(&astjson, Default::default())?;
111
112    Ok(generated_model)
113}