Crate path_abs [] [src]

Ergonomic paths and files in rust.

This library aims to provide ergonomic path and file operations to rust with reasonable performance.

This includes:

  • Improved error messages, see the Better Errors section.
  • Improved type safety. The types specify that a file once existed and was once a certain type. Obviously a file/directory can be deleted/changed by another process.
  • More stringent mutability requirements. See the Differing Method Signatures section.
  • Cheap cloning: all path types are Arc, which a cheap operation compared to filesystem operations and allows more flexibility and ergonomics in the library for relatively low cost.

Better Errors

All errors include the path and action which caused the error, as well as the unaltered std::io::Error message. Errors are std::io::Error, giving almost complete compatibility with existing code.

set_len (i.e. truncate a file):

The above error is actually impossible because FileWrite is always writeable, and FileRead does not implement set_len. However, it is kept for demonstration.

read (open file for reading):

And every other method has similarily improved errors. If a method does not have pretty error messages please open a ticket.

Exported Path Types

These are the exported Path types. All of them are absolute except for PathArc, which is just an Arc<PathBuf> with methods that have better error reporting.

  • PathArc: a reference counted PathBuf with methods reimplemented with better error messages. Use this for a generic serializable path that may or may not exist.
  • PathAbs: a reference counted absolute (canonicalized) path that is guaranteed (on initialization) to exist.
  • PathFile: a PathAbs that is guaranteed to be a file, with associated methods.
  • PathDir: a PathAbs that is guaranteed to be a directory, with associated methods.
  • PathType: an enum containing either a PathFile or a PathDir. Returned by PathDir::list

In addition, all paths are serializable through serde (even on windows!) by using the crate stfu8 to encode/decode, allowing ill-formed UTF-16. See that crate for more details on how the resulting encoding can be edited (by hand) even in the case of what would be ill-formed UTF-16.

Exported File Types

All File types provide type safe access to their relevant traits. For instance, you can't read with a FileWrite and you can't write with a FileRead.

  • FileRead: a read-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a read-only file.
  • FileWrite: a write-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a write-only file.
  • FileEdit: a read/write file handle with path() attached and improved error messages. Contains methods and trait implements for both readable and writeable files.

Differing Method Signatures

The type signatures of the File* types regarding read, write and other methods is slightly different than std::fs::File -- they all take &mut instead of &. This is to avoid a common possible footgun.

To demonstrate, imagine the following scenario:

  • You pass your open &File to a method, which puts it in a thread. This thread constantly calls seek(SeekFrom::Start(10))
  • You periodically read from a file expecting new data, but are always getting the same data.

Yes, this is actually allowed by the rust compiler since seek is implemented for &File. Technically this is still memory safe since the operating system will handle any contention, however many would argue that it isn't expected that an immutable reference passed to another function can affect the seek position of a file.

Examples

Recreating Cargo.init in example/

use std::path::Path;
use std::collections::HashSet;
use path_abs::{
    PathAbs,   // absolute path that exists
    PathDir,   // absolute path to a directory
    PathFile,  // absolute path to a file
    PathType,  // enum of Dir or File
    FileRead,  // Open read-only file handler
    FileWrite, // Open write-only file handler
    FileEdit,  // Open read/write file handler
};

let example = Path::new("example");

// Create your paths
let project = PathDir::create_all(example)?;
let src = PathDir::create(project.join("src"))?;
let lib = PathFile::create(src.join("lib.rs"))?;
let cargo = PathFile::create(project.join("Cargo.toml"))?;

// Write the templates
lib.write_str(r#"
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}"#)?;

cargo.write_str(r#"
[package]
name = "example"
version = "0.1.0"
authors = ["Garrett Berg <vitiral@gmail.com>"]

[dependencies]
"#)?;

// Put our result into a HashMap so we can assert it
let mut result = HashSet::new();
for p in project.list()? {
    result.insert(p?);
}

// Create our expected value
let mut expected = HashSet::new();
expected.insert(PathType::Dir(src));
expected.insert(PathType::File(cargo));

assert_eq!(expected, result);

// ----------------------------------
// Creating types from existing paths

// Creating a generic path
let lib_path = example.join("src").join("lib.rs");
let abs = PathAbs::new(&lib_path)?;

// Or a path with a known type
let file = PathType::new(&lib_path)
    ?
    .unwrap_file();

// Or use `PathAbs::into_file`
let file2 = abs.clone().into_file()?;

assert!(abs.is_file());
assert!(file.is_file());
assert!(file2.is_file());

// ----------------------------------
// Opening a File

// open read-only using the PathFile method
let read = file.read()?;

// Or use the type directly: open for appending
let write = FileWrite::append(&file)?;

// Open for read/write editing.
let edit = file.edit()?;

Modules

open

Open file paths and associated methods.

Structs

Error

An error produced by performing an filesystem operation on a Path.

FileEdit

A read/write file handle with path() attached and improved error messages. Contains methods and trait implements for both readable and writeable files.

FileRead

A read-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a read-only file.

FileWrite

A write-only file handle with path() attached and improved error messages. Contains only the methods and trait implementations which are allowed by a write-only file.

ListDir

An iterator over PathType objects, returned by PathDir::list.

PathAbs

An absolute (canonicalized) path that is guaranteed (when created) to exist.

PathArc

A PathBuf that is atomically reference counted and reimplements the PathBuf methods to display the action and path when there is an error.

PathDir

A PathAbs that is guaranteed to be a directory, with associated methods.

PathFile

a PathAbs that was a file at the time of initialization, with associated methods.

Enums

PathType

An an enum containing either a file or a directory.

Type Definitions

Result