thiserror
The thiserror crate provides macros to help avoid boilerplate when defining error types. It provides derive macros that assist in implementing From<T>, Display, and the Error trait.
use std::io::Read;use std::{fs, io};use thiserror::Error;#[derive(Debug, Error)]enum ReadUsernameError {#[error("I/O error: {0}")]IoError(#[from] io::Error),#[error("Found no username in {0}")]EmptyUsername(String),}fn read_username(path: &str) -> Result<String, ReadUsernameError> {let mut username = String::with_capacity(100);fs::File::open(path)?.read_to_string(&mut username)?;if username.is_empty() {return Err(ReadUsernameError::EmptyUsername(String::from(path)));}Ok(username)}fn main() {//fs::write("config.dat", "").unwrap();match read_username("config.dat") {Ok(username) => println!("Username: {username}"),Err(err) => println!("Error: {err:?}"),}}
This slide should take about 5 minutes.
- The
Errorderive macro is provided bythiserror, and has lots of useful attributes to help define error types in a compact way. - The message from
#[error]is used to derive theDisplaytrait. - Note that the (
thiserror::)Errorderive macro, while it has the effect of implementing the (std::error::)Errortrait, is not the same this; traits and macros do not share a namespace.