2019-06-22 21:51:36 +02:00
|
|
|
use std::thread_local;
|
|
|
|
use std::string::String;
|
|
|
|
use std::borrow::ToOwned;
|
|
|
|
use std::cell::{Cell, RefCell};
|
|
|
|
use crate::JsValue;
|
|
|
|
use uluru::{LRUCache, Entry};
|
|
|
|
|
|
|
|
|
|
|
|
struct Pair {
|
|
|
|
key: String,
|
|
|
|
value: JsValue,
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO figure out a good default capacity
|
|
|
|
type Entries = LRUCache::<[Entry<Pair>; 1_024]>;
|
|
|
|
|
|
|
|
struct Cache {
|
|
|
|
entries: RefCell<Entries>,
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO figure out a good max_str_len
|
|
|
|
thread_local! {
|
|
|
|
static CACHE: Cache = Cache {
|
|
|
|
entries: RefCell::new(LRUCache::default()),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-06-22 23:39:23 +02:00
|
|
|
fn get_js_string<'a>(cache: &'a mut Entries, key: &str) -> Option<&'a JsValue> {
|
|
|
|
cache.find(|p| p.key == key).map(|x| &x.value)
|
|
|
|
}
|
2019-06-22 21:51:36 +02:00
|
|
|
|
2019-06-22 23:39:23 +02:00
|
|
|
fn insert_js_string(cache: &mut Entries, key: &str, value: JsValue) {
|
|
|
|
cache.insert(Pair {
|
|
|
|
key: key.to_owned(),
|
|
|
|
value,
|
|
|
|
});
|
2019-06-22 21:51:36 +02:00
|
|
|
}
|
|
|
|
|
2019-06-22 23:39:23 +02:00
|
|
|
fn get_str(s: &str) -> JsValue {
|
2019-06-22 21:51:36 +02:00
|
|
|
CACHE.with(|cache| {
|
2019-06-22 23:39:23 +02:00
|
|
|
let mut cache = cache.entries.borrow_mut();
|
2019-06-22 21:51:36 +02:00
|
|
|
|
2019-06-22 23:39:23 +02:00
|
|
|
if let Some(value) = get_js_string(&mut cache, s) {
|
|
|
|
value.clone()
|
2019-06-22 21:51:36 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
JsValue::from(s)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-06-22 23:39:23 +02:00
|
|
|
fn intern_str(s: &str) {
|
|
|
|
CACHE.with(|cache| {
|
|
|
|
let mut cache = cache.entries.borrow_mut();
|
|
|
|
|
|
|
|
if get_js_string(&mut cache, s).is_none() {
|
|
|
|
insert_js_string(&mut cache, s, JsValue::from(s));
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-06-22 21:51:36 +02:00
|
|
|
#[inline]
|
2019-06-22 23:39:23 +02:00
|
|
|
pub(crate) fn str(s: &str) -> JsValue {
|
2019-06-22 21:51:36 +02:00
|
|
|
if cfg!(feature = "disable-interning") {
|
|
|
|
JsValue::from(s)
|
|
|
|
|
|
|
|
} else {
|
2019-06-22 23:39:23 +02:00
|
|
|
get_str(s)
|
2019-06-22 21:51:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-06-22 23:39:23 +02:00
|
|
|
pub fn intern(s: &str) -> &str {
|
2019-06-22 21:51:36 +02:00
|
|
|
if !cfg!(feature = "disable-interning") {
|
2019-06-22 23:39:23 +02:00
|
|
|
intern_str(s);
|
2019-06-22 21:51:36 +02:00
|
|
|
}
|
|
|
|
|
2019-06-22 23:39:23 +02:00
|
|
|
s
|
2019-06-22 21:51:36 +02:00
|
|
|
}
|