fluent_fallback/
localization.rs

1use crate::{
2    bundles::Bundles,
3    env::LocalesProvider,
4    generator::{BundleGenerator, BundleIterator, BundleStream},
5    types::ResourceId,
6};
7use once_cell::sync::OnceCell;
8use rustc_hash::FxHashSet;
9use std::rc::Rc;
10
11pub struct Localization<G, P>
12where
13    G: BundleGenerator<LocalesIter = P::Iter>,
14    P: LocalesProvider,
15{
16    bundles: OnceCell<Rc<Bundles<G>>>,
17    generator: G,
18    provider: P,
19    sync: bool,
20    res_ids: FxHashSet<ResourceId>,
21}
22
23impl<G, P> Localization<G, P>
24where
25    G: BundleGenerator<LocalesIter = P::Iter> + Default,
26    P: LocalesProvider + Default,
27{
28    pub fn new<I>(res_ids: I, sync: bool) -> Self
29    where
30        I: IntoIterator<Item = ResourceId>,
31    {
32        Self {
33            bundles: OnceCell::new(),
34            generator: G::default(),
35            provider: P::default(),
36            sync,
37            res_ids: FxHashSet::from_iter(res_ids),
38        }
39    }
40}
41
42impl<G, P> Localization<G, P>
43where
44    G: BundleGenerator<LocalesIter = P::Iter>,
45    P: LocalesProvider,
46{
47    pub fn with_env<I>(res_ids: I, sync: bool, provider: P, generator: G) -> Self
48    where
49        I: IntoIterator<Item = ResourceId>,
50    {
51        Self {
52            bundles: OnceCell::new(),
53            generator,
54            provider,
55            sync,
56            res_ids: FxHashSet::from_iter(res_ids),
57        }
58    }
59
60    pub fn is_sync(&self) -> bool {
61        self.sync
62    }
63
64    pub fn add_resource_id<T: Into<ResourceId>>(&mut self, res_id: T) {
65        self.res_ids.insert(res_id.into());
66        self.on_change();
67    }
68
69    pub fn add_resource_ids(&mut self, res_ids: Vec<ResourceId>) {
70        self.res_ids.extend(res_ids);
71        self.on_change();
72    }
73
74    pub fn remove_resource_id<T: PartialEq<ResourceId>>(&mut self, res_id: T) -> usize {
75        self.res_ids.retain(|x| !res_id.eq(x));
76        self.on_change();
77        self.res_ids.len()
78    }
79
80    pub fn remove_resource_ids(&mut self, res_ids: Vec<ResourceId>) -> usize {
81        self.res_ids.retain(|x| !res_ids.contains(x));
82        self.on_change();
83        self.res_ids.len()
84    }
85
86    pub fn set_async(&mut self) {
87        if self.sync {
88            self.sync = false;
89            self.on_change();
90        }
91    }
92
93    pub fn on_change(&mut self) {
94        self.bundles.take();
95    }
96}
97
98impl<G, P> Localization<G, P>
99where
100    G: BundleGenerator<LocalesIter = P::Iter>,
101    G::Iter: BundleIterator,
102    P: LocalesProvider,
103{
104    pub fn prefetch_sync(&mut self) {
105        let bundles = self.bundles();
106        bundles.prefetch_sync();
107    }
108}
109
110impl<G, P> Localization<G, P>
111where
112    G: BundleGenerator<LocalesIter = P::Iter>,
113    G::Stream: BundleStream,
114    P: LocalesProvider,
115{
116    pub async fn prefetch_async(&mut self) {
117        let bundles = self.bundles();
118        bundles.prefetch_async().await;
119    }
120}
121
122impl<G, P> Localization<G, P>
123where
124    G: BundleGenerator<LocalesIter = P::Iter>,
125    P: LocalesProvider,
126{
127    pub fn bundles(&self) -> &Rc<Bundles<G>> {
128        self.bundles.get_or_init(|| {
129            Rc::new(Bundles::new(
130                self.sync,
131                self.res_ids.clone(),
132                &self.generator,
133                &self.provider,
134            ))
135        })
136    }
137}