From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- third_party/rust/intl-memoizer/src/concurrent.rs | 39 +++++++ third_party/rust/intl-memoizer/src/lib.rs | 140 +++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 third_party/rust/intl-memoizer/src/concurrent.rs create mode 100644 third_party/rust/intl-memoizer/src/lib.rs (limited to 'third_party/rust/intl-memoizer/src') diff --git a/third_party/rust/intl-memoizer/src/concurrent.rs b/third_party/rust/intl-memoizer/src/concurrent.rs new file mode 100644 index 0000000000..95553281b6 --- /dev/null +++ b/third_party/rust/intl-memoizer/src/concurrent.rs @@ -0,0 +1,39 @@ +use super::*; +use std::sync::Mutex; + +#[derive(Debug)] +pub struct IntlLangMemoizer { + lang: LanguageIdentifier, + map: Mutex, +} + +impl IntlLangMemoizer { + pub fn new(lang: LanguageIdentifier) -> Self { + Self { + lang, + map: Mutex::new(type_map::concurrent::TypeMap::new()), + } + } + + pub fn with_try_get(&self, args: I::Args, cb: U) -> Result + where + Self: Sized, + I: Memoizable + Sync + Send + 'static, + I::Args: Send + Sync + 'static, + U: FnOnce(&I) -> R, + { + let mut map = self.map.lock().unwrap(); + let cache = map + .entry::>() + .or_insert_with(HashMap::new); + + let e = match cache.entry(args.clone()) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => { + let val = I::construct(self.lang.clone(), args)?; + entry.insert(val) + } + }; + Ok(cb(&e)) + } +} diff --git a/third_party/rust/intl-memoizer/src/lib.rs b/third_party/rust/intl-memoizer/src/lib.rs new file mode 100644 index 0000000000..8205616a87 --- /dev/null +++ b/third_party/rust/intl-memoizer/src/lib.rs @@ -0,0 +1,140 @@ +use std::cell::RefCell; +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::hash::Hash; +use std::rc::{Rc, Weak}; +use unic_langid::LanguageIdentifier; + +pub mod concurrent; + +pub trait Memoizable { + type Args: 'static + Eq + Hash + Clone; + type Error; + fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result + where + Self: std::marker::Sized; +} + +#[derive(Debug)] +pub struct IntlLangMemoizer { + lang: LanguageIdentifier, + map: RefCell, +} + +impl IntlLangMemoizer { + pub fn new(lang: LanguageIdentifier) -> Self { + Self { + lang, + map: RefCell::new(type_map::TypeMap::new()), + } + } + + pub fn with_try_get(&self, args: I::Args, cb: U) -> Result + where + Self: Sized, + I: Memoizable + 'static, + U: FnOnce(&I) -> R, + { + let mut map = self + .map + .try_borrow_mut() + .expect("Cannot use memoizer reentrantly"); + let cache = map + .entry::>() + .or_insert_with(HashMap::new); + + let e = match cache.entry(args.clone()) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => { + let val = I::construct(self.lang.clone(), args)?; + entry.insert(val) + } + }; + Ok(cb(&e)) + } +} + +#[derive(Default)] +pub struct IntlMemoizer { + map: HashMap>, +} + +impl IntlMemoizer { + pub fn get_for_lang(&mut self, lang: LanguageIdentifier) -> Rc { + match self.map.entry(lang.clone()) { + Entry::Vacant(empty) => { + let entry = Rc::new(IntlLangMemoizer::new(lang)); + empty.insert(Rc::downgrade(&entry)); + entry + } + Entry::Occupied(mut entry) => { + if let Some(entry) = entry.get().upgrade() { + entry + } else { + let e = Rc::new(IntlLangMemoizer::new(lang)); + entry.insert(Rc::downgrade(&e)); + e + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use fluent_langneg::{negotiate_languages, NegotiationStrategy}; + use intl_pluralrules::{PluralCategory, PluralRuleType, PluralRules as IntlPluralRules}; + + struct PluralRules(pub IntlPluralRules); + + impl PluralRules { + pub fn new( + lang: LanguageIdentifier, + pr_type: PluralRuleType, + ) -> Result { + let default_lang: LanguageIdentifier = "en".parse().unwrap(); + let pr_lang = negotiate_languages( + &[lang], + &IntlPluralRules::get_locales(pr_type), + Some(&default_lang), + NegotiationStrategy::Lookup, + )[0] + .clone(); + + Ok(Self(IntlPluralRules::create(pr_lang, pr_type)?)) + } + } + + impl Memoizable for PluralRules { + type Args = (PluralRuleType,); + type Error = &'static str; + fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result { + Self::new(lang, args.0) + } + } + + #[test] + fn it_works() { + let lang: LanguageIdentifier = "en".parse().unwrap(); + + let mut memoizer = IntlMemoizer::default(); + { + let en_memoizer = memoizer.get_for_lang(lang.clone()); + + let result = en_memoizer + .with_try_get::((PluralRuleType::CARDINAL,), |cb| cb.0.select(5)) + .unwrap(); + assert_eq!(result, Ok(PluralCategory::OTHER)); + } + + { + let en_memoizer = memoizer.get_for_lang(lang.clone()); + + let result = en_memoizer + .with_try_get::((PluralRuleType::CARDINAL,), |cb| cb.0.select(5)) + .unwrap(); + assert_eq!(result, Ok(PluralCategory::OTHER)); + } + } +} -- cgit v1.2.3