darklua_core/rules/
runtime_identifier.rs

1use blake3;
2use hex;
3use std::collections::HashMap;
4use strfmt::strfmt;
5
6pub struct RuntimeIdentifierBuilder {
7    format: String,
8    hash: String,
9    keywords: Option<Vec<String>>,
10}
11
12impl RuntimeIdentifierBuilder {
13    pub fn new(
14        format: impl Into<String>,
15        identifier: &[u8],
16        keywords: Option<Vec<String>>,
17    ) -> Result<Self, String> {
18        let format: String = format.into();
19        if !format.as_str().contains("{name}") {
20            return Err("`name` field is required for runtime identifier".to_string());
21        }
22        let hash = blake3::hash(identifier);
23        Ok(Self {
24            format,
25            hash: hex::encode(&hash.as_bytes()[..8]),
26            keywords,
27        })
28    }
29
30    pub fn build(&self, name: &str) -> Result<String, String> {
31        let mut vars = HashMap::new();
32        vars.insert("name".to_owned(), name);
33        vars.insert("hash".to_owned(), self.hash.as_str());
34
35        let name = strfmt(&self.format, &vars).map_err(|err| err.to_string())?;
36
37        if let Some(keywords) = &self.keywords {
38            if keywords.contains(&name) {
39                Err(format!("Runtime variable `{name}` cannot be set because it contains a reserved keyword."))?;
40            }
41        }
42
43        Ok(name)
44    }
45}