use std::ops::{Deref, DerefMut};
use regex::{Regex, RegexBuilder, Error};
use lru::LruCache;
pub struct RegexCache(LruCache<String, Regex>);
impl RegexCache {
pub fn new(capacity: usize) -> RegexCache {
RegexCache(LruCache::new(capacity))
}
pub fn save(&mut self, re: Regex) -> &Regex {
let source = re.as_str().to_owned();
if !self.0.contains_key(re.as_str()) {
self.insert(source.clone(), re);
}
self.0.get_mut(&source).unwrap()
}
pub fn compile(&mut self, source: &str) -> Result<&Regex, Error> {
if !self.0.contains_key(source) {
self.0.insert(source.into(), Regex::new(source)?);
}
Ok(self.0.get_mut(source).unwrap())
}
pub fn configure<F>(&mut self, source: &str, f: F) -> Result<&Regex, Error>
where F: FnOnce(&mut RegexBuilder) -> &mut RegexBuilder
{
if !self.0.contains_key(source) {
self.0.insert(source.into(), f(&mut RegexBuilder::new(source)).build()?);
}
Ok(self.0.get_mut(source).unwrap())
}
}
impl Deref for RegexCache {
type Target = LruCache<String, Regex>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for RegexCache {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(test)]
mod test {
use cache::RegexCache;
#[test]
fn respects_limit() {
let mut cache = RegexCache::new(2);
cache.compile("[01]2").unwrap();
cache.compile("[21]0").unwrap();
assert_eq!(cache.len(), 2);
cache.compile("[21]3").unwrap();
assert_eq!(cache.len(), 2);
}
}