Skip to main content

luaur_cli_lib/functions/
normalize_path.rs

1use crate::functions::is_absolute_path::is_absolute_path;
2use crate::functions::split_path::split_path;
3
4pub fn normalize_path(path: &str) -> alloc::string::String {
5    let components: alloc::vec::Vec<&str> = split_path(path);
6    let mut normalized_components: alloc::vec::Vec<&str> = alloc::vec::Vec::new();
7
8    let is_absolute = is_absolute_path(path);
9
10    // 1. Normalize path components
11    let start_index = if is_absolute { 1 } else { 0 };
12    for i in start_index..components.len() {
13        let component = components[i];
14        if component == ".." {
15            if normalized_components.is_empty() {
16                if !is_absolute {
17                    normalized_components.push("..");
18                }
19            } else if *normalized_components.last().unwrap() == ".." {
20                normalized_components.push("..");
21            } else {
22                normalized_components.pop();
23            }
24        } else if !component.is_empty() && component != "." {
25            normalized_components.push(component);
26        }
27    }
28
29    let mut normalized_path = alloc::string::String::new();
30
31    // 2. Add correct prefix to formatted path
32    if is_absolute {
33        // Mirror the C++ behavior: assumes path is absolute and components[0] exists.
34        normalized_path.push_str(components[0]);
35        normalized_path.push('/');
36    } else if normalized_components.is_empty() || normalized_components[0] != ".." {
37        normalized_path.push_str("./");
38    }
39
40    // 3. Join path components to form the normalized path
41    for (idx, component) in normalized_components.iter().enumerate() {
42        if idx != 0 {
43            normalized_path.push('/');
44        }
45        normalized_path.push_str(component);
46    }
47
48    let bytes = normalized_path.as_bytes();
49    if bytes.len() >= 2 && bytes[bytes.len() - 1] == b'.' && bytes[bytes.len() - 2] == b'.' {
50        normalized_path.push('/');
51    }
52
53    normalized_path
54}