Skip to main content

miden_debug_engine/
source_path.rs

1use miden_debug_types::Uri;
2
3/// Converts a source URI or path into a stable form for loading and comparison.
4pub fn normalize_source_path(path: &str) -> String {
5    let path = path.trim();
6    let path = Uri::new(path)
7        .to_path()
8        .map(|path| path.to_string_lossy().into_owned())
9        .unwrap_or_else(|| path.to_owned());
10    let mut path = path.replace('\\', "/");
11    if path
12        .as_bytes()
13        .get(0..2)
14        .is_some_and(|bytes| bytes[0].is_ascii_alphabetic() && bytes[1] == b':')
15    {
16        path.replace_range(..1, &path[..1].to_ascii_lowercase());
17    }
18
19    let is_absolute = path.starts_with('/');
20    let mut parts = Vec::new();
21    for part in path.split('/') {
22        match part {
23            "" | "." => {}
24            ".." => {
25                if parts.last().is_some_and(|last| *last != "..") {
26                    parts.pop();
27                } else {
28                    parts.push(part);
29                }
30            }
31            _ => parts.push(part),
32        }
33    }
34
35    let normalized = parts.join("/");
36    if is_absolute && !normalized.is_empty() {
37        format!("/{normalized}")
38    } else {
39        normalized
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::normalize_source_path;
46
47    #[test]
48    fn normalizes_file_uris_and_windows_drive_letters() {
49        assert_eq!(
50            normalize_source_path("file:///C:/Users/me/program.masm"),
51            "c:/Users/me/program.masm"
52        );
53        assert_eq!(
54            normalize_source_path("file:///c:/Users/me/program.masm"),
55            "c:/Users/me/program.masm"
56        );
57        assert_eq!(
58            normalize_source_path("file://localhost/C:/Users/me/program.masm"),
59            "c:/Users/me/program.masm"
60        );
61        assert_eq!(
62            normalize_source_path("C:\\Users\\me\\program.masm"),
63            "c:/Users/me/program.masm"
64        );
65    }
66
67    #[test]
68    fn normalizes_path_components() {
69        assert_eq!(
70            normalize_source_path("/home/me/./src/../program.masm"),
71            "/home/me/program.masm"
72        );
73        assert_eq!(
74            normalize_source_path("relative/./src/../program.masm"),
75            "relative/program.masm"
76        );
77    }
78}