LINUX.ORG.RU

История изменений

Исправление 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),
        }
    }
}
Как я понял, причина надобности в таком коде состоит в строгости системы типов и в отсутствии наследования. Ниже сказано, что если мы добавляем третий тип ошибок, то достаточно добавить к типу ошибок новый вариант и добавить реализацию для From, чтобы преобразовать частный вид ошибок к типу CliError. А про то, что нужно ещё пополнить description и cause, не написано. Это автор упустил или я не заметил магию, которая сделает это самостоятельно?

Исходная версия 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),
        }
    }
}
Как я понял, причина надобности в таком коде состоит в строгости системы типов и в отсутствии наследования. Ниже сказано, что если мы добавляем третий тип, то достаточно добавить к типу ошибок новый вариант и добавить реализацию для From, чтобы преобразовать частный вид ошибок к типу CliError. А про то, что нужно ещё пополнить description и cause, не написано. Это автор упустил или я не заметил магию, которая сделает это самостоятельно?