Crate file_paths

The file_paths crate provides relativity and resolution for textual file paths. Path is based on a variant for compliance reasons. The provided Path isn't specifically a "file path", it does no system operation.

It's supports two variants (PlatformPathVariant):

  • Common: considers absolute paths as starting with a path separator only
  • Windows: considers absolute paths as either:
    • starting with a UNC prefix (\\);
    • starting with a drive prefix (drive:);
    • starting with a path separator.

It might not be useful in pratice to have these variants: wouldn't it simply be easier to always use Windows? This Path is based on Common, so I'd like to keep them separate for compliance (for example, someone might want the is_absolute method to work a certain way for a certain purpose, and Path isn't necessarily a file operation or a file operation in the operating system).

PlatformPathVariant::NATIVE yields the target platform proper one.

Path can be constructed with _native and _common suffixes too.

#[test]
fn relativity() {
    assert_eq!("", Path::new_common("/a/b").relative("/a/b"));
    assert_eq!("c", Path::new_common("/a/b").relative("/a/b/c"));
    assert_eq!("../../c/d", Path::new_common("/a/b/c").relative("/a/c/d"));
    assert_eq!("..", Path::new_common("/a/b/c").relative("/a/b"));
    assert_eq!("../..", Path::new_common("/a/b/c").relative("/a"));
    assert_eq!("..", Path::new_common("/a").relative("/"));
    assert_eq!("a", Path::new_common("/").relative("/a"));
    assert_eq!("", Path::new_common("/").relative("/"));
    assert_eq!("../../c/d", Path::new_common("/a/b").relative("/c/d"));
    assert_eq!("../c", Path::new_common("/a/b").relative("/a/c"));

    let windows = PlatformPathVariant::Windows;
    assert_eq!("", Path::new("C:/", windows).relative("C:/"));
    assert_eq!("", Path::new("C:/foo", windows).relative("C:/foo"));
    assert_eq!(r"\\foo", Path::new("C:/", windows).relative(r"\\foo"));
    assert_eq!("../../foo", Path::new(r"\\a/b", windows).relative(r"\\foo"));
    assert_eq!("D:/", Path::new("C:/", windows).relative(r"D:"));
}

#[test]
fn resolution() {
    assert_eq!("a", Path::from_n_common(["a/b/.."]).to_string());
    assert_eq!("a", Path::from_n_common(["a", "b", ".."]).to_string());
    assert_eq!("/a/b", Path::new_common("/c").resolve("/a/b").to_string());
    assert_eq!("a", Path::new_common("a/b").resolve("..").to_string());
    assert_eq!("a/b", Path::new_common("a/b/").to_string());
    assert_eq!("a/b", Path::new_common("a//b").to_string());

    let windows = PlatformPathVariant::Windows;
    assert_eq!(r"\\Whack/a/Box", Path::from_n(["foo", r"\\Whack////a//Box", "..", "Box"], windows).to_string());
    assert_eq!("C:/a", Path::new("C:/", windows).resolve("a").to_string());
    assert_eq!("D:/", Path::new("C:/", windows).resolve("D:/").to_string());
    assert_eq!("D:/a", Path::new("D:/a", windows).to_string());
    assert_eq!("C:/a/f/b", Path::new("a", windows).resolve("C:/a///f//b").to_string());
}

Can anyone tell me if there's a name better than file_paths since it's not limited to files? (I'm thinking of using this both in file system and node paths)

If you want a generic word for file_path that doesn't have to refer to a filesystem, you could try address, identifier or location.

1 Like