liquid_core/parser/
registry.rs

1use std::collections::hash_map;
2
3type MapImpl<K, V> = hash_map::HashMap<K, V>;
4type KeysImpl<'a, K, V> = hash_map::Keys<'a, K, V>;
5
6/// Liquid language plugin registry.
7pub struct PluginRegistry<P> {
8    plugins: MapImpl<String, P>,
9}
10
11impl<P> PluginRegistry<P> {
12    /// Create a new registry.
13    pub fn new() -> Self {
14        Self {
15            plugins: Default::default(),
16        }
17    }
18
19    /// Register a plugin
20    ///
21    /// Generally this is used when setting up the program.
22    ///
23    /// Returns whether this overrode an existing plugin.
24    pub fn register(&mut self, name: String, plugin: P) -> bool {
25        let old = self.plugins.insert(name, plugin);
26        old.is_some()
27    }
28
29    /// Look up an existing plugin.
30    ///
31    /// Generally this is used for running plugins.
32    pub fn get(&self, name: &str) -> Option<&P> {
33        self.plugins.get(name)
34    }
35
36    /// All available plugins
37    pub fn plugin_names(&self) -> PluginNames<P> {
38        PluginNames {
39            iter: self.plugins.keys(),
40        }
41    }
42
43    /// All plugins
44    pub fn plugins(&self) -> impl Iterator<Item = &P> {
45        self.plugins.values()
46    }
47}
48
49impl<P> Default for PluginRegistry<P> {
50    #[inline]
51    fn default() -> Self {
52        Self::new()
53    }
54}
55
56impl<P> Clone for PluginRegistry<P>
57where
58    P: Clone,
59{
60    #[inline]
61    fn clone(&self) -> Self {
62        Self {
63            plugins: self.plugins.clone(),
64        }
65    }
66}
67
68//////////////////////////////////////////////////////////////////////////////
69
70macro_rules! delegate_iterator {
71    (($name:ident $($generics:tt)*) => $item:ty) => {
72        impl $($generics)* Iterator for $name $($generics)* {
73            type Item = $item;
74            #[inline]
75            fn next(&mut self) -> Option<Self::Item> {
76                self.iter.next().map(|s| s.as_str())
77            }
78            #[inline]
79            fn size_hint(&self) -> (usize, Option<usize>) {
80                self.iter.size_hint()
81            }
82        }
83
84        impl $($generics)* ExactSizeIterator for $name $($generics)* {
85            #[inline]
86            fn len(&self) -> usize {
87                self.iter.len()
88            }
89        }
90    }
91}
92
93//////////////////////////////////////////////////////////////////////////////
94
95/// Available plugins.
96#[derive(Debug)]
97pub struct PluginNames<'a, P>
98where
99    P: 'a,
100{
101    iter: KeysImpl<'a, String, P>,
102}
103
104delegate_iterator!((PluginNames<'a, P>) => &'a str);