1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::ffi::{OsStr, OsString};
use std::path::Path;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum LookupError {
#[error("File system access error while scanning: {}", .0)]
ScanError(String),
#[error("Visual Studio User settings file parse error: {}", .0)]
ParseError(String),
#[error("Error trying to render a file path in readable form: {}", .0)]
PathConversionError(String),
#[error("Lookup context building error: {}", .0)]
ContextDeductionError(String),
#[error("Could not demangle symbol")]
DemanglingError(String),
#[error("OsString could not be converted into a string")]
OsStringConversionError(OsString),
#[error(transparent)]
VarError(#[from] std::env::VarError),
#[error(transparent)]
RegexError(#[from] regex::Error),
#[error(transparent)]
IOError(#[from] std::io::Error),
#[error(transparent)]
PEError(#[from] pelite::Error),
#[error(transparent)]
Utf8Error(#[from] std::str::Utf8Error),
#[error(transparent)]
InternalError(#[from] anyhow::Error),
}
pub fn decanonicalize(s: &str) -> String {
s.replacen(r"\\?\", "", 1)
}
pub fn readable_canonical_path<P: AsRef<Path>>(p: P) -> Result<String, LookupError> {
Ok(decanonicalize(std::fs::canonicalize(&p)?.to_str().ok_or(
LookupError::PathConversionError(format!(
"Can't compute canonic path for {:?}",
p.as_ref()
)),
)?))
}
pub fn path_to_string<P: AsRef<Path>>(p: P) -> String {
p.as_ref()
.to_str()
.unwrap_or(format!("{:?}", p.as_ref()).as_ref())
.to_owned()
}
pub fn osstring_to_string(p: &OsStr) -> String {
p.to_str().unwrap_or(format!("{:?}", p).as_ref()).to_owned()
}
#[cfg(test)]
mod tests {
use crate::{decanonicalize, readable_canonical_path, LookupError};
#[test]
fn decanonicalize_removes_prefix() -> Result<(), LookupError> {
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let cargo_dir_canon = std::fs::canonicalize(&cargo_dir)?;
let cargo_dir_decanon = decanonicalize(cargo_dir_canon.to_str().unwrap());
assert!(!cargo_dir_decanon.contains(r"\\?\"));
let cargo_dir_decanon2 = readable_canonical_path(&cargo_dir)?;
assert!(!cargo_dir_decanon2.contains(r"\\?\"));
assert_eq!(cargo_dir_decanon, cargo_dir_decanon2);
Ok(())
}
}