formualizer_eval/
function_registry.rs1use crate::function::Function;
2use dashmap::DashMap;
3use once_cell::sync::Lazy;
4use std::sync::Arc;
5
6static REG: Lazy<DashMap<(String, String), Arc<dyn Function>>> = Lazy::new(DashMap::new);
8
9static ALIASES: Lazy<DashMap<(String, String), (String, String)>> = Lazy::new(DashMap::new);
11
12#[inline]
13fn norm<S: AsRef<str>>(s: S) -> String {
14 s.as_ref().to_uppercase()
15}
16
17pub fn register_function(f: Arc<dyn Function>) {
18 let ns = norm(f.namespace());
19 let name = norm(f.name());
20 let key = (ns.clone(), name.clone());
21 REG.insert(key.clone(), Arc::clone(&f));
23 for &alias in f.aliases() {
25 if alias.eq_ignore_ascii_case(&name) {
26 continue;
27 }
28 let akey = (ns.clone(), norm(alias));
29 ALIASES.insert(akey, key.clone());
30 }
31}
32
33const EXCEL_PREFIXES: &[&str] = &["_XLFN.", "_XLL.", "_XLWS."];
35
36pub fn get(ns: &str, name: &str) -> Option<Arc<dyn Function>> {
37 let key = (norm(ns), norm(name));
38
39 if let Some(v) = REG.get(&key) {
41 return Some(Arc::clone(v.value()));
42 }
43
44 if let Some(canon) = ALIASES.get(&key) {
46 if let Some(v) = REG.get(canon.value()) {
47 return Some(Arc::clone(v.value()));
48 }
49 }
50
51 let normalized_name = norm(name);
53 for prefix in EXCEL_PREFIXES {
54 if let Some(stripped) = normalized_name.strip_prefix(prefix) {
55 let stripped_key = (norm(ns), stripped.to_string());
56
57 if let Some(v) = REG.get(&stripped_key) {
58 ALIASES.insert(key, stripped_key);
60 return Some(Arc::clone(v.value()));
61 }
62 }
63 }
64
65 None
66}
67
68pub fn register_alias(ns: &str, alias: &str, target_ns: &str, target_name: &str) {
70 let akey = (norm(ns), norm(alias));
71 let tkey = (norm(target_ns), norm(target_name));
72 ALIASES.insert(akey, tkey);
73}