keramics_vfs/windows/
path.rs1use keramics_formats::{Path, PathComponent};
15use keramics_types::Ucs2String;
16
17pub struct WindowsPath {}
19
20impl WindowsPath {
21 pub fn data_fork_name(ucs2_string: &Ucs2String) -> Option<Ucs2String> {
23 if ucs2_string.is_empty() {
24 return None;
25 }
26 match ucs2_string
27 .elements
28 .iter()
29 .rposition(|value| *value == 0x003a)
30 {
31 Some(value_index) => {
32 let data_fork_name_string: Ucs2String =
33 Ucs2String::from(&ucs2_string.elements[value_index + 1..]);
34
35 Some(data_fork_name_string)
36 }
37 None => None,
38 }
39 }
40
41 pub fn from_str(mut string: &str) -> Path {
43 let components: Vec<PathComponent> = if string.is_empty() {
44 vec![]
45 } else if string == "\\" {
46 vec![PathComponent::Root]
47 } else {
48 if string.starts_with("\\\\.\\")
49 || string.starts_with("\\\\?\\")
50 || string.starts_with("\\??\\")
51 {
52 string = &string[4..];
53 }
54 let mut components: Vec<PathComponent> = Vec::new();
55
56 for string_segment in string.split("\\") {
57 if string_segment.is_empty() {
58 if components.is_empty() {
59 components.push(PathComponent::Root);
60 }
61 } else if string_segment == "." {
62 if components.is_empty() {
63 components.push(PathComponent::Current);
64 }
65 } else if string_segment == ".." {
66 match components.last() {
67 None | Some(PathComponent::Parent) => {
68 components.push(PathComponent::Parent);
69 }
70 Some(PathComponent::Root) => {}
71 _ => _ = components.pop(),
72 }
73 } else {
74 if let Some(PathComponent::Current) = components.last() {
75 _ = components.pop();
76 }
77 let path_component: PathComponent =
78 PathComponent::Ucs2String(Ucs2String::from(string_segment));
79
80 components.push(path_component);
81 }
82 }
83 components
84 };
85 Path { components }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_data_fork_name() {
95 let ucs2_string: Ucs2String = Ucs2String::from("");
96 let result: Option<Ucs2String> = WindowsPath::data_fork_name(&ucs2_string);
97 assert_eq!(result, None);
98
99 let ucs2_string: Ucs2String = Ucs2String::from("file");
100 let result: Option<Ucs2String> = WindowsPath::data_fork_name(&ucs2_string);
101 assert_eq!(result, None);
102
103 let ucs2_string: Ucs2String = Ucs2String::from(":fork");
104 let result: Option<Ucs2String> = WindowsPath::data_fork_name(&ucs2_string);
105 assert_eq!(result, Some(Ucs2String::from("fork")));
106
107 let ucs2_string: Ucs2String = Ucs2String::from("file:fork");
108 let result: Option<Ucs2String> = WindowsPath::data_fork_name(&ucs2_string);
109 assert_eq!(result, Some(Ucs2String::from("fork")));
110
111 let ucs2_string: Ucs2String = Ucs2String::from("file:fork1:fork2");
112 let result: Option<Ucs2String> = WindowsPath::data_fork_name(&ucs2_string);
113 assert_eq!(result, Some(Ucs2String::from("fork2")));
115
116 let ucs2_string: Ucs2String = Ucs2String::from("file:");
117 let result: Option<Ucs2String> = WindowsPath::data_fork_name(&ucs2_string);
118 assert_eq!(result, Some(Ucs2String::from("")));
119 }
120
121 #[test]
122 fn test_from_str() {
123 let test_struct: Path = WindowsPath::from_str("\\");
124 assert_eq!(test_struct.components, vec![PathComponent::Root]);
125
126 let test_struct: Path = WindowsPath::from_str("\\directory");
127 assert_eq!(
128 test_struct,
129 Path {
130 components: vec![
131 PathComponent::Root,
132 PathComponent::Ucs2String(Ucs2String::from("directory"))
133 ]
134 }
135 );
136
137 let test_struct: Path = WindowsPath::from_str("\\directory\\filename.txt");
138 assert_eq!(
139 test_struct,
140 Path {
141 components: vec![
142 PathComponent::Root,
143 PathComponent::Ucs2String(Ucs2String::from("directory")),
144 PathComponent::Ucs2String(Ucs2String::from("filename.txt")),
145 ]
146 }
147 );
148
149 let test_struct: Path = WindowsPath::from_str("\\directory\\.\\filename.txt");
150 assert_eq!(
151 test_struct,
152 Path {
153 components: vec![
154 PathComponent::Root,
155 PathComponent::Ucs2String(Ucs2String::from("directory")),
156 PathComponent::Ucs2String(Ucs2String::from("filename.txt")),
157 ]
158 }
159 );
160
161 let test_struct: Path = WindowsPath::from_str("\\directory\\");
162 assert_eq!(
163 test_struct,
164 Path {
165 components: vec![
166 PathComponent::Root,
167 PathComponent::Ucs2String(Ucs2String::from("directory"))
168 ]
169 }
170 );
171
172 let test_struct: Path = WindowsPath::from_str(".\\directory");
173 assert_eq!(
174 test_struct,
175 Path {
176 components: vec![PathComponent::Ucs2String(Ucs2String::from("directory"))]
177 }
178 );
179
180 let test_struct: Path = WindowsPath::from_str("..\\directory");
181 assert_eq!(
182 test_struct,
183 Path {
184 components: vec![
185 PathComponent::Parent,
186 PathComponent::Ucs2String(Ucs2String::from("directory"))
187 ]
188 }
189 );
190
191 let test_struct: Path = WindowsPath::from_str("..\\directory\\..\\filename.txt");
192 assert_eq!(
193 test_struct,
194 Path {
195 components: vec![
196 PathComponent::Parent,
197 PathComponent::Ucs2String(Ucs2String::from("filename.txt"))
198 ]
199 }
200 );
201
202 let test_struct: Path = WindowsPath::from_str("..\\..\\directory");
203 assert_eq!(
204 test_struct,
205 Path {
206 components: vec![
207 PathComponent::Parent,
208 PathComponent::Parent,
209 PathComponent::Ucs2String(Ucs2String::from("directory")),
210 ]
211 }
212 );
213
214 let test_struct: Path = WindowsPath::from_str("\\..\\directory");
215 assert_eq!(
216 test_struct,
217 Path {
218 components: vec![
219 PathComponent::Root,
220 PathComponent::Ucs2String(Ucs2String::from("directory"))
221 ]
222 }
223 );
224
225 let test_struct: Path = WindowsPath::from_str(".");
226 assert_eq!(
227 test_struct,
228 Path {
229 components: vec![PathComponent::Current]
230 }
231 );
232
233 let test_struct: Path = WindowsPath::from_str("");
235 assert_eq!(test_struct, Path { components: vec![] });
236 }
237
238 #[test]
239 fn test_from_str_with_prefix() {
240 let test_struct: Path = WindowsPath::from_str("\\\\.\\C:\\testdir1\\testfile1");
241 assert_eq!(
242 test_struct,
243 Path {
244 components: vec![
245 PathComponent::Ucs2String(Ucs2String::from("C:")),
246 PathComponent::Ucs2String(Ucs2String::from("testdir1")),
247 PathComponent::Ucs2String(Ucs2String::from("testfile1")),
248 ]
249 }
250 );
251
252 let test_struct: Path = WindowsPath::from_str("\\\\?\\C:\\testdir1\\testfile1");
253 assert_eq!(
254 test_struct,
255 Path {
256 components: vec![
257 PathComponent::Ucs2String(Ucs2String::from("C:")),
258 PathComponent::Ucs2String(Ucs2String::from("testdir1")),
259 PathComponent::Ucs2String(Ucs2String::from("testfile1")),
260 ]
261 }
262 );
263
264 let test_struct: Path = WindowsPath::from_str("\\??\\C:\\testdir1\\testfile1");
265 assert_eq!(
266 test_struct,
267 Path {
268 components: vec![
269 PathComponent::Ucs2String(Ucs2String::from("C:")),
270 PathComponent::Ucs2String(Ucs2String::from("testdir1")),
271 PathComponent::Ucs2String(Ucs2String::from("testfile1")),
272 ]
273 }
274 );
275 }
276
277 #[test]
278 fn test_from_str_with_drive_letter() {
279 let test_struct: Path = WindowsPath::from_str("C:");
280 assert_eq!(
281 test_struct,
282 Path {
283 components: vec![PathComponent::Ucs2String(Ucs2String::from("C:"))]
284 }
285 );
286 }
287}