Skip to main content

miden_debug_engine/
source_path.rs

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