Remove Interners struct.

This commit is contained in:
Stephen Chung
2022-08-14 14:32:16 +08:00
parent f7d910fa55
commit b75ea94908
2 changed files with 44 additions and 46 deletions

View File

@@ -5,6 +5,7 @@ use crate::ImmutableString;
use std::prelude::v1::*;
use std::{
collections::BTreeMap,
fmt,
hash::{Hash, Hasher},
marker::PhantomData,
ops::AddAssign,
@@ -20,10 +21,12 @@ pub const MAX_STRING_LEN: usize = 24;
/// Exported under the `internals` feature only.
///
/// Normal identifiers, property getters and setters are interned separately.
#[derive(Debug, Clone, Hash)]
#[derive(Clone, Hash)]
pub struct StringsInterner<'a> {
/// Maximum capacity.
max: usize,
/// Maximum number of strings interned.
pub capacity: usize,
/// Maximum string length.
pub max_string_len: usize,
/// Normal strings.
strings: BTreeMap<u64, ImmutableString>,
/// Take care of the lifetime parameter.
@@ -37,24 +40,26 @@ impl Default for StringsInterner<'_> {
}
}
impl fmt::Debug for StringsInterner<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.strings.values()).finish()
}
}
impl StringsInterner<'_> {
/// Create a new [`StringsInterner`].
#[inline(always)]
#[must_use]
pub fn new() -> Self {
Self::new_with_capacity(MAX_INTERNED_STRINGS)
}
/// Create a new [`StringsInterner`] with maximum capacity.
#[inline]
#[must_use]
pub fn new_with_capacity(capacity: usize) -> Self {
Self {
max: capacity,
capacity: MAX_INTERNED_STRINGS,
max_string_len: MAX_STRING_LEN,
strings: BTreeMap::new(),
dummy: PhantomData,
}
}
/// Get an identifier from a text string, adding it to the interner if necessary.
#[inline(always)]
#[must_use]
@@ -72,12 +77,9 @@ impl StringsInterner<'_> {
) -> ImmutableString {
let key = text.as_ref();
// Do not intern numbers
if key.bytes().all(|c| c == b'.' || (c >= b'0' && c <= b'9')) {
return text.into();
}
if key.len() > MAX_STRING_LEN {
// Do not intern long strings or numbers
if key.len() > MAX_STRING_LEN || key.bytes().all(|c| c == b'.' || (c >= b'0' && c <= b'9'))
{
return mapper(text);
}
@@ -98,11 +100,15 @@ impl StringsInterner<'_> {
self.strings.insert(key, value.clone());
// If the interner is over capacity, remove the longest entry
if self.strings.len() > self.max {
if self.strings.len() > self.capacity {
// Leave some buffer to grow when shrinking the cache.
// We leave at least two entries, one for the empty string, and one for the string
// that has just been inserted.
let max = if self.max < 5 { 2 } else { self.max - 3 };
let max = if self.capacity < 5 {
2
} else {
self.capacity - 3
};
while self.strings.len() > max {
let (_, n) = self.strings.iter().fold((0, 0), |(x, n), (&k, v)| {
@@ -127,7 +133,7 @@ impl StringsInterner<'_> {
self.strings.len()
}
/// Number of strings interned.
/// Are there no interned strings?
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
@@ -135,7 +141,7 @@ impl StringsInterner<'_> {
}
/// Clear all interned strings.
#[inline]
#[inline(always)]
pub fn clear(&mut self) {
self.strings.clear();
}