Skip to main content

everything_ipc/
search.rs

1/*!
2Search text generating utilities.
3*/
4use std::{
5    borrow::Cow,
6    ffi::{OsStr, OsString},
7    fs, io,
8    path::{Path, PathBuf},
9};
10
11/// Canonicalize a path into the form can be recognized by Everything.
12#[doc(alias = "realpath_ev")]
13pub fn canonicalize_path_ev<'a>(path: &'a Path) -> io::Result<PathBuf> {
14    let path = fs::canonicalize(path)?;
15    let path = normalize_path_ev(&path).into_owned();
16    Ok(path)
17}
18
19/// Convert a path into the form can be recognized by Everything.
20///
21/// Basically removes the verbatim prefix, e.g. `\\?\C:\Windows` -> `C:\Windows`.
22/// Note that this does not resolve symbolic links and junctions,
23/// for which you can call [`canonicalize_path_ev()`].
24///
25/// https://github.com/dylni/normpath can also be used, but a bit overkill.
26pub fn normalize_path_ev<'a>(path: &'a Path) -> Cow<'a, Path> {
27    let bytes = path.as_os_str().as_encoded_bytes();
28    if let Some(bytes) = bytes.strip_prefix(br"\\?\") {
29        // `\\?\UNC\server\share` -> `\\server\share`
30        if let Some(bytes) = bytes.strip_prefix(b"UNC") {
31            let s = unsafe { OsStr::from_encoded_bytes_unchecked(bytes) };
32            let mut buf = OsString::with_capacity(1 + s.len());
33            buf.push(OsStr::new("\\"));
34            buf.push(s);
35            return Cow::Owned(PathBuf::from(buf));
36        }
37
38        // `\\?\C:` -> `C:`
39        // Ignore `\\?\cat_pics`
40        let s = unsafe { OsStr::from_encoded_bytes_unchecked(bytes) };
41        return Cow::Borrowed(Path::new(s));
42    }
43    Cow::Borrowed(path)
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn normalize_path_ev_verbatim_disk() {
52        // Verbatim disk path: \\?\C:\foo -> C:\foo
53        let path = Path::new(r"\\?\C:\Windows");
54        let result = normalize_path_ev(path);
55        assert_eq!(result, Path::new(r"C:\Windows"));
56    }
57
58    #[test]
59    fn normalize_path_ev_regular_disk() {
60        // Regular disk path returns as-is (not verbatim)
61        let path = Path::new(r"C:\Windows");
62        let result = normalize_path_ev(path);
63        assert_eq!(result, Path::new(r"C:\Windows"));
64    }
65
66    #[test]
67    fn normalize_path_ev_verbatim_unc() {
68        // Verbatim UNC path: \\?\UNC\server\share -> \\server\share
69        let path = Path::new(r"\\?\UNC\server\share");
70        let result = normalize_path_ev(path);
71        assert_eq!(result, Path::new(r"\\server\share"));
72    }
73
74    #[test]
75    fn normalize_path_ev_relative() {
76        // Relative paths return as-is
77        let path = Path::new("foo/bar");
78        let result = normalize_path_ev(path);
79        assert_eq!(result, Path::new("foo/bar"));
80    }
81
82    #[test]
83    fn normalize_path_ev_root_only() {
84        // Verbatim disk path to root
85        let path = Path::new(r"\\?\C:\");
86        let result = normalize_path_ev(path);
87        assert_eq!(result, Path::new(r"C:\"));
88    }
89}