clashlib/stub/
stub_config.rs

1use std::fs;
2
3use anyhow::{Context, Result};
4use include_dir::include_dir;
5use tera::Tera;
6
7use super::Language;
8
9const HARDCODED_EMBEDDED_TEMPLATE_DIR: include_dir::Dir<'static> =
10    include_dir!("$CARGO_MANIFEST_DIR/config/stub_templates");
11
12#[derive(Clone)]
13pub struct StubConfig {
14    pub(super) language: Language,
15    pub(super) tera: Tera,
16}
17
18impl StubConfig {
19    pub fn read_from_dir(dir: std::path::PathBuf) -> Result<Self> {
20        let toml_file = dir.join("stub_config.toml");
21        let toml_str = fs::read_to_string(toml_file)?;
22        let language: Language = toml::from_str(&toml_str)?;
23        let jinja_glob = dir.join("*.jinja");
24        let tera = Tera::new(jinja_glob.to_str().expect("language directory path should be valid utf8"))
25            .context("Failed to create Tera instance")?;
26        Ok(Self { language, tera })
27    }
28
29    pub(super) fn read_from_embedded(lang_name: &str) -> Result<Self> {
30        // If you just created a new template for a language and you get:
31        // Error: No stub generator found for 'language'
32        // you may need to recompile the binaries to update: `cargo build`
33        let embedded_config_dir = HARDCODED_EMBEDDED_TEMPLATE_DIR
34            .get_dir(lang_name)
35            .context(format!("No stub generator found for '{lang_name}'"))?;
36        let toml_file = embedded_config_dir
37            .get_file(format!("{lang_name}/stub_config.toml"))
38            .expect("Embedded stub generators should have stub_config.toml");
39        let toml_str = toml_file
40            .contents_utf8()
41            .expect("Embedded stub_config.toml contents should be valid utf8");
42        let language: Language = toml::from_str(toml_str)?;
43        let templates = embedded_config_dir
44            .find("*.jinja")
45            .expect("*.jinja should be a valid glob pattern")
46            .filter_map(|dir_entry| {
47                let file = dir_entry.as_file()?;
48                Some((file.path().file_name()?.to_str()?, file.contents_utf8()?))
49            });
50
51        let mut tera = Tera::default();
52
53        tera.add_raw_templates(templates)
54            .expect("Adding embedded templates to tera should not fail");
55        Ok(Self { language, tera })
56    }
57}