glossa_codegen/
generator.rs1pub(crate) mod flattening;
2mod init_lazy_data;
3pub(crate) mod output_bincode;
4pub(crate) mod output_match;
5pub(crate) mod output_phf;
6use std::{io, path::PathBuf, sync::OnceLock};
7
8use getset::{Getters, MutGetters, WithSetters};
9use glossa_shared::{fmt_compact, tap::Pipe};
10pub use output_phf::to_lower_snake_case;
11
12use crate::{
13 L10nResources, MiniStr, Visibility,
14 generator::flattening::{L10nDSLMaps, L10nMaps},
15 internal_aliases::HighlightCfgMap,
16};
17
18#[derive(Getters, WithSetters, MutGetters, Debug, Clone)]
19#[getset(get = "pub with_prefix", set_with = "pub", get_mut = "pub with_prefix")]
20pub struct Generator<'h> {
21 #[getset(skip)]
22 #[getset(get = "pub")]
23 resources: Box<L10nResources>,
24
25 #[getset(get_mut)]
26 visibility: Visibility,
27
28 #[getset(skip)]
29 #[getset(get = "pub", get_mut = "pub")]
30 outdir: Option<PathBuf>,
31
32 bincode_suffix: MiniStr,
33 mod_prefix: MiniStr,
34
35 #[getset(skip)]
36 #[getset(get = "pub")]
37 highlight: Option<Box<HighlightCfgMap<'h>>>,
38
39 #[getset(skip)]
40 lazy_maps: Box<LazyMaps>,
42}
43
44#[cfg(feature = "highlight")]
45impl<'h> Generator<'h> {
46 pub fn with_highlight(mut self, highlight: HighlightCfgMap<'h>) -> Self {
47 self.highlight = Some(highlight.into());
48 self.clear_highlight_cache();
49 self
50 }
51
52 pub fn set_highlight(&mut self, highlight: Option<HighlightCfgMap<'h>>) {
53 self.highlight = highlight.map(|data| data.into());
54 self.clear_highlight_cache();
55 }
56 fn clear_highlight_cache(&mut self) {
57 self.lazy_maps.highlight.take();
58 self.lazy_maps.merged.take();
59 }
60}
61
62impl Generator<'_> {
63 pub fn with_outdir<P: Into<PathBuf>>(mut self, outdir: P) -> Self {
64 self.outdir = Some(outdir.into());
65 self
66 }
67}
68
69impl Generator<'_> {
70 pub fn with_resources(mut self, resources: L10nResources) -> Self {
97 self.resources = resources.into();
98 self.lazy_maps = Default::default();
99 self
100 }
101}
102
103#[derive(Default, Debug, Clone)]
104struct LazyMaps {
105 regular: OnceLock<L10nMaps>,
107
108 highlight: OnceLock<Option<L10nMaps>>,
110
111 dsl: OnceLock<L10nDSLMaps>,
113
114 merged: OnceLock<L10nMaps>,
116}
117
118impl Default for Generator<'_> {
119 fn default() -> Self {
130 Self {
131 bincode_suffix: MiniStr::const_new(".bincode"),
132 outdir: Default::default(),
133 resources: Default::default(),
134 mod_prefix: MiniStr::const_new("l10n_"),
137 visibility: Default::default(),
140 highlight: Default::default(),
142 lazy_maps: Default::default(),
143 }
144 }
145}
146
147#[derive(Debug, Clone, Copy)]
148pub enum MapType {
149 Regular,
150 Highlight,
151 RegularAndHighlight,
152 DSL,
153}
154
155impl core::str::FromStr for MapType {
156 type Err = io::Error;
157
158 fn from_str(s: &str) -> Result<Self, Self::Err> {
159 use MapType::*;
160 match s {
161 "regular" | "r" => Regular,
162 "highlight" | "h" => Highlight,
163 "dsl" | "tmpl" => DSL,
164 "regular-and-highlight" | "regularandhighlight" | "_" => RegularAndHighlight,
165 other => Err(io::Error::new(
166 io::ErrorKind::InvalidInput,
167 fmt_compact!(
168 r#"
169 Expected: "regular" | "highlight" | "dsl" | "_"
170 Actual: "{other}""#
171 ),
172 ))?,
173 }
174 .pipe(Ok)
175 }
176}
177
178impl MapType {
179 fn get_non_dsl_maps<'a>(
180 &self,
181 generator: &'a Generator<'a>,
182 ) -> io::Result<&'a L10nMaps> {
183 use MapType::*;
184 match self {
185 Regular => generator.get_or_init_maps(),
186 Highlight => generator
187 .get_or_init_highlight_maps()
188 .ok_or_else(|| io::Error::other("Failed to get highlight maps"))?,
189 RegularAndHighlight => generator.get_or_init_merged_maps(),
190 _ => return io::Error::other("DSL Maps are not supported.").pipe(Err),
191 }
192 .pipe(Ok)
193 }
194
195 #[must_use]
199 pub fn is_dsl(&self) -> bool {
200 matches!(self, Self::DSL)
201 }
202}
203
204impl Default for MapType {
205 fn default() -> Self {
206 Self::DSL
207 }
208}
209
210#[cfg(test)]
211pub(crate) mod dbg_generator {
212 use super::*;
213 use crate::resources::dbg_shared;
214
215 pub(crate) fn new_generator<'h>() -> Generator<'h> {
216 let data = dbg_shared::new_resources();
217 Generator::default()
218 .with_resources(data)
219 .with_outdir("tmp")
220 }
221
222 #[cfg(feature = "highlight")]
223 pub(crate) fn highlight_generator<'h>() -> Generator<'h> {
224 let hmap = crate::highlight::dbg_shared::new_highlight_map();
225 new_generator().with_highlight(hmap)
226 }
227
228 pub(crate) fn en_generator<'h>() -> Generator<'h> {
229 let data = dbg_shared::new_resources().with_include_languages(["en"]);
230 new_generator().with_resources(data)
231 }
232
233 pub(crate) fn en_gb_generator<'h>() -> Generator<'h> {
234 let data = dbg_shared::new_resources().with_include_languages(["en-GB"]);
235 new_generator().with_resources(data)
236 }
237
238 pub(crate) fn es_generator<'h>() -> Generator<'h> {
239 let data = dbg_shared::new_resources().with_include_languages(["es"]);
241 new_generator().with_resources(data)
242 }
243
244 pub(crate) fn de_en_fr_pt_zh_generator<'h>() -> Generator<'h> {
245 let data = dbg_shared::new_resources()
246 .with_include_languages([
247 "de", "zh", "pt", "fr", "en", "en-GB",
249 ])
250 .with_include_map_names(["yes-no"]);
251 new_generator().with_resources(data)
252 }
253}