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
|
use serde_derive::Deserialize;
use std::path::{ PathBuf, Path };
use toml::de;
use log::{ error };
type Error = std::io::Error;
use std::io::ErrorKind;
use crate::backends::{ Backend, PythonBackend, ClangBackend };
#[derive(Debug, Deserialize, Default)]
pub struct Conf {
#[serde(skip)]
path: Option<PathBuf>,
#[serde(default)]
python: PythonBackend,
#[serde(default)]
clang: ClangBackend
}
impl Conf {
pub fn get_template(&self, fname: &Path) -> &str {
self.get_backend(fname)
.and_then(|backend| backend.get_template())
.unwrap_or("")
}
pub fn get_backend(&self, fname: &Path) -> Option<Box<&dyn Backend>> {
let ext = fname.extension()
.and_then(|ext| ext.to_str())
.unwrap_or("");
match ext {
"py" => Some(Box::new(&self.python)),
"cc" | "cpp" | "cxx" => Some(Box::new(&self.clang)),
_ => None
}
}
}
pub fn get_conf() -> Conf {
match get_conf_maybe() {
Ok(c) => c,
Err(e) => {
match e.kind() {
ErrorKind::InvalidData => error!("parse: {}", e),
_ => error!("{}", e)
};
Default::default()
}
}
}
pub fn get_conf_maybe() -> Result<Conf, Error> {
let mut current = std::env::current_dir()?;
let path = loop {
let candidate = current.join(".evr");
if candidate.exists() {
break candidate;
}
if !current.pop() {
return Err(Error::new(ErrorKind::NotFound, "Not a evr subtree"));
}
};
let raw_buf = std::fs::read_to_string(path.as_path())?;
let buf_result: Result<Conf, de::Error> = de::from_str(&raw_buf);
buf_result
.map(|mut buf| {
buf.path = Some(path.clone());
buf
})
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
}
|