История изменений
Исправление den73, (текущая версия) :
Под конец уже более-менее ничего. Единственное, чего я не понял. Если в функции может быть более одного типов ошибок, и мы хотим передать клиенту исчерпывающую информацию, нужно создавать перечисление (говоря по-человечески - юнион) из этих типов. И тут есть вот такой кусок кода:
use std::error;
use std::fmt;
impl fmt::Display for CliError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
// Оба изначальных типа ошибок уже реализуют `Display`,
// так что мы можем использовать их реализации
CliError::Io(ref err) => write!(f, "IO error: {}", err),
CliError::Parse(ref err) => write!(f, "Parse error: {}", err),
}
}
}
impl error::Error for CliError {
fn description(&self) -> &str {
// Оба изначальных типа ошибок уже реализуют `Error`,
// так что мы можем использовать их реализацией
match *self {
CliError::Io(ref err) => err.description(),
CliError::Parse(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
// В обоих случаях просходит неявное преобразование значения `err`
// из конкретного типа (`&io::Error` или `&num::ParseIntError`)
// в типаж-обьект `&Error`. Это работает потому что оба типа реализуют `Error`.
CliError::Io(ref err) => Some(err),
CliError::Parse(ref err) => Some(err),
}
}
}
Исходная версия den73, :
Под конец уже более-менее ничего. Единственное, чего я не понял. Если в функции может быть более одного типов ошибок, и мы хотим передать клиенту исчерпывающую информацию, нужно создавать перечисление (говоря по-человечески - юнион) из этих типов. И тут есть вот такой кусок кода:
use std::error;
use std::fmt;
impl fmt::Display for CliError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
// Оба изначальных типа ошибок уже реализуют `Display`,
// так что мы можем использовать их реализации
CliError::Io(ref err) => write!(f, "IO error: {}", err),
CliError::Parse(ref err) => write!(f, "Parse error: {}", err),
}
}
}
impl error::Error for CliError {
fn description(&self) -> &str {
// Оба изначальных типа ошибок уже реализуют `Error`,
// так что мы можем использовать их реализацией
match *self {
CliError::Io(ref err) => err.description(),
CliError::Parse(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
// В обоих случаях просходит неявное преобразование значения `err`
// из конкретного типа (`&io::Error` или `&num::ParseIntError`)
// в типаж-обьект `&Error`. Это работает потому что оба типа реализуют `Error`.
CliError::Io(ref err) => Some(err),
CliError::Parse(ref err) => Some(err),
}
}
}