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 tap::Pipe;
12
13use crate::{
14 decode::file::{decode_file_to_maps, decode_single_file_to_flatten_map},
15 type_aliases::L10nMaps,
16};
17
18pub fn list_bincode_files(bincode_dir: Option<&Path>) -> Option<Vec<PathBuf>> {
22 bincode_dir?
23 .read_dir()
24 .ok()?
25 .flatten()
26 .map(|x| x.path())
27 .filter(|x| !x.is_dir())
28 .collect::<Vec<_>>()
29 .pipe(|x| (!x.is_empty()).then_some(x))
30}
31
32pub fn list_static_bincode_files(
33 bincode_dir: Option<&Path>,
34) -> Option<&'static [PathBuf]> {
35 static V: OnceLock<Option<Vec<PathBuf>>> = OnceLock::new();
36 V.get_or_init(|| list_bincode_files(bincode_dir))
37 .as_deref()
38}
39
40pub fn try_load_files<P: AsRef<Path>>(files: &[P]) -> ResolverResult<L10nMaps> {
41 let all = OsStr::new("all");
42 log::debug!("Loading bincode data ...");
43
44 let iter = files.iter().map(AsRef::as_ref);
45
46 match iter
47 .clone()
48 .find(|x| x.file_stem() == Some(all))
49 {
50 Some(p) => {
51 debug!("load: all.bincode");
52 decode_file_to_maps(p)
53 }
54 _ => iter
55 .filter_map(|x| {
56 decode_single_file_to_flatten_map(x)
57 .ok()
58 .and_then(|data| {
59 x.file_stem()
60 .inspect(|s| debug!("file-stem: {s:?}"))
61 .and_then(|s| s.to_str())
62 .map(|lang| (lang.to_compact_string(), data))
63 })
64 })
65 .collect::<L10nMaps>()
66 .pipe(Ok),
67 }
68}
69
70pub fn merge_locales(
71 lhs: Option<&L10nMaps>,
72 rhs: Option<&[LangID]>,
73) -> Option<Box<[LangID]>> {
74 let builtin = rhs
75 .into_iter()
76 .flatten()
77 .cloned();
78
79 let locales = lhs?
80 .keys()
81 .inspect(|x| debug!("language: {x}"))
82 .filter_map(|x| x.parse::<LangID>().ok())
83 .chain(builtin)
84 .collect::<ahash::HashSet<_>>() .into_iter()
86 .collect();
87
88 Some(locales)
89}