runmat_runtime/builtins/common/
path_state.rs1use once_cell::sync::Lazy;
11use std::env;
12use std::sync::RwLock;
13
14pub const PATH_LIST_SEPARATOR: char = if cfg!(windows) { ';' } else { ':' };
16
17#[derive(Debug, Clone)]
18struct PathState {
19 current: String,
21}
22
23impl PathState {
24 fn initialise() -> Self {
25 Self {
26 current: initial_path_string(),
27 }
28 }
29}
30
31fn initial_path_string() -> String {
32 let mut parts = Vec::<String>::new();
33 for var in ["RUNMAT_PATH", "MATLABPATH"] {
34 if let Ok(value) = env::var(var) {
35 parts.extend(
36 value
37 .split(PATH_LIST_SEPARATOR)
38 .map(|part| part.trim())
39 .filter(|part| !part.is_empty())
40 .map(|part| part.to_string()),
41 );
42 }
43 }
44 join_parts(&parts)
45}
46
47fn join_parts(parts: &[String]) -> String {
48 let mut joined = String::new();
49 for (idx, part) in parts.iter().enumerate() {
50 if idx > 0 {
51 joined.push(PATH_LIST_SEPARATOR);
52 }
53 joined.push_str(part);
54 }
55 joined
56}
57
58static PATH_STATE: Lazy<RwLock<PathState>> = Lazy::new(|| RwLock::new(PathState::initialise()));
59
60pub fn current_path_string() -> String {
63 PATH_STATE
64 .read()
65 .map(|guard| guard.current.clone())
66 .unwrap_or_else(|poison| poison.into_inner().current.clone())
67}
68
69pub fn set_path_string(new_path: &str) {
73 if new_path.is_empty() {
74 env::remove_var("RUNMAT_PATH");
75 } else {
76 env::set_var("RUNMAT_PATH", new_path);
77 }
78
79 let mut guard = PATH_STATE
80 .write()
81 .unwrap_or_else(|poison| poison.into_inner());
82 guard.current = new_path.to_string();
83}
84
85pub fn current_path_segments() -> Vec<String> {
88 let path = current_path_string();
89 split_segments(&path)
90}
91
92fn split_segments(path: &str) -> Vec<String> {
93 path.split(PATH_LIST_SEPARATOR)
94 .map(|part| part.trim())
95 .filter(|part| !part.is_empty())
96 .map(|part| part.to_string())
97 .collect()
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn join_and_split_round_trip() {
106 let parts = vec!["/tmp/a".to_string(), "/tmp/b".to_string()];
107 let joined = join_parts(&parts);
108 assert_eq!(split_segments(&joined), parts);
109 }
110}