Przeglądaj źródła

Teach to_file_path to understand percent-encoded drive letters on Windows.

Fixes #230
Arnavion 10 lat temu
rodzic
commit
6492574893
2 zmienionych plików z 29 dodań i 5 usunięć
  1. 25 5
      src/lib.rs
  2. 4 0
      tests/unit.rs

+ 25 - 5
src/lib.rs

@@ -1419,11 +1419,31 @@ fn file_url_segments_to_pathbuf(segments: str::Split<char>) -> Result<PathBuf, (
 #[cfg_attr(not(windows), allow(dead_code))]
 #[cfg_attr(not(windows), allow(dead_code))]
 fn file_url_segments_to_pathbuf_windows(mut segments: str::Split<char>) -> Result<PathBuf, ()> {
 fn file_url_segments_to_pathbuf_windows(mut segments: str::Split<char>) -> Result<PathBuf, ()> {
     let first = try!(segments.next().ok_or(()));
     let first = try!(segments.next().ok_or(()));
-    if first.len() != 2 || !first.starts_with(parser::ascii_alpha)
-            || first.as_bytes()[1] != b':' {
-        return Err(())
-    }
-    let mut string = first.to_owned();
+
+    let mut string = match first.len() {
+        2 => {
+            if !first.starts_with(parser::ascii_alpha) || first.as_bytes()[1] != b':' {
+                return Err(())
+            }
+
+            first.to_owned()
+        },
+
+        4 => {
+            if !first.starts_with(parser::ascii_alpha) {
+                return Err(())
+            }
+            let bytes = first.as_bytes();
+            if bytes[1] != b'%' || bytes[2] != b'3' || (bytes[3] != b'a' && bytes[3] != b'A') {
+                return Err(())
+            }
+
+            first[0..1].to_owned() + ":"
+        },
+
+        _ => return Err(()),
+    };
+
     for segment in segments {
     for segment in segments {
         string.push('\\');
         string.push('\\');
 
 

+ 4 - 0
tests/unit.rs

@@ -70,6 +70,10 @@ fn new_path_windows_fun() {
         // test windows canonicalized path
         // test windows canonicalized path
         let path = PathBuf::from(r"\\?\C:\foo\bar");
         let path = PathBuf::from(r"\\?\C:\foo\bar");
         assert!(Url::from_file_path(path).is_ok());
         assert!(Url::from_file_path(path).is_ok());
+
+        // Percent-encoded drive letter
+        let url = Url::parse("file:///C%3A/foo/bar").unwrap();
+        assert_eq!(url.to_file_path(), Ok(PathBuf::from(r"C:\foo\bar")));
     }
     }
 }
 }