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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::{borrow::Borrow, path::PathBuf, str::FromStr};
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
pub struct FuzzyPath(String);
impl FuzzyPath {
pub unsafe fn from_str_unchecked<S: Into<String>>(str: S) -> Self {
FuzzyPath(str.into())
}
}
impl From<&str> for FuzzyPath {
fn from(str: &str) -> Self {
let str = str.replace("\\", "/");
let str = str.trim_end_matches("/");
let mut normalized = String::with_capacity(str.len());
let mut slash = false;
for char in str.chars() {
if char == '/' {
if !slash {
slash = true;
normalized.push('/');
}
} else {
slash = false;
let char = char.to_lowercase();
normalized.extend(char);
}
}
FuzzyPath(normalized)
}
}
impl From<PathBuf> for FuzzyPath {
fn from(pathbuf: PathBuf) -> Self {
pathbuf.to_string_lossy().as_ref().into()
}
}
impl From<String> for FuzzyPath {
fn from(string: String) -> Self {
string.as_str().into()
}
}
impl Into<PathBuf> for FuzzyPath {
fn into(self) -> PathBuf {
PathBuf::from(self.0)
}
}
impl Into<String> for FuzzyPath {
fn into(self) -> String {
self.0
}
}
impl AsRef<String> for FuzzyPath {
fn as_ref(&self) -> &String {
&self.0
}
}
impl AsRef<str> for FuzzyPath {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl Borrow<str> for FuzzyPath {
fn borrow(&self) -> &str {
self.0.as_str()
}
}
impl Borrow<String> for FuzzyPath {
fn borrow(&self) -> &String {
&self.0
}
}
impl FromStr for FuzzyPath {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(s.into())
}
}
#[cfg(feature = "serde")]
mod serde;
#[test]
fn test_normalize() {
assert_eq!(FuzzyPath::from("HELLO\\\\world/////foo/bar/////////"), FuzzyPath::from("hello/world/foo/bar"));
assert_eq!(FuzzyPath::from("\\\\HELLO\\\\world/////foo/bar/////////"), FuzzyPath::from("/hello/world/foo/bar"));
}