A bunch of fixes and improvements
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
use arcstr::ArcStr;
|
||||
use hashbrown::HashMap;
|
||||
use parking_lot::RwLock;
|
||||
use std::borrow::Borrow;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
|
||||
use conquer_once::OnceCell;
|
||||
use hashbrown::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
/// StringKey is an immutable string that is used for indexing of hashmaps or equality a lot.
|
||||
/// By reference counting the string instead of copying, and caching the hash, we can get some
|
||||
@@ -16,16 +16,16 @@ use hashbrown::HashMap;
|
||||
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
|
||||
pub struct StringKey {
|
||||
/// The underlying reference counted string.
|
||||
str: Arc<str>,
|
||||
str: ArcStr,
|
||||
/// The unique hash of the string.
|
||||
hash: u32,
|
||||
}
|
||||
|
||||
/// A cache of all allocated strings. This allows us to re-use strings that are often used without
|
||||
/// allocation.
|
||||
static STRING_CACHE: OnceCell<Mutex<HashMap<u32, Weak<str>>>> = OnceCell::uninit();
|
||||
static STRING_CACHE: LazyLock<RwLock<HashMap<u32, ArcStr>>> = LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
/// An empty StringKey
|
||||
static EMPTY: OnceCell<StringKey> = OnceCell::uninit();
|
||||
static EMPTY: LazyLock<StringKey> = LazyLock::new(|| StringKey::new(""));
|
||||
|
||||
impl StringKey {
|
||||
/// Gets the hash of a string.
|
||||
@@ -42,25 +42,29 @@ impl StringKey {
|
||||
/// Creates a new StringKey. If we can find a value for this StringKey in the cache, we re-use
|
||||
/// that value.
|
||||
pub fn new(s: &str) -> Self {
|
||||
let hash = StringKey::get_hash(s);
|
||||
let mut cache = STRING_CACHE.get_or_init(|| Mutex::new(HashMap::new())).lock().unwrap();
|
||||
let cached_value = cache.get(&hash);
|
||||
if let Some(cached_value) = cached_value {
|
||||
if let Some(cached_value) = cached_value.upgrade() {
|
||||
let s: ArcStr = s.into();
|
||||
let hash = StringKey::get_hash(s.as_str());
|
||||
{
|
||||
let cache_read = STRING_CACHE.read();
|
||||
let cached_value = cache_read.get(&hash);
|
||||
if let Some(cached_value) = cached_value {
|
||||
return Self {
|
||||
str: cached_value,
|
||||
str: cached_value.clone(),
|
||||
hash,
|
||||
};
|
||||
}
|
||||
}
|
||||
let v = Self { str: s.into(), hash };
|
||||
cache.insert(hash, Arc::downgrade(&v.str));
|
||||
v
|
||||
{
|
||||
let v = Self { str: s.clone(), hash };
|
||||
let mut cache_write = STRING_CACHE.write();
|
||||
cache_write.insert(hash, s);
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the empty StringKey.
|
||||
pub fn empty() -> Self {
|
||||
EMPTY.get_or_init(|| StringKey::new("")).clone()
|
||||
EMPTY.clone()
|
||||
}
|
||||
|
||||
/// Gets the underlying string for the StringKey.
|
||||
@@ -108,7 +112,7 @@ impl Display for StringKey {
|
||||
|
||||
impl Into<StringKey> for &CStr {
|
||||
fn into(self) -> StringKey {
|
||||
StringKey::new(self.to_str().unwrap())
|
||||
StringKey::new(self.to_str().unwrap().into())
|
||||
}
|
||||
}
|
||||
/// Converts a character to lowercased in a const safe way.
|
||||
@@ -160,7 +164,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_empty_stringkey() {
|
||||
let sk = StringKey::new("");
|
||||
let sk = StringKey::new("".into());
|
||||
assert_eq!(sk.str(), "");
|
||||
assert_eq!(sk.hash(), 0);
|
||||
assert_eq!(sk.hash(), StringKey::get_hash(""));
|
||||
@@ -168,7 +172,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_stringkey_foo() {
|
||||
let sk = StringKey::new("foo");
|
||||
let sk = StringKey::new("foo".into());
|
||||
assert_eq!(sk.str(), "foo");
|
||||
assert_eq!(sk.hash(), 2356372769);
|
||||
assert_eq!(sk.hash(), StringKey::get_hash("foo"));
|
||||
@@ -177,7 +181,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_stringkey_bar() {
|
||||
let sk = StringKey::new("bar");
|
||||
let sk = StringKey::new("bar".into());
|
||||
assert_eq!(sk.str(), "bar");
|
||||
assert_eq!(sk.hash(), 1996459178);
|
||||
assert_eq!(sk.hash(), StringKey::get_hash("bar"));
|
||||
|
||||
Reference in New Issue
Block a user