flams_math_archives/
mathhub.rs1use crate::{Archive, utils::path_ext::PathExt};
2use std::path::{Path, PathBuf};
3
4#[allow(clippy::doc_markdown)]
5#[must_use]
11pub fn default_mathhubs() -> Vec<PathBuf> {
12 if let Ok(f) = std::env::var("MATHHUB") {
13 return f.split(',').map(|s| PathBuf::from(s.trim())).collect();
14 }
15 if let Some(d) = simple_home_dir::home_dir() {
16 let p = d.join(".mathhub").join("mathhub.path");
17 if let Ok(f) = std::fs::read_to_string(p) {
18 return f
19 .split('\n')
20 .map(|s: &str| PathBuf::from(s.trim()))
21 .collect();
22 }
23 return vec![d.join("MathHub")];
24 }
25 panic!(
26 "No MathHub directory found and default ~/MathHub not accessible!\n\
27Please set the MATHHUB environment variable or create a file ~/.mathhub/mathhub.path containing \
28the path to the MathHub directory."
29 )
30}
31
32static MH: std::sync::OnceLock<&'static [&'static Path]> = std::sync::OnceLock::new();
33
34pub fn mathhubs() -> &'static [&'static Path] {
37 MH.get_or_init(|| {
38 &*Box::leak(
39 default_mathhubs()
40 .into_iter()
41 .map(|p| &*Box::leak(p.into_boxed_path()))
42 .collect::<Vec<_>>()
43 .into_boxed_slice(),
44 )
45 })
46}
47
48#[allow(clippy::result_unit_err)]
54pub fn set_mathhubs(paths: impl IntoIterator<Item = PathBuf>) -> Result<(), ()> {
55 if MH.get().is_some() {
56 return Err(());
57 }
58 MH.get_or_init(|| {
59 &*Box::leak(
60 paths
61 .into_iter()
62 .map(|p| &*Box::leak(p.into_boxed_path()))
63 .collect::<Vec<_>>()
64 .into_boxed_slice(),
65 )
66 });
67 Ok(())
68}
69
70pub static MATHHUBS: std::sync::LazyLock<&'static [&'static Path]> = std::sync::LazyLock::new(
71 || {
72 if let Ok(f) = std::env::var("MATHHUB") {
73 return Box::leak(
74 f.split(',')
75 .map(|s| &*PathBuf::from(s.trim()).leak())
76 .collect::<Box<[_]>>(),
77 );
78 }
79 if let Some(d) = simple_home_dir::home_dir() {
80 let p = d.join(".mathhub").join("mathhub.path");
81 if let Ok(f) = std::fs::read_to_string(p) {
82 return Box::leak(
83 f.split('\n')
84 .map(|s| &*PathBuf::from(s.trim()).leak())
85 .collect::<Box<[_]>>(),
86 );
87 }
88 return Box::leak(Box::new([&*d.join("MathHub").leak()]));
89 }
90 panic!(
91 "No MathHub directory found and default ~/MathHub not accessible!\n\
92 Please set the MATHHUB environment variable or create a file ~/.mathhub/mathhub.path containing \
93 the path to the MathHub directory."
94 )
95 },
96);
97
98pub fn load_all_archives() -> impl rayon::iter::ParallelIterator<Item = Archive> {
99 use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
101 use spliter::ParallelSpliterator;
102 crate::mathhub::MATHHUBS.par_iter().flat_map(|p| {
103 crate::archive_iter::ManifestIterator::new(p)
104 .par_split()
105 .into_par_iter()
106 .map(move |r| (p, r))
107 .filter_map(|(mh, p)| {
108 let parent = unsafe { p.parent().unwrap_unchecked().parent().unwrap_unchecked() };
110
111 let rel_path = parent.relative_to(mh)?;
112 match crate::manifest::parse_manifest(&p, rel_path) {
113 Ok(r) => Some(r),
114 Err(e) => {
115 tracing::warn!("{e} in {rel_path}");
116 None
117 }
118 }
119 })
120 .map(|a| {
121 if let Archive::Local(a) = &a {
122 a.update_sources();
123 }
124 a
125 })
126 })
127 }
143
144#[test]
145fn all_archives() {
146 use crate::source_format;
147 use ftml_ontology::utils::time::measure;
148 use rayon::iter::*;
149 source_format!(STEX {
150 name: "stex",
151 file_extensions: &["tex", "ltx"],
152 description: "foo",
153 dependencies: |_| Vec::new(),
154 targets: &[]
155 });
156
157 let _ = tracing_subscriber::fmt().try_init();
158 let (i, t) = measure(|| load_all_archives().count());
159 tracing::info!("Loaded {i} archives in {t}");
160 tracing::info!("Memory: {}", ftml_uris::get_memory_state());
161}