use dashmap::DashMap;
use once_cell::sync::Lazy;
use std::sync::atomic::{AtomicU32, Ordering};
#[allow(dead_code)]
pub struct StringIntern {
strings: DashMap<String, u32>,
reverse: DashMap<u32, String>,
next_id: AtomicU32,
}
#[allow(dead_code)]
impl StringIntern {
pub fn new() -> Self {
Self {
strings: DashMap::new(),
reverse: DashMap::new(),
next_id: AtomicU32::new(1),
}
}
pub fn intern(&self, s: &str) -> u32 {
if let Some(id) = self.strings.get(s) {
return *id;
}
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
self.strings.insert(s.to_string(), id);
self.reverse.insert(id, s.to_string());
id
}
pub fn get(&self, id: u32) -> Option<String> {
self.reverse.get(&id).map(|s| s.clone())
}
pub fn intern_batch(&self, strings: &[&str]) -> Vec<u32> {
strings.iter().map(|s| self.intern(s)).collect()
}
pub fn size(&self) -> usize {
self.strings.len()
}
}
#[allow(dead_code)]
impl Default for StringIntern {
fn default() -> Self {
Self::new()
}
}
#[allow(dead_code)]
pub static ORG_NAMES: Lazy<StringIntern> = Lazy::new(StringIntern::new);
#[allow(dead_code)]
pub static USER_ROLES: Lazy<StringIntern> = Lazy::new(StringIntern::new);
#[allow(dead_code)]
pub static PRODUCT_CATEGORIES: Lazy<StringIntern> = Lazy::new(StringIntern::new);
#[allow(dead_code)]
pub static COUNTRIES: Lazy<StringIntern> = Lazy::new(StringIntern::new);
#[allow(dead_code)]
pub static STATUSES: Lazy<StringIntern> = Lazy::new(StringIntern::new);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_intern_same_string() {
let intern = StringIntern::new();
let id1 = intern.intern("test");
let id2 = intern.intern("test");
assert_eq!(id1, id2);
}
#[test]
fn test_intern_different_strings() {
let intern = StringIntern::new();
let id1 = intern.intern("test1");
let id2 = intern.intern("test2");
assert_ne!(id1, id2);
}
#[test]
fn test_reverse_lookup() {
let intern = StringIntern::new();
let id = intern.intern("hello");
assert_eq!(intern.get(id), Some("hello".to_string()));
}
#[test]
fn test_batch_intern() {
let intern = StringIntern::new();
let strings = vec!["a", "b", "c", "a", "b"];
let ids = intern.intern_batch(&strings);
assert_eq!(ids[0], ids[3]); assert_eq!(ids[1], ids[4]); }
}