Skip to main content

wpl/eval/builtins/
registry.rs

1use once_cell::sync::Lazy;
2use smol_str::SmolStr;
3use std::collections::HashMap;
4use std::sync::{Mutex, MutexGuard};
5
6use super::PipeHold;
7
8pub type PlgPipeUnitBuilder = fn() -> PipeHold;
9
10#[derive(Default)]
11struct PlgPipeUnitRegistry {
12    builders: HashMap<SmolStr, PlgPipeUnitBuilder>,
13}
14
15impl PlgPipeUnitRegistry {
16    fn register(&mut self, name: &str, builder: PlgPipeUnitBuilder) {
17        self.builders
18            .insert(SmolStr::from(name.to_ascii_uppercase()), builder);
19    }
20
21    fn create(&self, name: &str) -> Option<PipeHold> {
22        self.builders
23            .get(&SmolStr::from(name.to_ascii_uppercase()))
24            .map(|builder| (builder)())
25    }
26
27    fn list(&self) -> Vec<SmolStr> {
28        self.builders.keys().cloned().collect()
29    }
30}
31
32static PIPE_UNIT_REGISTRY: Lazy<Mutex<PlgPipeUnitRegistry>> =
33    Lazy::new(|| Mutex::new(PlgPipeUnitRegistry::default()));
34
35fn registry() -> MutexGuard<'static, PlgPipeUnitRegistry> {
36    PIPE_UNIT_REGISTRY
37        .lock()
38        .expect("plg_pipe unit registry poisoned")
39}
40
41pub fn register_pipe_unit(name: &str, builder: PlgPipeUnitBuilder) {
42    registry().register(name, builder);
43}
44
45pub fn create_pipe_unit(name: &str) -> Option<PipeHold> {
46    registry().create(name)
47}
48
49pub fn list_pipe_units() -> Vec<SmolStr> {
50    registry().list()
51}
52
53#[macro_export]
54macro_rules! register_wpl_pipe {
55    ($name:expr, $builder:expr) => {
56        $crate::eval::builtins::registry::register_pipe_unit(
57            $name,
58            $builder as $crate::eval::builtins::registry::PlgPipeUnitBuilder,
59        );
60    };
61
62    ($($name:expr => $builder:expr),* $(,)?) => {
63        $crate::eval::builtins::registry::register_pipe_unit_batch(vec![
64            $(
65                $name => $builder as $crate::eval::builtins::registry::PlgPipeUnitBuilder
66            ),*
67        ]);
68    };
69}
70
71pub fn register_wpl_pipe_batch<I>(items: I)
72where
73    I: IntoIterator<Item = (&'static str, PlgPipeUnitBuilder)>,
74{
75    let mut guard = registry();
76    for (name, builder) in items {
77        guard.register(name, builder);
78    }
79}