summaryrefslogtreecommitdiffstats
path: root/src/conf.rs
blob: f8c7bdbdcd614135d4246f8ab00e63c6e768dc98 (plain) (blame)
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
use serde_derive::Deserialize;
use std::path::{Path, PathBuf};
use toml::de;

type Error = std::io::Error;
use std::io::ErrorKind;

use crate::backends::{Backend, ClangBackend, ClangCBackend, PythonBackend};

#[derive(Debug, Deserialize)]
pub struct Conf {
    #[serde(skip)]
    path: Option<PathBuf>,

    #[serde(default)]
    python: PythonBackend,

    #[serde(default)]
    clang: ClangBackend,

    #[serde(default)]
    clang_c: ClangCBackend,
}

impl Conf {
    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)),
            "c" => Some(Box::new(&self.clang_c)),
            _ => None,
        }
    }
}

pub fn get_conf() -> 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))
}