glossa_shared/
load_bincode.rs

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