scolapasta_path/paths/
default.rs1use std::ffi::{OsStr, OsString};
2use std::path::{self, PathBuf};
3
4#[allow(dead_code)]
5pub fn is_explicit_relative(path: &OsStr) -> bool {
6 let bytes = if let Some(path) = path.to_str() {
7 path.as_bytes()
8 } else {
9 return false;
10 };
11 is_explicit_relative_bytes(bytes)
12}
13
14#[allow(dead_code)]
15pub fn is_explicit_relative_bytes(path: &[u8]) -> bool {
16 match path {
20 [b'.', b'.', x, ..] if path::is_separator((*x).into()) => true,
21 [b'.', x, ..] if path::is_separator((*x).into()) => true,
22 _ => false,
23 }
24}
25
26#[allow(dead_code)]
27pub fn normalize_slashes(path: PathBuf) -> Result<Vec<u8>, PathBuf> {
28 match OsString::from(path).into_string() {
29 Ok(s) => Ok(s.into()),
30 Err(buf) => Err(buf.into()),
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use std::ffi::OsStr;
37 use std::path::PathBuf;
38
39 use super::{is_explicit_relative, is_explicit_relative_bytes, normalize_slashes};
40
41 #[test]
42 fn empty() {
43 assert!(!is_explicit_relative(OsStr::new("")));
44 assert!(!is_explicit_relative_bytes("".as_bytes()));
45 }
46
47 #[test]
48 fn single_char() {
49 assert!(!is_explicit_relative(OsStr::new("a")));
50 assert!(!is_explicit_relative_bytes("a".as_bytes()));
51 }
52
53 #[test]
54 fn single_dot() {
55 assert!(!is_explicit_relative(OsStr::new(".")));
56 assert!(!is_explicit_relative_bytes(".".as_bytes()));
57 }
58
59 #[test]
60 fn double_dot() {
61 assert!(!is_explicit_relative(OsStr::new("..")));
62 assert!(!is_explicit_relative_bytes("..".as_bytes()));
63 }
64
65 #[test]
66 fn triple_dot() {
67 assert!(!is_explicit_relative(OsStr::new("...")));
68 assert!(!is_explicit_relative_bytes("...".as_bytes()));
69 }
70
71 #[test]
72 fn single_dot_slash() {
73 assert!(is_explicit_relative(OsStr::new("./")));
74 assert!(is_explicit_relative_bytes("./".as_bytes()));
75 }
76
77 #[test]
78 fn double_dot_slash() {
79 assert!(is_explicit_relative(OsStr::new("../")));
80 assert!(is_explicit_relative_bytes("../".as_bytes()));
81 }
82
83 #[test]
84 fn absolute() {
85 let test_cases = [r"/bin", r"/home/artichoke"];
86 for path in test_cases {
87 assert!(
88 !is_explicit_relative(OsStr::new(path)),
89 "expected absolute path '{path}' to NOT be explicit relative path"
90 );
91 assert!(
92 !is_explicit_relative_bytes(path.as_bytes()),
93 "expected absolute path '{path}' to NOT be explicit relative path"
94 );
95 }
96 }
97
98 #[test]
99 fn relative() {
100 let test_cases = [r"temp", r"temp/../var"];
101 for path in test_cases {
102 assert!(
103 !is_explicit_relative(OsStr::new(path)),
104 "expected relative path '{path}' to NOT be explicit relative path"
105 );
106 assert!(
107 !is_explicit_relative_bytes(path.as_bytes()),
108 "expected relative path '{path}' to NOT be explicit relative path"
109 );
110 }
111 }
112
113 #[test]
114 fn explicit_relative() {
115 let test_cases = [r"./cache", r"../cache", r"./.git", r"../.git"];
116 for path in test_cases {
117 assert!(
118 is_explicit_relative(OsStr::new(path)),
119 "expected relative path '{path}' to be explicit relative path"
120 );
121 assert!(
122 is_explicit_relative_bytes(path.as_bytes()),
123 "expected relative path '{path}' to be explicit relative path"
124 );
125 }
126 }
127
128 #[test]
129 fn not_explicit_relative() {
130 let test_cases = [r"...\var", r".../var", r"\var", r"/var"];
131 for path in test_cases {
132 assert!(
133 !is_explicit_relative(OsStr::new(path)),
134 "expected path '{path}' to NOT be explicit relative path"
135 );
136 assert!(
137 !is_explicit_relative_bytes(path.as_bytes()),
138 "expected path '{path}' to NOT be explicit relative path"
139 );
140 }
141 }
142
143 #[test]
144 fn invalid_utf8_explicit_relative_bytes() {
145 let test_cases: [&[u8]; 4] = [b"./\xFF", b"../\xFF", b"./\xFF\xFE", b"../\xFF\xFE"];
146 for path in test_cases {
147 assert!(
148 is_explicit_relative_bytes(path),
149 "expected invalid UTF-8 relative path '{path:?}' to be explicit relative path"
150 );
151 }
152 }
153
154 #[test]
155 fn invalid_utf8_not_explicit_relative_bytes() {
156 let test_cases: [&[u8]; 4] = [b"/\xFF", b"\xFF", b"/\xFF\xFE", b"\xFF\xFE"];
157 for path in test_cases {
158 assert!(
159 !is_explicit_relative_bytes(path),
160 "expected invalid UTF-8 path '{path:?}' to NOT be explicit relative path"
161 );
162 }
163 }
164
165 #[test]
166 fn normalize_slashes_no_backslash() {
167 let path = PathBuf::from(r"abcxyz".to_string());
168 assert_eq!(normalize_slashes(path).unwrap(), b"abcxyz".to_vec());
169
170 let path = PathBuf::from(r"abc/xyz".to_string());
171 assert_eq!(normalize_slashes(path).unwrap(), b"abc/xyz".to_vec());
172 }
173
174 #[test]
175 fn normalize_slashes_backslash_noop() {
176 let path = PathBuf::from(r"abc\xyz".to_string());
177 assert_eq!(normalize_slashes(path).unwrap(), br"abc\xyz".to_vec());
178
179 let path = PathBuf::from(r"abc\xyz\123".to_string());
180 assert_eq!(normalize_slashes(path).unwrap(), br"abc\xyz\123".to_vec());
181 }
182}