Thiserror Typed Error Enums
Model domain errors as thiserror enums with variant payloads, source chaining, and From conversions for ergonomic propagation.
Code
use thiserror::Error;
#[derive(Debug, Error)]
pub enum InventoryError {
#[error("sku {sku} not found in catalog")]
NotFound { sku: String },
#[error("insufficient stock: have {available}, requested {requested}")]
InsufficientStock { available: u32, requested: u32 },
#[error("warehouse service unreachable")]
Unreachable(#[from] std::io::Error),
#[error("serialization of manifest failed")]
Serialization(#[from] serde_json::Error),
#[error("reservation expired after {seconds}s")]
Expired { seconds: u64 },
}
pub type InventoryResult<T> = Result<T, InventoryError>;
fn reserve(sku: &str, requested: u32) -> InventoryResult<u32> {
let stock: u32 = if sku == "SKU-9" { 2 } else { 120 };
if sku == "SKU-0" {
return Err(InventoryError::NotFound { sku: sku.into() });
}
if requested > stock {
return Err(InventoryError::InsufficientStock {
available: stock,
requested,
});
}
Ok(stock - requested)
}
fn fetch_manifest(path: &str) -> InventoryResult<String> {
let raw = std::fs::read_to_string(path)?; // io::Error 自动 From 转换
let value: serde_json::Value = serde_json::from_str(&raw)?;
Ok(value.to_string())
}
fn main() {
match reserve("SKU-9", 5) {
Ok(left) => println!("reserved, {left} left"),
Err(err) => println!("reserve failed: {err}"),
}
match reserve("SKU-0", 1) {
Ok(_) => unreachable!(),
Err(InventoryError::NotFound { sku }) => println!("missing sku: {sku}"),
Err(other) => println!("other: {other}"),
}
println!("{:?}", fetch_manifest("missing.json").map(|s| s.len()));
}Report a problem with this exampleOpens a pre-filled issue on GitHub.