Skip to content

Commit d46a428

Browse files
committed
clean up
1 parent e7cfc08 commit d46a428

File tree

4 files changed

+75
-80
lines changed

4 files changed

+75
-80
lines changed

src/file_system.rs

Lines changed: 7 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -155,53 +155,19 @@ impl FileSystemOs {
155155
/// See [std::fs::read_link]
156156
#[inline]
157157
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
158-
let target = fs::read_link(path)?;
158+
let path = fs::read_link(path)?;
159159
cfg_if! {
160-
if #[cfg(windows)] {
161-
Ok(match Self::try_strip_windows_prefix(&target) {
162-
Some(path) => path,
160+
if #[cfg(target_os = "windows")] {
161+
match crate::windows::try_strip_windows_prefix(path) {
163162
// We won't follow the link if we cannot represent its target properly.
164-
None => target,
165-
})
163+
Ok(p) | Err(crate::ResolveError::PathNotSupported(p)) => Ok(p),
164+
_ => unreachable!(),
165+
}
166166
} else {
167-
Ok(target.to_path_buf())
167+
Ok(path)
168168
}
169169
}
170170
}
171-
172-
/// When applicable, converts a [DOS device path](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths)
173-
/// to a normal path (usually, "Traditional DOS paths" or "UNC path") that can be consumed by the `import`/`require` syntax of Node.js.
174-
/// Returns `None` if the path cannot be represented as a normal path.
175-
pub fn try_strip_windows_prefix<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
176-
// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
177-
let path_bytes = path.as_ref().as_os_str().as_encoded_bytes();
178-
179-
let path = if let Some(p) =
180-
path_bytes.strip_prefix(br"\\?\UNC\").or(path_bytes.strip_prefix(br"\\.\UNC\"))
181-
{
182-
// UNC paths
183-
unsafe {
184-
PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(&[br"\\", p].concat()))
185-
}
186-
} else if let Some(p) =
187-
path_bytes.strip_prefix(br"\\?\").or(path_bytes.strip_prefix(br"\\.\"))
188-
{
189-
// Assuming traditional DOS path "\\?\C:\"
190-
if p[1] != b':' {
191-
// E.g.,
192-
// \\?\Volume{b75e2c83-0000-0000-0000-602f00000000}
193-
// \\?\BootPartition\
194-
// It seems nodejs does not support DOS device paths with Volume GUIDs.
195-
// This can happen if the path points to a Mounted Volume without a drive letter.
196-
return None;
197-
}
198-
unsafe { PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(p)) }
199-
} else {
200-
path.as_ref().to_path_buf()
201-
};
202-
203-
Some(path)
204-
}
205171
}
206172

207173
impl FileSystem for FileSystemOs {
@@ -267,37 +233,3 @@ fn metadata() {
267233
);
268234
let _ = meta;
269235
}
270-
271-
#[test]
272-
fn test_strip_windows_prefix() {
273-
assert_eq!(
274-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(
275-
r"\\?\C:\Users\user\Documents\file.txt"
276-
)),
277-
Some(PathBuf::from(r"C:\Users\user\Documents\file.txt"))
278-
);
279-
280-
assert_eq!(
281-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(
282-
r"\\.\C:\Users\user\Documents\file.txt"
283-
)),
284-
Some(PathBuf::from(r"C:\Users\user\Documents\file.txt"))
285-
);
286-
287-
assert_eq!(
288-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(r"\\?\UNC\server\share\file.txt")),
289-
Some(PathBuf::from(r"\\server\share\file.txt"))
290-
);
291-
292-
assert_eq!(
293-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(
294-
r"\\?\Volume{c8ec34d8-3ba6-45c3-9b9d-3e4148e12d00}\file.txt"
295-
)),
296-
None
297-
);
298-
299-
assert_eq!(
300-
FileSystemOs::try_strip_windows_prefix(PathBuf::from(r"\\?\BootPartition\file.txt")),
301-
None
302-
);
303-
}

