Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include the file path in an IO error in Rust?

In this minimalist program, I'd like the file_size function to include the path /not/there in the Err so it can be displayed in the main function:

use std::fs::metadata;
use std::io;
use std::path::Path;
use std::path::PathBuf;

fn file_size(path: &Path) -> io::Result<u64> {
    Ok(metadata(path)?.len())
}

fn main() {
    if let Err(err) = file_size(&PathBuf::from("/not/there")) {
        eprintln!("{}", err);
    }
}
like image 671
Gaëtan Lehmann Avatar asked Dec 26 '18 17:12

Gaëtan Lehmann


1 Answers

You must define your own error type in order to wrap this additional data.

Personally, I like to use the custom_error crate for that, as it's especially convenient for dealing with several types. In your case it might look like this:

use custom_error::custom_error;
use std::fs::metadata;
use std::io;
use std::path::{Path, PathBuf};
use std::result::Result;

custom_error! {ProgramError
    Io {
        source: io::Error,
        path: PathBuf
    } = @{format!("{path}: {source}", source=source, path=path.display())},
}

fn file_size(path: &Path) -> Result<u64, ProgramError> {
    metadata(path)
        .map(|md| md.len())
        .map_err(|e| ProgramError::Io {
            source: e,
            path: path.to_path_buf(),
        })
}

fn main() {
    if let Err(err) = file_size(&PathBuf::from("/not/there")) {
        eprintln!("{}", err);
    }
}

Output:

/not/there: No such file or directory (os error 2)
like image 149
Denys Séguret Avatar answered Sep 21 '22 18:09

Denys Séguret