1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#[macro_use]
extern crate log;
extern crate toml;
extern crate modelica_parser;
pub mod modelica_model;
pub mod transpile_scheme;
pub mod transpile_js;
use std::path::Path;
use std::fs;
use std::io::Read;
use std::fs::File;
#[derive(Debug, PartialEq)]
pub struct ModelMetadata {
pub name_en: String,
pub description_en: Option<String>,
pub vars: Vec<ModelVar>,
}
#[derive(Debug, PartialEq)]
pub enum ModelVarType {
Independent,
Dependent,
Constant,
Time,
State,
Parameter,
}
#[derive(Debug, PartialEq)]
pub struct ModelVar {
pub slug: String,
pub name_en: Option<String>,
pub vtype: ModelVarType,
pub latex: Option<String>,
pub units_si: Option<String>,
}
#[derive(Debug, PartialEq)]
pub struct ModelEntry {
pub ast: modelica_parser::ast::ModelicaModel,
pub metadata: ModelMetadata,
pub markdown: String,
}
pub fn parse_metadata(raw: String) -> Result<ModelMetadata,String> {
let root = toml::Parser::new(&raw).parse().unwrap();
let model = root.get("model")
.expect("missing 'model' section")
.as_table().unwrap();
let variables = root.get("variables")
.expect("missing 'variables' section")
.as_table().unwrap();
let mut vars = vec![];
for (slug, info) in variables {
let info = info.as_table().unwrap();
let vtype = match info.get("type").unwrap().as_str().unwrap() {
"independent" => ModelVarType::Independent,
"dependent" => ModelVarType::Dependent,
"constant" => ModelVarType::Constant,
"time" => ModelVarType::Time,
"state" => ModelVarType::State,
"parameter" => ModelVarType::Parameter,
other => return Err(format!("Unknown variable type: {}", other)),
};
vars.push(ModelVar {
slug: slug.to_string(),
name_en: info.get("name-en").map(|x| x.as_str().unwrap().to_string()),
vtype: vtype,
latex: info.get("latex").map(|x| x.as_str().unwrap().to_string()),
units_si: info.get("units-si").map(|x| x.as_str().unwrap().to_string()),
});
}
Ok(ModelMetadata {
name_en: model.get("name-en").unwrap().as_str().unwrap().to_string(),
description_en: model.get("description-en").map(|x| x.as_str().unwrap().to_string()),
vars: vars,
})
}
pub fn load_model_entry(p: &Path) -> Result<ModelEntry,String> {
debug!("Attempting to load model from: {:?}", p);
let ast = {
let mut s = String::new();
try!(File::open(p.join("model.modelica")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string()));
try!(modelica_parser::parser::parse_model(&s).map_err(|e| format!("{:?}", e)))
};
let metadata = {
let mut s = String::new();
try!(File::open(p.join("metadata.toml")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string()));
parse_metadata(s).unwrap()
};
let markdown = {
let mut s = String::new();
try!(File::open(p.join("page.md")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string()));
s
};
Ok(ModelEntry {
ast: ast,
metadata: metadata,
markdown: markdown,
})
}
pub fn search_models(p: &Path) -> Vec<String> {
if fs::metadata(p).unwrap().is_dir() {
fs::read_dir(p).unwrap()
.map(|x| x.unwrap())
.filter(|x| x.metadata().unwrap().is_dir())
.filter(|x| x.path().join("model.modelica").exists())
.map(|x| x.path().to_string_lossy().to_string())
.collect()
} else {
vec![]
}
}
|