diff --git a/i18n-embed-fl/Cargo.toml b/i18n-embed-fl/Cargo.toml index 85445ab..e54b2b3 100644 --- a/i18n-embed-fl/Cargo.toml +++ b/i18n-embed-fl/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" proc-macro = true [dependencies] -dashmap = "6.0" +dashmap = { version = "6.0", optional = true } find-crate = { workspace = true } fluent = { workspace = true } fluent-syntax = { workspace = true } @@ -32,3 +32,7 @@ doc-comment = { workspace = true } env_logger = { workspace = true } pretty_assertions = { workspace = true } rust-embed = { workspace = true } + +[features] +# Uses dashmap implementation for `fl!()` macro lookups. +dashmap = ["dep:dashmap"] \ No newline at end of file diff --git a/i18n-embed-fl/src/lib.rs b/i18n-embed-fl/src/lib.rs index e68c915..86b8139 100644 --- a/i18n-embed-fl/src/lib.rs +++ b/i18n-embed-fl/src/lib.rs @@ -9,6 +9,12 @@ use std::{ path::Path, sync::OnceLock, }; + +#[cfg(feature = "dashmap")] +use dashmap::mapref::one::Ref; +#[cfg(not(feature = "dashmap"))] +use std::sync::{Arc, RwLock}; + use syn::{parse::Parse, parse_macro_input, spanned::Spanned}; use unic_langid::LanguageIdentifier; @@ -165,10 +171,57 @@ struct DomainSpecificData { _assets: FileSystemAssets, } -fn domains() -> &'static dashmap::DashMap { - static DOMAINS: OnceLock> = OnceLock::new(); +#[derive(Default)] +struct DomainsMap { + #[cfg(not(feature = "dashmap"))] + map: RwLock>>, + + #[cfg(feature = "dashmap")] + map: dashmap::DashMap, +} + +#[cfg(feature = "dashmap")] +impl DomainsMap { + fn get(&self, domain: &String) -> Option> { + self.map.get(domain) + } + + fn entry_or_insert( + &self, + domain: &String, + data: DomainSpecificData, + ) -> Ref { + self.map.entry(domain.clone()).or_insert(data).downgrade() + } +} + +#[cfg(not(feature = "dashmap"))] +impl DomainsMap { + fn get(&self, domain: &String) -> Option> { + match self.map.read().unwrap().get(domain) { + None => None, + Some(data) => Some(data.clone()), + } + } + + fn entry_or_insert( + &self, + domain: &String, + data: DomainSpecificData, + ) -> Arc { + self.map + .write() + .unwrap() + .entry(domain.clone()) + .or_insert(Arc::new(data)) + .clone() + } +} + +fn domains() -> &'static DomainsMap { + static DOMAINS: OnceLock = OnceLock::new(); - DOMAINS.get_or_init(|| dashmap::DashMap::new()) + DOMAINS.get_or_init(|| DomainsMap::default()) } /// A macro to obtain localized messages and optionally their attributes, and check the `message_id`, `attribute_id` @@ -421,7 +474,7 @@ pub fn fl(input: TokenStream) -> TokenStream { _assets: assets, }; - domains().entry(domain.clone()).or_insert(data).downgrade() + domains().entry_or_insert(&domain, data) }; let message_id_string = match &message_id {