use super::{BundleAdapter, L10nRegistry, MetaSources}; use crate::env::ErrorReporter; use crate::errors::L10nRegistryError; use crate::fluent::{FluentBundle, FluentError}; use crate::solver::{SerialProblemSolver, SyncTester}; use crate::source::ResourceOption; use fluent_fallback::{generator::BundleIterator, types::ResourceId}; use unic_langid::LanguageIdentifier; impl MetaSources { pub(crate) fn bundle_from_order
(
&self,
metasource: usize,
locale: LanguageIdentifier,
source_order: &[usize],
resource_ids: &[ResourceId],
error_reporter: &P,
bundle_adapter: Option<&B>,
) -> Option L10nRegistry
where
P: Clone,
B: Clone,
{
/// A test-only function for easily generating bundles for a single langid.
#[cfg(feature = "test-fluent")]
pub fn generate_bundles_for_lang_sync(
&self,
langid: LanguageIdentifier,
resource_ids: Vec {
let lang_ids = vec![langid];
GenerateBundlesSync::new(self.clone(), lang_ids.into_iter(), resource_ids)
}
/// Wiring for hooking up the synchronous bundle generation to the
/// [BundleGenerator] trait.
pub fn generate_bundles_sync(
&self,
locales: std::vec::IntoIter {
GenerateBundlesSync::new(self.clone(), locales, resource_ids)
}
}
enum State {
Empty,
Locale(LanguageIdentifier),
Solver {
locale: LanguageIdentifier,
solver: SerialProblemSolver,
},
}
impl Default for State {
fn default() -> Self {
Self::Empty
}
}
impl State {
fn get_locale(&self) -> &LanguageIdentifier {
match self {
Self::Locale(locale) => locale,
Self::Solver { locale, .. } => locale,
Self::Empty => unreachable!("Attempting to get a locale for an empty state."),
}
}
fn take_solver(&mut self) -> SerialProblemSolver {
replace_with::replace_with_or_default_and_return(self, |self_| match self_ {
Self::Solver { locale, solver } => (solver, Self::Locale(locale)),
_ => unreachable!("Attempting to take a solver in an invalid state."),
})
}
fn put_back_solver(&mut self, solver: SerialProblemSolver) {
replace_with::replace_with_or_default(self, |self_| match self_ {
Self::Locale(locale) => Self::Solver { locale, solver },
_ => unreachable!("Attempting to put back a solver in an invalid state."),
})
}
}
pub struct GenerateBundlesSync {
reg: L10nRegistry ,
locales: std::vec::IntoIter GenerateBundlesSync {
fn new(
reg: L10nRegistry ,
locales: std::vec::IntoIter SyncTester for GenerateBundlesSync {
fn test_sync(&self, res_idx: usize, source_idx: usize) -> bool {
let locale = self.state.get_locale();
let resource_id = &self.resource_ids[res_idx];
!self
.reg
.try_borrow_metasources()
.expect("Unable to get the MetaSources.")
.filesource(self.current_metasource, source_idx)
.fetch_file_sync(locale, resource_id, /* overload */ true)
.is_required_and_missing()
}
}
impl BundleIterator for GenerateBundlesSync
where
P: ErrorReporter,
{
fn prefetch_sync(&mut self) {
if let State::Solver { .. } = self.state {
let mut solver = self.state.take_solver();
if let Err(idx) = solver.try_next(self, true) {
self.reg
.shared
.provider
.report_errors(vec![L10nRegistryError::MissingResource {
locale: self.state.get_locale().clone(),
resource_id: self.resource_ids[idx].clone(),
}]);
}
self.state.put_back_solver(solver);
return;
}
if let Some(locale) = self.locales.next() {
let mut solver = SerialProblemSolver::new(
self.resource_ids.len(),
self.reg
.try_borrow_metasources()
.expect("Unable to get the MetaSources.")
.get(self.current_metasource)
.len(),
);
self.state = State::Locale(locale.clone());
if let Err(idx) = solver.try_next(self, true) {
self.reg
.shared
.provider
.report_errors(vec![L10nRegistryError::MissingResource {
locale,
resource_id: self.resource_ids[idx].clone(),
}]);
}
self.state.put_back_solver(solver);
}
}
}
impl Iterator for GenerateBundlesSync
where
P: ErrorReporter,
B: BundleAdapter,
{
type Item = Result