Перевод чужого сбоя в свой в Rust
Разбор текста в число может завершиться своим сбоем библиотеки. Если функция обещает вернуть только ваш тип ошибки, чужой вид нужно превратить в него явно, а не оставлять два разных типа во второй ветке исхода.
Стандартный трейт перевода как раз связывает пары типов: из исходного сбоя собирают ваше значение с нужными полями. После этого короткая запись в теле функции сможет подставить ваш тип вместо библиотечного, когда перевод написан.
Свяжем сбой разбора целого с типом пути:
#[derive(Debug)]
struct PathError {
path: String,
}
impl std::fmt::Display for PathError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "bad path {}", self.path)
}
}
impl std::error::Error for PathError {}
impl From<std::num::ParseIntError> for PathError {
fn from(_: std::num::ParseIntError) -> Self {
PathError {
path: String::from("input"),
}
}
}
fn main() {
let text = "x";
let parsed: Result<i32, PathError> = text.parse();
match parsed {
Ok(n) => println!("{}", n),
Err(e) => println!("{}", e),
}
}
На экране текст с полем "input": разбор
не удался, и сбой библиотеки превратили в
PathError через блок перевода.
Тот же перевод можно вызвать явно, если нужно добавить поле из контекста:
#[derive(Debug)]
struct PathError {
path: String,
}
impl std::fmt::Display for PathError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "bad path {}", self.path)
}
}
impl std::error::Error for PathError {}
impl From<std::num::ParseIntError> for PathError {
fn from(_: std::num::ParseIntError) -> Self {
PathError {
path: String::from("input"),
}
}
}
fn main() {
let text = "9z";
let outcome = text
.parse::<i32>()
.map_err(|_| PathError {
path: String::from("field"),
});
match outcome {
Ok(n) => println!("{}", n),
Err(e) => println!("{}", e),
}
}
Дан следующий код:
struct NumError {
hint: String,
}
impl std::fmt::Display for NumError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "num {}", self.hint)
}
}
impl std::error::Error for NumError {}
Напишите перевод из std::num::ParseIntError,
который кладет в hint строку "digit".
Разберите литерал "a" в i32 и выведите
текст сбоя.
Дан следующий код:
struct LineError {
line: u32,
}
Оформите печать, трейт ошибки и перевод из
сбоя разбора целого с полем line, равным
1. Проверьте на строке "12x".
Дан следующий код:
struct TokenError {
token: String,
}
Сделайте тип сбоя с полем token и переводом
из ParseIntError, который записывает
"?" в это поле. Выведите результат разбора
"7_".