Skip to content

Commit 71aee0b

Browse files
committed
Attempts to support UNC paths
1 parent ccf6c78 commit 71aee0b

File tree

1 file changed

+69
-3
lines changed

1 file changed

+69
-3
lines changed

src/util.rs

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use serde::{Deserialize, Deserializer, de::Error};
33
use std::borrow::Cow;
44

55
use std::path::{MAIN_SEPARATOR_STR, Path, PathBuf};
6+
#[cfg(windows)]
7+
use std::sync::LazyLock;
68

79
#[derive(Debug, Default, Clone)]
810
pub struct Trie<T> {
@@ -32,11 +34,62 @@ impl<T> Trie<T> {
3234
}
3335
}
3436

37+
#[cfg(windows)]
38+
static WINDOWS_PATH_REGEXP: LazyLock<Regex> =
39+
LazyLock::new(|| Regex::new(r"^([a-zA-Z]:.*)$").unwrap());
40+
#[cfg(windows)]
41+
static UNC_WINDOWS_PATH_REGEXP: LazyLock<Regex> =
42+
LazyLock::new(|| Regex::new(r"^[\/\\][\/\\](\.[\/\\])?(.*)$").unwrap());
43+
#[cfg(windows)]
44+
static PORTABLE_PATH_REGEXP: LazyLock<Regex> =
45+
LazyLock::new(|| Regex::new(r"^\/([a-zA-Z]:.*)$").unwrap());
46+
#[cfg(windows)]
47+
static UNC_PORTABLE_PATH_REGEXP: LazyLock<Regex> =
48+
LazyLock::new(|| Regex::new(r"^\/unc\/(\.dot\/)?(.*)$").unwrap());
49+
50+
fn from_portable_path<'a>(str: &'a str) -> Cow<'a, str> {
51+
#[cfg(windows)]
52+
{
53+
if let Ok(Some(caps)) = PORTABLE_PATH_REGEXP.captures(str) {
54+
return Cow::Borrowed(caps.get(1).unwrap().as_str());
55+
}
56+
57+
if let Ok(Some(caps)) = UNC_PORTABLE_PATH_REGEXP.captures(str) {
58+
if caps.get(1).is_some() {
59+
return Cow::Owned(format!("\\\\.\\{}", caps.get(2).unwrap().as_str()));
60+
} else {
61+
return Cow::Owned(format!("\\\\{}", caps.get(2).unwrap().as_str()));
62+
}
63+
}
64+
}
65+
66+
Cow::Borrowed(str)
67+
}
68+
69+
fn to_portable_path<'a>(str: &'a str) -> Cow<'a, str> {
70+
#[cfg(windows)]
71+
{
72+
if let Ok(Some(caps)) = WINDOWS_PATH_REGEXP.captures(str) {
73+
return Cow::Owned(format!("/{}", caps.get(1).unwrap().as_str()));
74+
}
75+
76+
if let Ok(Some(caps)) = UNC_WINDOWS_PATH_REGEXP.captures(str) {
77+
if caps.get(1).is_some() {
78+
return Cow::Owned(format!("/unc/.dot/{}", caps.get(2).unwrap().as_str()));
79+
} else {
80+
return Cow::Owned(format!("/unc/{}", caps.get(2).unwrap().as_str()));
81+
}
82+
}
83+
}
84+
85+
Cow::Borrowed(str)
86+
}
87+
3588
pub fn normalize_path<P: AsRef<str>>(original: P) -> String {
36-
let original_str = original.as_ref();
89+
let original_str = to_portable_path(original.as_ref());
3790

3891
let check_str_root = original_str.strip_prefix("/");
39-
let str_minus_root = check_str_root.unwrap_or(original_str);
92+
let str_minus_root = check_str_root.unwrap_or(original_str.as_ref());
4093

4194
let components = str_minus_root.split(&['/', '\\'][..]);
4295

@@ -86,7 +139,7 @@ pub fn normalize_path<P: AsRef<str>>(original: P) -> String {
86139
str.push('/');
87140
}
88141

89-
str
142+
from_portable_path(&str).into_owned()
90143
}
91144

92145
#[cfg(test)]
@@ -106,6 +159,7 @@ mod tests {
106159
assert_eq!(normalize_path("foo/bar/.."), "foo");
107160
assert_eq!(normalize_path("foo/../../bar"), "../bar");
108161
assert_eq!(normalize_path("../foo/../../bar"), "../../bar");
162+
assert_eq!(normalize_path("foo/../../bar"), "../bar");
109163
assert_eq!(normalize_path("./foo"), "foo");
110164
assert_eq!(normalize_path("../foo"), "../foo");
111165
assert_eq!(normalize_path("../D:/foo"), "../D:/foo");
@@ -114,6 +168,18 @@ mod tests {
114168
assert_eq!(normalize_path("/../foo/bar"), "/foo/bar");
115169
assert_eq!(normalize_path("/../foo/bar//"), "/foo/bar/");
116170
assert_eq!(normalize_path("/foo/bar/"), "/foo/bar/");
171+
172+
#[cfg(windows)]
173+
assert_eq!(normalize_path("D:\\foo\\..\\bar"), "D:/bar");
174+
#[cfg(windows)]
175+
assert_eq!(normalize_path("D:\\foo\\..\\..\\C:\\bar\\test"), "C:/bar/test");
176+
#[cfg(windows)]
177+
assert_eq!(normalize_path("\\\\server-name\\foo\\..\\bar"), "\\\\server-name/bar");
178+
#[cfg(windows)]
179+
assert_eq!(
180+
normalize_path("\\\\server-name\\foo\\..\\..\\..\\C:\\bar\\test"),
181+
"C:/bar/test"
182+
);
117183
}
118184
}
119185

0 commit comments

Comments
 (0)