Как включить путь к файлу при ошибке ввода-вывода в Rust? - PullRequest
0 голосов
/ 26 декабря 2018

В этой минималистической программе мне бы хотелось, чтобы функция file_size включала путь /not/there в Err, чтобы он мог отображаться в функции 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);
    }
}

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

Хотя ответ Дени Сегюре правильный, мне нравится использовать мой ящик SNAFU , потому что он обеспечивает концепцию контекста .Это делает процесс прикрепления пути (или чего-либо еще!) Очень легким для выполнения:

use snafu::{ResultExt, Snafu}; // 0.2.3
use std::{
    fs, io,
    path::{Path, PathBuf},
};

#[derive(Debug, Snafu)]
enum ProgramError {
    #[snafu(display("Could not get metadata for {}: {}", path.display(), source))]
    Metadata { source: io::Error, path: PathBuf },
}

fn file_size(path: impl AsRef<Path>) -> Result<u64, ProgramError> {
    let path = path.as_ref();
    let md = fs::metadata(&path).context(Metadata { path })?;
    Ok(md.len())
}

fn main() {
    if let Err(err) = file_size("/not/there") {
        eprintln!("{}", err);
    }
}
0 голосов
/ 26 декабря 2018

Вы должны определить свой собственный тип ошибки, чтобы обернуть эти дополнительные данные.

Лично я для этого использую ящик custom_error , так как это особенно удобно для работы с несколькимитипы.В вашем случае это может выглядеть так:

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);
    }
}

Вывод:

/not/there: No such file or directory (os error 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...