Rust
thiserror
Build derived error types with the thiserror crate.
thiserror
In libraries, error types are usually an enum, and writing Display for each variant is repetitive. The thiserror crate generates it with a derive:
// Cargo.toml: thiserror = "1"
use thiserror::Error;
#[derive(Debug, Error)]
enum AyarHatasi {
#[error("eksik anahtar: {0}")]
Eksik(String),
#[error("geçersiz değer: {anahtar}={deger}")]
Gecersiz { anahtar: String, deger: String },
}
The code it generates is identical to the impl Display and impl Error you would write by hand; there's no runtime cost.
The hand-written equivalent
Since there are no external crates in the exercise environment, we'll write the same type by hand. This is what's behind thiserror:
impl fmt::Display for AyarHatasi {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AyarHatasi::Eksik(a) => write!(f, "eksik anahtar: {a}"),
AyarHatasi::Gecersiz { anahtar, deger } => {
write!(f, "geçersiz değer: {anahtar}={deger}")
}
}
}
}
impl std::error::Error for AyarHatasi {}
Exercise Settings errors
Define the AyarHatasi enum with the variants Eksik(String) and Gecersiz { anahtar, deger }; implement Display and Error by hand. Print Eksik("port") and Gecersiz { anahtar: "port", deger: "abc" } with {} on separate lines.
Show example solution
use std::fmt;
#[derive(Debug)]
enum AyarHatasi {
Eksik(String),
Gecersiz { anahtar: String, deger: String },
}
impl fmt::Display for AyarHatasi {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AyarHatasi::Eksik(a) => write!(f, "eksik anahtar: {a}"),
AyarHatasi::Gecersiz { anahtar, deger } => {
write!(f, "geçersiz değer: {anahtar}={deger}")
}
}
}
}
impl std::error::Error for AyarHatasi {}
fn main() {
let a = AyarHatasi::Eksik(String::from("port"));
let b = AyarHatasi::Gecersiz {
anahtar: String::from("port"),
deger: String::from("abc"),
};
println!("{}", a);
println!("{}", b);
}
Test yourself
-
<code>thiserror</code> or <code>anyhow</code>? What is the general rule?
- thiserror everywhere
- Both do the same thing
- thiserror in libraries (concrete types), anyhow in applications (one flexible type)
- anyhow everywhere
Show answer
thiserror in libraries (concrete types), anyhow in applications (one flexible type) — A library user wants to handle errors by kind; an application mostly reports the error.
-
Message attribute
#[derive(Debug, Error)]
enum AyarHatasi {
#[____("eksik anahtar: {0}")]
Eksik(String),
}
Show answer
#[derive(Debug, Error)]
enum AyarHatasi {
#[error("eksik anahtar: {0}")]
Eksik(String),
}
-
Value and message
- Eksik("port")
- eksik anahtar: port
- Gecersiz { port, abc }
- geçersiz değer: port=abc
- #[error("{0}")]
- First field
- #[error(transparent)]
- Inner error's message
Next lesson: anyhow