Skip to main content

spo_rhai/module/resolvers/
stat.rs

1use crate::{
2    Engine, Identifier, Module, ModuleResolver, Position, RhaiResultOf, SharedModule, SmartString,
3    ERR,
4};
5#[cfg(feature = "no_std")]
6use std::prelude::v1::*;
7use std::{
8    collections::btree_map::{IntoIter, Iter},
9    collections::BTreeMap,
10    ops::AddAssign,
11};
12
13/// A static [module][Module] resolution service that serves [modules][Module] added into it.
14///
15/// # Example
16///
17/// ```
18/// use rhai::{Engine, Module};
19/// use rhai::module_resolvers::StaticModuleResolver;
20///
21/// let mut resolver = StaticModuleResolver::new();
22///
23/// let module = Module::new();
24/// resolver.insert("hello", module);
25///
26/// let mut engine = Engine::new();
27///
28/// engine.set_module_resolver(resolver);
29/// ```
30#[derive(Debug, Clone, Default)]
31pub struct StaticModuleResolver(BTreeMap<Identifier, SharedModule>);
32
33impl StaticModuleResolver {
34    /// Create a new [`StaticModuleResolver`].
35    ///
36    /// # Example
37    ///
38    /// ```
39    /// use rhai::{Engine, Module};
40    /// use rhai::module_resolvers::StaticModuleResolver;
41    ///
42    /// let mut resolver = StaticModuleResolver::new();
43    ///
44    /// let module = Module::new();
45    /// resolver.insert("hello", module);
46    ///
47    /// let mut engine = Engine::new();
48    /// engine.set_module_resolver(resolver);
49    /// ```
50    #[inline(always)]
51    #[must_use]
52    pub const fn new() -> Self {
53        Self(BTreeMap::new())
54    }
55    /// Add a [module][Module] keyed by its path.
56    #[inline]
57    pub fn insert(&mut self, path: impl Into<Identifier>, mut module: Module) {
58        let path = path.into();
59
60        if module.id().is_none() {
61            module.set_id(path.clone());
62        }
63
64        module.build_index();
65        self.0.insert(path, module.into());
66    }
67    /// Remove a [module][Module] given its path.
68    #[inline(always)]
69    pub fn remove(&mut self, path: &str) -> Option<SharedModule> {
70        self.0.remove(path)
71    }
72    /// Does the path exist?
73    #[inline(always)]
74    #[must_use]
75    pub fn contains_path(&self, path: &str) -> bool {
76        self.0.contains_key(path)
77    }
78    /// Get an iterator of all the [modules][Module].
79    #[inline]
80    pub fn iter(&self) -> impl Iterator<Item = (&str, &SharedModule)> {
81        self.0.iter().map(|(k, v)| (k.as_str(), v))
82    }
83    /// Get a mutable iterator of all the [modules][Module].
84    #[inline]
85    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&str, &mut SharedModule)> {
86        self.0.iter_mut().map(|(k, v)| (k.as_str(), v))
87    }
88    /// Get an iterator of all the [module][Module] paths.
89    #[inline]
90    pub fn paths(&self) -> impl Iterator<Item = &str> {
91        self.0.keys().map(SmartString::as_str)
92    }
93    /// Get an iterator of all the [modules][Module].
94    #[inline(always)]
95    pub fn values(&self) -> impl Iterator<Item = &SharedModule> {
96        self.0.values()
97    }
98    /// Remove all [modules][Module].
99    #[inline(always)]
100    pub fn clear(&mut self) -> &mut Self {
101        self.0.clear();
102        self
103    }
104    /// Returns `true` if this [`StaticModuleResolver`] contains no module resolvers.
105    #[inline(always)]
106    #[must_use]
107    pub fn is_empty(&self) -> bool {
108        self.0.is_empty()
109    }
110    /// Get the number of [modules][Module] in this [`StaticModuleResolver`].
111    #[inline(always)]
112    #[must_use]
113    pub fn len(&self) -> usize {
114        self.0.len()
115    }
116    /// Merge another [`StaticModuleResolver`] into this.
117    /// The other [`StaticModuleResolver`] is consumed.
118    ///
119    /// Existing modules of the same path name are overwritten.
120    #[inline]
121    pub fn merge(&mut self, other: Self) -> &mut Self {
122        self.0.extend(other.0);
123        self
124    }
125}
126
127impl IntoIterator for StaticModuleResolver {
128    type Item = (Identifier, SharedModule);
129    type IntoIter = IntoIter<SmartString, SharedModule>;
130
131    #[inline(always)]
132    #[must_use]
133    fn into_iter(self) -> Self::IntoIter {
134        self.0.into_iter()
135    }
136}
137
138impl<'a> IntoIterator for &'a StaticModuleResolver {
139    type Item = (&'a Identifier, &'a SharedModule);
140    type IntoIter = Iter<'a, SmartString, SharedModule>;
141
142    #[inline(always)]
143    fn into_iter(self) -> Self::IntoIter {
144        self.0.iter()
145    }
146}
147
148impl AddAssign<Self> for StaticModuleResolver {
149    #[inline(always)]
150    fn add_assign(&mut self, rhs: Self) {
151        self.merge(rhs);
152    }
153}
154
155impl ModuleResolver for StaticModuleResolver {
156    #[inline]
157    fn resolve(
158        &self,
159        _: &Engine,
160        _: Option<&str>,
161        path: &str,
162        pos: Position,
163    ) -> RhaiResultOf<SharedModule> {
164        self.0
165            .get(path)
166            .cloned()
167            .ok_or_else(|| ERR::ErrorModuleNotFound(path.into(), pos).into())
168    }
169}