如何在 Rust 的 IO 错误中包含文件路径?

Gaë*_*ann 5 error-handling rust

在这个极简程序中,我希望file_size函数在其中包含路径/not/thereErr以便可以在main函数中显示:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Den*_*ret 5

您必须定义自己的错误类型才能包装这些附加数据。

就我个人而言,我喜欢为此使用custom_error crate,因为它在处理多种类型时特别方便。在您的情况下,它可能如下所示:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)