1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! This module provides the error-handling framework for the whole project.

pub use std::error::Error;
use std::fmt;
use std::result;

///
/// custom Result type for functions which can
/// potentially fail
///
pub type Result<T> = result::Result<T, MazeError>;

///
/// Categories of potential errors
///
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ErrorKind {
    /// Provided dimensions were not positive
    /// integers
    InvalidDimensions,

    /// special case where the provided dimensions are not
    /// valid numbers
    InvalidDimensionsNotNumber,

    /// Provided vertex/vertices was/were
    /// invalid
    InvalidVertexOrVertices,
}

impl ErrorKind {
    fn as_str(&self) -> &'static str {
        match *self {
            ErrorKind::InvalidDimensionsNotNumber => "invalid dimensions: non-numeric values",
            ErrorKind::InvalidDimensions => "invalid dimensions: non (positive) integer values",
            ErrorKind::InvalidVertexOrVertices => "invalid vertex or vertices",
        }
    }
}

///
/// Custom error type for the Maze project
///
pub struct MazeError {
    repr: Repr,
}

///
/// Possible variants for errors - the basic ones listed in the
/// ErrorKind enum, or custom types for more flexibility.
///
#[derive(Debug)]
enum Repr {
    Simple(ErrorKind),
    Custom(Box<Custom>),
}

#[derive(Debug)]
struct Custom {
    kind: ErrorKind,
    error: Box<dyn Error + Send + Sync>,
}

impl MazeError {
    /// allow creation of errors from known kinds of errors
    /// as well as from custom types
    pub fn new<E>(kind: ErrorKind, error: E) -> Self
    where
        E: Into<Box<dyn Error + Send + Sync>>,
    {
        MazeError {
            repr: Repr::Custom(Box::new(Custom {
                kind: kind,
                error: error.into(),
            })),
        }
    }

    /// allows the creation of a simple error by
    /// simply passing in the error kind
    pub fn of(kind: ErrorKind) -> Self {
        MazeError {
            repr: Repr::Simple(kind),
        }
    }
}

/// make this custom error type an actual error type that can be used
/// in conjunction with other error types.
impl Error for MazeError {}

impl fmt::Debug for MazeError {
    /// allows errors to be printed using the `{:?}` formatter
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.repr, f)
    }
}

impl fmt::Display for MazeError {
    /// allows errors to be printed using the `{}` formatter
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.repr {
            Repr::Simple(kind) => write!(f, "Error: {}", kind.as_str()),
            Repr::Custom(ref custom_error) => write!(f, "{}", custom_error.error),
        }
    }
}

impl From<ErrorKind> for MazeError {
    /// Allows conversions from other error types into
    /// our custom error type
    #[inline]
    fn from(kind: ErrorKind) -> MazeError {
        MazeError {
            repr: Repr::Simple(kind),
        }
    }
}