thiserror та anyhow

Крейти thiserror та anyhow широко використовуються для спрощення обробки помилок.

  • thiserror часто використовується у бібліотеках для створення користувацьких типів помилок, які реалізують From<T>.
  • anyhow часто використовується програмами для полегшення обробки помилок у функціях, зокрема для додавання контекстної інформації до ваших помилок.
use anyhow::{bail, Context, Result};
use std::fs;
use std::io::Read;
use thiserror::Error;

#[derive(Clone, Debug, Eq, Error, PartialEq)]
#[error("Не знайдено імені користувача в {0}")]
struct EmptyUsernameError(String);

fn read_username(path: &str) -> Result<String> {
    let mut username = String::with_capacity(100);
    fs::File::open(path)
        .with_context(|| format!("Не вдалося відкрити {path}"))?
        .read_to_string(&mut username)
        .context("Не вдалося прочитати")?;
    if username.is_empty() {
        bail!(EmptyUsernameError(path.to_string()));
    }
    Ok(username)
}

fn main() {
    //fs::write("config.dat", "").unwrap();
    match read_username("config.dat") {
        Ok(username) => println!("Ім'я користувача: {username}"),
        Err(err) => println!("Помилка: {err:?}"),
    }
}
This slide should take about 5 minutes.

thiserror

  • Похідний макрос Error надається thiserror і має багато корисних атрибутів для компактного визначення типів помилок.
  • Трейт std::error::Error виводиться автоматично.
  • Повідомлення з #[error] використовується для отримання трейту Display.

anyhow

  • anyhow::Error по суті є обгорткою навколо Box<dyn Error>. Таким чином, це знову ж таки, як правило, не є хорошим вибором для загальнодоступного API бібліотеки, але широко використовується в програмах.
  • anyhow::Result<V> — це псевдонім типу для Result<V, anyhow::Error>.
  • Фактичний тип помилки всередині нього можна вилучити для перевірки, якщо це необхідно.
  • Функціональність, яку надає anyhow::Result<T>, може бути знайома розробникам Go, оскільки вона забезпечує подібні моделі використання та ергономіку до (T, error) від Go.
  • anyhow::Context - це трейт, реалізований для стандартних типів Result та Option. Використання anyhow::Context необхідне для того, щоб дозволити використання .context() та .with_context() для цих типів.