use super::interned::InternedString;
use std::sync::Arc;
use std::sync::LazyLock;
use std::sync::atomic::{AtomicBool, Ordering};
pub(super) struct LanguageStringPool {
pool: dashmap::DashMap<String, Arc<String>>,
initialized: AtomicBool,
}
impl LanguageStringPool {
pub(super) fn new() -> Self {
LanguageStringPool {
pool: dashmap::DashMap::new(),
initialized: AtomicBool::new(false),
}
}
#[inline]
fn ensure_initialized(&self) {
if self.initialized.load(Ordering::Acquire) {
return;
}
let lang_codes = vec![
"en", "es", "fr", "de", "it", "pt", "ru", "ja", "ko", "zh", "ar", "hi", "th", "tr", "pl", "nl", "sv", "no",
"da", "fi", "cs", "hu", "ro", "el", "he", "fa", "ur", "vi", "id", "ms", "bn", "pa", "te", "mr", "ta", "gu",
"kn", "ml", "or", "uk", "bg", "sr", "hr", "sl", "sk", "et", "lv", "lt", "sq", "mk", "ka", "hy", "eo",
"ast", "ca", "eu", "gl", "cy", "gd", "ga",
];
for code in lang_codes {
self.pool.insert(code.to_string(), Arc::new(code.to_string()));
}
let _ = self
.initialized
.compare_exchange(false, true, Ordering::Release, Ordering::Relaxed);
}
pub(super) fn get_or_intern(&self, lang_code: &str) -> Arc<String> {
self.ensure_initialized();
if let Some(entry) = self.pool.get(lang_code) {
Arc::clone(&*entry)
} else {
let arc_string = Arc::new(lang_code.to_string());
self.pool.insert(lang_code.to_string(), Arc::clone(&arc_string));
arc_string
}
}
}
pub(super) static LANGUAGE_POOL: LazyLock<LanguageStringPool> = LazyLock::new(LanguageStringPool::new);
pub fn intern_language_code(lang_code: &str) -> InternedString {
InternedString(LANGUAGE_POOL.get_or_intern(lang_code))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_language_code_deduplication() {
let en1 = intern_language_code("en");
let en2 = intern_language_code("en");
assert_eq!(en1, en2);
assert!(Arc::ptr_eq(&en1.0, &en2.0));
}
#[test]
fn test_preinterned_language_codes() {
let en = intern_language_code("en");
assert_eq!(en.as_str(), "en");
let es = intern_language_code("es");
assert_eq!(es.as_str(), "es");
let fr = intern_language_code("fr");
assert_eq!(fr.as_str(), "fr");
}
}