pub(crate) mod flattening;
mod init_lazy_data;
pub(crate) mod locales;
mod router;
pub(crate) mod output_bincode;
pub(crate) mod output_match;
pub(crate) mod output_phf;
use std::{io, path::PathBuf, sync::OnceLock};
use getset::{Getters, MutGetters, WithSetters};
use glossa_shared::{fmt_compact, tap::Pipe};
pub use output_phf::to_lower_snake_case;
use crate::{
L10nResources, MiniStr, Visibility,
generator::flattening::{L10nDSLMaps, L10nMaps},
internal_aliases::HighlightCfgMap,
};
#[derive(Getters, WithSetters, MutGetters, Debug, Clone)]
#[getset(get = "pub with_prefix", set_with = "pub", get_mut = "pub with_prefix")]
pub struct Generator<'h> {
#[getset(skip)]
#[getset(get = "pub")]
resources: Box<L10nResources>,
#[getset(get_mut)]
visibility: Visibility,
mod_visibility: Visibility,
#[getset(skip)]
#[getset(get = "pub", get_mut = "pub")]
outdir: Option<PathBuf>,
bincode_suffix: MiniStr,
mod_prefix: MiniStr,
feature_prefix: MiniStr,
#[getset(skip)]
#[getset(get = "pub")]
highlight: Option<Box<HighlightCfgMap<'h>>>,
#[getset(skip)]
lazy_maps: Box<LazyMaps>,
}
#[cfg(feature = "highlight")]
impl<'h> Generator<'h> {
pub fn with_highlight(mut self, highlight: HighlightCfgMap<'h>) -> Self {
self.highlight = Some(highlight.into());
self.clear_highlight_cache();
self
}
pub fn set_highlight(&mut self, highlight: Option<HighlightCfgMap<'h>>) {
self.highlight = highlight.map(|data| data.into());
self.clear_highlight_cache();
}
fn clear_highlight_cache(&mut self) {
self.lazy_maps.highlight.take();
self.lazy_maps.merged.take();
}
}
impl Generator<'_> {
pub fn with_outdir<P: Into<PathBuf>>(mut self, outdir: P) -> Self {
self.outdir = Some(outdir.into());
self
}
}
impl Generator<'_> {
pub fn with_resources(mut self, resources: L10nResources) -> Self {
self.resources = resources.into();
self.lazy_maps = Default::default();
self
}
}
#[derive(Default, Debug, Clone)]
struct LazyMaps {
regular: OnceLock<L10nMaps>,
highlight: OnceLock<Option<L10nMaps>>,
dsl: OnceLock<L10nDSLMaps>,
merged: OnceLock<L10nMaps>,
}
impl Default for Generator<'_> {
fn default() -> Self {
Self {
bincode_suffix: MiniStr::const_new(".bincode"),
outdir: Default::default(),
resources: Default::default(),
mod_prefix: MiniStr::const_new("l10n_"),
feature_prefix: MiniStr::const_new("l10n-"),
visibility: Default::default(),
mod_visibility: Visibility::Private,
highlight: Default::default(),
lazy_maps: Default::default(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum MapType {
Regular,
Highlight,
RegularAndHighlight,
DSL,
}
impl core::str::FromStr for MapType {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use MapType::*;
match s {
"regular" | "r" => Regular,
"highlight" | "h" => Highlight,
"dsl" | "tmpl" => DSL,
"regular-and-highlight" | "regularandhighlight" | "_" => RegularAndHighlight,
other => Err(io::Error::new(
io::ErrorKind::InvalidInput,
fmt_compact!(
r#"
Expected: "regular" | "highlight" | "dsl" | "_"
Actual: "{other}""#
),
))?,
}
.pipe(Ok)
}
}
impl MapType {
pub fn get_non_dsl_maps<'a>(
&self,
generator: &'a Generator<'a>,
) -> io::Result<&'a L10nMaps> {
use MapType::*;
match self {
Regular => generator.get_or_init_maps(),
Highlight => generator
.get_or_init_highlight_maps()
.ok_or_else(|| io::Error::other("Failed to get highlight maps"))?,
RegularAndHighlight => generator.get_or_init_merged_maps(),
_ => return io::Error::other("DSL Maps are not supported.").pipe(Err),
}
.pipe(Ok)
}
#[cfg(feature = "ron")]
pub fn output_ron<'a>(
&self,
generator: &'a Generator<'a>,
) -> crate::AnyResult<String> {
use ron::ser::PrettyConfig;
let cfg = PrettyConfig::new()
.depth_limit(5)
.separate_tuple_members(false);
match self.is_dsl() {
true => ron::ser::to_string_pretty(generator.get_or_init_dsl_maps(), cfg)?,
_ => ron::ser::to_string_pretty(self.get_non_dsl_maps(generator)?, cfg)?,
}
.pipe(Ok)
}
#[must_use]
pub fn is_dsl(&self) -> bool {
matches!(self, Self::DSL)
}
}
impl Default for MapType {
fn default() -> Self {
Self::DSL
}
}
#[cfg(test)]
pub(crate) mod dbg_generator {
use super::*;
use crate::resources::dbg_shared;
pub(crate) fn new_generator<'h>() -> Generator<'h> {
let data = dbg_shared::new_resources();
Generator::default()
.with_resources(data)
.with_outdir("tmp")
}
#[cfg(feature = "highlight")]
pub(crate) fn highlight_generator<'h>() -> Generator<'h> {
let hmap = crate::highlight::dbg_shared::new_highlight_map();
new_generator().with_highlight(hmap)
}
pub(crate) fn en_generator<'h>() -> Generator<'h> {
let data = dbg_shared::new_resources().with_include_languages(["en"]);
new_generator().with_resources(data)
}
pub(crate) fn en_gb_generator<'h>() -> Generator<'h> {
let data = dbg_shared::new_resources().with_include_languages(["en-GB"]);
new_generator().with_resources(data)
}
pub(crate) fn es_generator<'h>() -> Generator<'h> {
let data = dbg_shared::new_resources().with_include_languages(["es"]);
new_generator().with_resources(data)
}
pub(crate) fn de_en_fr_pt_zh_generator<'h>() -> Generator<'h> {
let data = dbg_shared::new_resources()
.with_include_languages([
"de", "zh", "pt", "fr", "en", "en-GB",
])
.with_include_map_names(["yes-no"]);
new_generator().with_resources(data)
}
}