Skip to content

Commit

Permalink
Implement canon_path_in_place for backslashes (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
clemenswasser authored Apr 7, 2022
1 parent 27e31fd commit 95dc3fb
Showing 1 changed file with 27 additions and 18 deletions.
45 changes: 27 additions & 18 deletions src/canon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn canon_path_in_place(path: &mut String) {
if src == end {
return;
}
if *src == b'/' {
if *src == b'/' || *src == b'\\' {
src = src.add(1);
dst = dst.add(1);
}
Expand All @@ -63,7 +63,7 @@ pub fn canon_path_in_place(path: &mut String) {
while src < end {
// Peek ahead for special path components: "/", ".", and "..".
match *src {
b'/' => {
b'/' | b'\\' => {
src = src.add(1);
continue;
}
Expand All @@ -73,15 +73,15 @@ pub fn canon_path_in_place(path: &mut String) {
break; // Trailing '.', trim.
}
match *peek {
b'/' => {
b'/' | b'\\' => {
// "./", skip.
src = src.add(2);
continue;
}
b'.' => {
// ".."
peek = peek.add(1);
if !(peek == end || *peek == b'/') {
if !(peek == end || *peek == b'/' || *peek == b'\\') {
// Componet that happens to start with "..".
// Handle as an ordinary component.
break;
Expand All @@ -95,7 +95,7 @@ pub fn canon_path_in_place(path: &mut String) {
*dst = b'.';
dst = dst.add(1);
if peek != end {
*dst = b'/';
*dst = *peek;
dst = dst.add(1);
}
}
Expand All @@ -116,7 +116,7 @@ pub fn canon_path_in_place(path: &mut String) {
*dst = *src;
src = src.add(1);
dst = dst.add(1);
if *src.offset(-1) == b'/' {
if *src.offset(-1) == b'/' || *src.offset(-1) == b'\\' {
break;
}
}
Expand All @@ -136,33 +136,42 @@ pub fn canon_path<T: Into<String>>(inpath: T) -> String {
mod tests {
use super::*;

// Assert that canon path equals expected path with different path separators
fn assert_canon_path_eq(left: &str, right: &str) {
assert_eq!(canon_path(left), right);
assert_eq!(
canon_path(left.replace('/', "\\")),
right.replace('/', "\\")
);
}

#[test]
fn noop() {
assert_eq!(canon_path("foo"), "foo");
assert_canon_path_eq("foo", "foo");

assert_eq!(canon_path("foo/bar"), "foo/bar");
assert_canon_path_eq("foo/bar", "foo/bar");
}

#[test]
fn dot() {
assert_eq!(canon_path("./foo"), "foo");
assert_eq!(canon_path("foo/."), "foo/");
assert_eq!(canon_path("foo/./bar"), "foo/bar");
assert_canon_path_eq("./foo", "foo");
assert_canon_path_eq("foo/.", "foo/");
assert_canon_path_eq("foo/./bar", "foo/bar");
}

#[test]
fn slash() {
assert_eq!(canon_path("/foo"), "/foo");
assert_eq!(canon_path("foo//bar"), "foo/bar");
assert_canon_path_eq("/foo", "/foo");
assert_canon_path_eq("foo//bar", "foo/bar");
}

#[test]
fn parent() {
assert_eq!(canon_path("foo/../bar"), "bar");
assert_canon_path_eq("foo/../bar", "bar");

assert_eq!(canon_path("/foo/../bar"), "/bar");
assert_eq!(canon_path("../foo"), "../foo");
assert_eq!(canon_path("../foo/../bar"), "../bar");
assert_eq!(canon_path("../../bar"), "../../bar");
assert_canon_path_eq("/foo/../bar", "/bar");
assert_canon_path_eq("../foo", "../foo");
assert_canon_path_eq("../foo/../bar", "../bar");
assert_canon_path_eq("../../bar", "../../bar");
}
}

0 comments on commit 95dc3fb

Please sign in to comment.