glossa_shared/
load_bincode.rs1use std::{
2 ffi::OsStr,
3 path::{Path, PathBuf},
4 sync::OnceLock,
5};
6
7use compact_str::ToCompactString;
8use glossa_dsl::error::ResolverResult;
9use lang_id::LangID;
10use log::debug;
11use rayon::iter::{IntoParallelRefIterator, ParallelBridge, ParallelIterator};
12use tap::Pipe;
13
14use crate::{
15 decode::file::{
16 decode_file_to_dsl_maps, decode_file_to_maps, decode_single_file_to_dsl_map,
17 decode_single_file_to_flatten_map,
18 },
19 type_aliases::{DSLMaps, L10nMaps},
20};
21
22pub fn list_bincode_files(bincode_dir: Option<&Path>) -> Option<Vec<PathBuf>> {
26 bincode_dir?
27 .read_dir()
28 .ok()?
29 .par_bridge()
30 .flatten()
31 .map(|x| x.path())
32 .filter(|x| !x.is_dir())
33 .collect::<Vec<_>>()
34 .pipe(|x| (!x.is_empty()).then_some(x))
35}
36
37pub fn list_static_bincode_files(
38 bincode_dir: Option<&Path>,
39) -> Option<&'static [PathBuf]> {
40 static V: OnceLock<Option<Vec<PathBuf>>> = OnceLock::new();
41 V.get_or_init(|| list_bincode_files(bincode_dir))
42 .as_deref()
43}
44
45pub fn try_load_files<P: AsRef<Path>>(files: &[P]) -> ResolverResult<L10nMaps> {
46 let all = OsStr::new("all");
47 log::debug!("Loading bincode data ...");
48
49 let iter = files.iter().map(AsRef::as_ref);
50
51 match iter
52 .clone()
53 .find(|x| x.file_stem() == Some(all))
54 {
55 Some(p) => {
56 debug!("load: all.bincode");
57 decode_file_to_maps(p)
58 }
59 _ => {
60 iter
62 .collect::<Vec<_>>()
63 .par_iter()
64 .filter_map(|file| {
65 decode_single_file_to_flatten_map(file)
66 .ok()
67 .and_then(|data| {
68 file
69 .file_stem()
70 .inspect(|s| debug!("file-stem: {s:?}"))
71 .and_then(|s| s.to_str())
72 .map(|lang| (lang.to_compact_string(), data))
73 })
74 })
75 .collect::<L10nMaps>()
76 .pipe(Ok)
77 }
78 }
79}
80
81pub fn try_load_dsl_files<P: AsRef<Path>>(files: &[P]) -> ResolverResult<DSLMaps> {
82 let all = OsStr::new("all");
83 log::debug!("Loading bincode data ...");
84
85 let iter = files.iter().map(AsRef::as_ref);
86
87 match iter
88 .clone()
89 .find(|x| x.file_stem() == Some(all))
90 {
91 Some(p) => {
92 debug!("load DSL: all.bincode");
93 decode_file_to_dsl_maps(p)
94 }
95 _ => iter
96 .collect::<Vec<_>>()
97 .par_iter()
98 .filter_map(|file| {
100 decode_single_file_to_dsl_map(file)
101 .ok()
102 .and_then(|data| {
103 file
104 .file_stem()
105 .inspect(|s| debug!("file-stem: {s:?}"))
106 .and_then(|s| s.to_str())
107 .map(|lang| (lang.to_compact_string(), data))
108 })
109 })
110 .collect::<DSLMaps>()
111 .pipe(Ok),
112 }
113}
114
115pub fn merge_locales(
116 lhs: Option<&L10nMaps>,
117 rhs: Option<&[LangID]>,
118) -> Option<Box<[LangID]>> {
119 let builtin = rhs
120 .into_iter()
121 .flatten()
122 .cloned();
123
124 let locales = lhs?
125 .keys()
126 .inspect(|x| debug!("language: {x}"))
127 .filter_map(|x| x.parse::<LangID>().ok())
128 .chain(builtin)
129 .collect::<ahash::HashSet<_>>() .into_iter()
131 .collect();
132
133 Some(locales)
134}