spo_rhai/eval/
cache.rs

1//! System caches.
2
3use crate::func::{RhaiFunc, StraightHashMap};
4use crate::types::BloomFilterU64;
5use crate::{ImmutableString, StaticVec};
6#[cfg(feature = "no_std")]
7use std::prelude::v1::*;
8
9/// _(internals)_ An entry in a function resolution cache.
10/// Exported under the `internals` feature only.
11#[derive(Debug, Clone)]
12pub struct FnResolutionCacheEntry {
13    /// Function.
14    pub func: RhaiFunc,
15    /// Optional source.
16    pub source: Option<ImmutableString>,
17}
18
19/// _(internals)_ A function resolution cache with a bloom filter.
20/// Exported under the `internals` feature only.
21///
22/// The [bloom filter][`BloomFilterU64`] is used to rapidly check whether a function hash has never been encountered.
23/// It enables caching a hash only during the second encounter to avoid "one-hit wonders".
24#[derive(Debug, Clone, Default)]
25pub struct FnResolutionCache {
26    /// Hash map containing cached functions.
27    pub dict: StraightHashMap<Option<FnResolutionCacheEntry>>,
28    /// Bloom filter to avoid caching "one-hit wonders".
29    pub filter: BloomFilterU64,
30}
31
32impl FnResolutionCache {
33    /// Clear the [`FnResolutionCache`].
34    #[inline(always)]
35    #[allow(dead_code)]
36    pub fn clear(&mut self) {
37        self.dict.clear();
38        self.filter.clear();
39    }
40}
41
42/// _(internals)_ A type containing system-wide caches.
43/// Exported under the `internals` feature only.
44///
45/// The following caches are contained inside this type:
46/// * A stack of [function resolution caches][FnResolutionCache]
47#[derive(Debug, Clone)]
48pub struct Caches {
49    fn_resolution: StaticVec<FnResolutionCache>,
50}
51
52impl Caches {
53    /// Create an empty [`Caches`].
54    #[inline(always)]
55    #[must_use]
56    pub const fn new() -> Self {
57        Self {
58            fn_resolution: StaticVec::new_const(),
59        }
60    }
61    /// Get the number of function resolution cache(s) in the stack.
62    #[inline(always)]
63    #[must_use]
64    pub fn fn_resolution_caches_len(&self) -> usize {
65        self.fn_resolution.len()
66    }
67    /// Get a mutable reference to the current function resolution cache.
68    ///
69    /// A new function resolution cache is pushed onto the stack if the stack is empty.
70    #[inline]
71    #[must_use]
72    pub fn fn_resolution_cache_mut(&mut self) -> &mut FnResolutionCache {
73        // Push a new function resolution cache if the stack is empty
74        if self.fn_resolution.is_empty() {
75            self.push_fn_resolution_cache();
76        }
77        self.fn_resolution.last_mut().unwrap()
78    }
79    /// Push an empty function resolution cache onto the stack and make it current.
80    #[inline(always)]
81    pub fn push_fn_resolution_cache(&mut self) {
82        self.fn_resolution.push(<_>::default());
83    }
84    /// Rewind the function resolution caches stack to a particular size.
85    #[inline(always)]
86    pub fn rewind_fn_resolution_caches(&mut self, len: usize) {
87        self.fn_resolution.truncate(len);
88    }
89}