#[cfg(any(feature = "regex", feature = "glob"))]
use core::num::NonZeroUsize;
#[cfg(any(feature = "regex", feature = "glob"))]
use lazy_static::lazy_static;
#[cfg(all(feature = "std", any(feature = "regex", feature = "glob")))]
use parking_lot::Mutex;
#[cfg(all(not(feature = "std"), any(feature = "regex", feature = "glob")))]
use spin::Mutex;
#[cfg(any(feature = "regex", feature = "glob"))]
use alloc::string::String;
#[derive(Debug, Clone, Copy)]
pub struct Config {
pub regex: usize,
pub glob: usize,
}
impl Config {
pub const MAX_CAPACITY: usize = 1 << 16;
}
impl Default for Config {
fn default() -> Self {
Self {
regex: 256,
glob: 128,
}
}
}
#[cfg(any(feature = "regex", feature = "glob"))]
pub(crate) struct LruCache<V> {
inner: Option<lru::LruCache<String, V>>,
}
#[cfg(any(feature = "regex", feature = "glob"))]
impl<V> LruCache<V> {
pub(crate) fn new(capacity: usize) -> Self {
Self {
inner: NonZeroUsize::new(capacity).map(lru::LruCache::new),
}
}
pub(crate) fn get(&mut self, key: &str) -> Option<&V> {
self.inner.as_mut()?.get(key)
}
pub(crate) fn put(&mut self, key: String, value: V) {
if let Some(cache) = self.inner.as_mut() {
cache.put(key, value);
}
}
pub(crate) fn clear(&mut self) {
if let Some(cache) = self.inner.as_mut() {
cache.clear();
}
}
pub(crate) fn resize(&mut self, capacity: usize) {
match NonZeroUsize::new(capacity) {
Some(cap) => match self.inner.as_mut() {
Some(cache) => cache.resize(cap),
None => self.inner = Some(lru::LruCache::new(cap)),
},
None => {
self.inner = None;
}
}
}
#[allow(dead_code)]
pub(crate) fn len(&self) -> usize {
self.inner.as_ref().map_or(0, lru::LruCache::len)
}
}
#[cfg(feature = "regex")]
lazy_static! {
pub(crate) static ref REGEX_CACHE: Mutex<LruCache<regex::Regex>> =
Mutex::new(LruCache::new(Config::default().regex));
}
#[cfg(feature = "glob")]
lazy_static! {
pub(crate) static ref GLOB_CACHE: Mutex<LruCache<globset::GlobMatcher>> =
Mutex::new(LruCache::new(Config::default().glob));
}
pub fn configure(config: Config) {
let regex = config.regex.min(Config::MAX_CAPACITY);
let glob = config.glob.min(Config::MAX_CAPACITY);
#[cfg(feature = "regex")]
REGEX_CACHE.lock().resize(regex);
#[cfg(feature = "glob")]
GLOB_CACHE.lock().resize(glob);
let _ = (regex, glob);
}
pub fn clear() {
#[cfg(feature = "regex")]
REGEX_CACHE.lock().clear();
#[cfg(feature = "glob")]
GLOB_CACHE.lock().clear();
}