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
119
120
121
122
123
124
125
126
127
128
129
130
//! Specs error module.
//!
//! There are specific types for errors (e.g. `WrongGeneration`)
//! and additionally one `Error` type that can represent them all.
//! Each error in this module has an `Into<Error>` implementation.

use std::error::Error as StdError;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};

use world::{Entity, Generation};

/// A boxed error implementing `Debug`, `Display` and `Error`.
pub struct BoxedErr(pub Box<StdError + Send + Sync + 'static>);

impl BoxedErr {
    /// Creates a new boxed error.
    pub fn new<T>(err: T) -> Self
    where
        T: StdError + Send + Sync + 'static,
    {
        BoxedErr(Box::new(err))
    }
}

impl AsRef<StdError> for BoxedErr {
    fn as_ref(&self) -> &(StdError + 'static) {
        self.0.as_ref()
    }
}

impl Debug for BoxedErr {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{:}", self.0)
    }
}

impl Display for BoxedErr {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", self.as_ref())
    }
}

impl StdError for BoxedErr {
    fn description(&self) -> &str {
        self.as_ref().description()
    }
}

/// The Specs error type.
/// This is an enum which is able to represent
/// all error types of this library.
///
/// Please note that you should not use `__NonExhaustive`,
/// which is a variant specifically added for extensibility
/// without breakage.
#[derive(Debug)]
pub enum Error {
    /// A custom, boxed error.
    Custom(BoxedErr),
    /// Wrong generation error.
    WrongGeneration(WrongGeneration),

    #[doc(hidden)]
    __NonExhaustive,
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            Error::Custom(ref e) => write!(f, "Custom: {}", e),
            Error::WrongGeneration(ref e) => write!(f, "Wrong generation: {}", e),

            Error::__NonExhaustive => unimplemented!(),
        }
    }
}

impl From<WrongGeneration> for Error {
    fn from(e: WrongGeneration) -> Self {
        Error::WrongGeneration(e)
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        "A Specs error"
    }

    fn cause(&self) -> Option<&StdError> {
        let e = match *self {
            Error::Custom(ref e) => e.as_ref(),
            Error::WrongGeneration(ref e) => e,

            Error::__NonExhaustive => unimplemented!(),
        };

        Some(e)
    }
}

/// Wrong generation error.
#[derive(Debug)]
pub struct WrongGeneration {
    /// The action that failed because of the wrong generation.
    pub action: &'static str,
    /// The actual generation of this id.
    pub actual_gen: Generation,
    /// The entity that has been passed, containing
    /// the id and the invalid generation.
    pub entity: Entity,
}

impl Display for WrongGeneration {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(
            f,
            "Tried to {} entity {:?}, but the generation is wrong; it should be {:?}",
            self.action,
            self.entity,
            self.actual_gen
        )
    }
}

impl StdError for WrongGeneration {
    fn description(&self) -> &str {
        "Used an entity with a generation that is not valid anymore \
         (e.g. because the entity has been deleted)"
    }
}