src/fs_cache.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,8 @@ impl<Fs: FileSystem> Cache for FsCache<Fs> {
7979
let cached_path = self.canonicalize_impl(path)?;
8080
let path = cached_path.to_path_buf();
8181
cfg_if! {
82-
if #[cfg(windows)] {
83-
match crate::FileSystemOs::try_strip_windows_prefix(&path) {
84-
Some(path) => Ok(path),
85-
None => Err(ResolveError::PathNotSupported(path)),
86-
}
82+
if #[cfg(target_os = "windows")] {
83+
crate::windows::try_strip_windows_prefix(path)
8784
} else {
8885
Ok(path)
8986
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ mod specifier;
6565
mod tsconfig;
6666
#[cfg(feature = "fs_cache")]
6767
mod tsconfig_serde;
68+
#[cfg(target_os = "windows")]
69+
mod windows;
6870

6971
#[cfg(test)]
7072
mod tests;

src/windows.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use std::path::PathBuf;
2+
3+
use crate::ResolveError;
4+
5+
/// When applicable, converts a [DOS device path](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths)
6+
/// to a normal path (usually, "Traditional DOS paths" or "UNC path") that can be consumed by the `import`/`require` syntax of Node.js.
7+
/// Returns `None` if the path cannot be represented as a normal path.
8+
pub fn try_strip_windows_prefix(path: PathBuf) -> Result<PathBuf, ResolveError> {
9+
// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
10+
let path_bytes = path.as_os_str().as_encoded_bytes();
11+
12+
let path = if let Some(p) =
13+
path_bytes.strip_prefix(br"\\?\UNC\").or_else(|| path_bytes.strip_prefix(br"\\.\UNC\"))
14+
{
15+
// UNC paths
16+
// SAFETY:
17+
unsafe {
18+
PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(&[br"\\", p].concat()))
19+
}
20+
} else if let Some(p) =
21+
path_bytes.strip_prefix(br"\\?\").or_else(|| path_bytes.strip_prefix(br"\\.\"))
22+
{
23+
// Assuming traditional DOS path "\\?\C:\"
24+
if p[1] != b':' {
25+
// E.g.,
26+
// \\?\Volume{b75e2c83-0000-0000-0000-602f00000000}
27+
// \\?\BootPartition\
28+
// It seems nodejs does not support DOS device paths with Volume GUIDs.
29+
// This can happen if the path points to a Mounted Volume without a drive letter.
30+
return Err(ResolveError::PathNotSupported(path));
31+
}
32+
// SAFETY:
33+
unsafe { PathBuf::from(std::ffi::OsStr::from_encoded_bytes_unchecked(p)) }
34+
} else {
35+
path
36+
};
37+
38+
Ok(path)
39+
}
40+
41+
#[test]
42+
fn test_try_strip_windows_prefix() {
43+
let pass = [
44+
(r"\\?\C:\Users\user\Documents\file1.txt", r"C:\Users\user\Documents\file1.txt"),
45+
(r"\\.\C:\Users\user\Documents\file2.txt", r"C:\Users\user\Documents\file2.txt"),
46+
(r"\\?\UNC\server\share\file3.txt", r"\\server\share\file3.txt"),
47+
];
48+
49+
for (path, expected) in pass {
50+
assert_eq!(try_strip_windows_prefix(PathBuf::from(path)), Ok(PathBuf::from(expected)));
51+
}
52+
53+
let fail = [
54+
r"\\?\Volume{c8ec34d8-3ba6-45c3-9b9d-3e4148e12d00}\file4.txt",
55+
r"\\?\BootPartition\file4.txt",
56+
];
57+
58+
for path in fail {
59+
assert_eq!(
60+
try_strip_windows_prefix(PathBuf::from(path)),
61+
Err(crate::ResolveError::PathNotSupported(PathBuf::from(path)))
62+
);
63+
}
64+
}

0 commit comments

Comments
 (0)