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}