rusty_systems/
error.rs

1//! General error handling tools and utilities
2
3use std::fmt::{Display, Formatter};
4use std::sync::PoisonError;
5
6#[derive(Debug, Clone)]
7pub enum ErrorKind {
8    General,
9    Parse,
10    /// Errors related to defining systems, production rules,
11    /// and so on.
12    Definitions,
13    /// Returned when attempting to create duplicate items
14    Duplicate,
15    /// Errors related to running a system. See [`crate::system::System`].
16    Execution,
17    /// Indicates an error with locks, such as a [`PoisonError`].
18    Locking,
19    /// An IO Error. 
20    Io
21}
22
23
24/// Errors that might be thrown when using this library. They will be
25/// of kind [`ErrorKind`].
26#[derive(Debug)]
27pub struct Error {
28    kind: ErrorKind,
29    message: String,
30    source: Option<Box<dyn std::error::Error>>
31}
32
33impl Default for Error {
34    fn default() -> Self {
35        Self {
36            kind: ErrorKind::General,
37            message: String::from("An unspecified error occurred"),
38            source: None
39        }
40    }
41}
42
43impl Display for Error {
44    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
45
46        if let ErrorKind::Definitions = self.kind {
47            f.write_str("Definition error: ")?;
48        }
49
50        f.write_str(&self.message)
51    }
52}
53
54impl std::error::Error for Error {
55    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
56        self.source.as_ref().map(|e| &**e)
57    }
58}
59
60
61impl Error {
62    pub fn new<S : ToString>(kind: ErrorKind, message: S) -> Self {
63        Error {
64            kind,
65            message: message.to_string(),
66            ..Default::default()
67        }
68    }
69
70    pub fn general<T : ToString>(message: T) -> Self {
71        Self::new(ErrorKind::General, message)
72    }
73
74    pub fn definition<T : ToString>(message: T) -> Self {
75        Self::new(ErrorKind::Definitions, message)
76    }
77
78    pub fn execution<T : ToString>(message: T) -> Self {
79        Self::new(ErrorKind::Execution, message)
80    }
81}
82
83impl<T> From<PoisonError<T>> for Error {
84    fn from(value: PoisonError<T>) -> Self {
85        Error::new(ErrorKind::Locking, value.to_string())
86    }
87}
88
89impl From<std::io::Error> for Error {
90    fn from(error: std::io::Error) -> Self {
91        Error {
92            kind: ErrorKind::Io,
93            message: error.to_string(),
94            source: Some(Box::new(error)),
95        }
96    }
97}
98
99impl From<std::num::ParseIntError> for Error {
100    fn from(error: std::num::ParseIntError) -> Self {
101        Error {
102            kind: ErrorKind::Parse,
103            message: error.to_string(),
104            source: Some(Box::new(error)),
105        }
106    }
107}
108
109impl From<std::num::ParseFloatError> for Error {
110    fn from(error: std::num::ParseFloatError) -> Self {
111        Error {
112            kind: ErrorKind::Parse,
113            message: error.to_string(),
114            source: Some(Box::new(error)),
115        }
116    }
117}