cellular_raza_concepts/
errors.rs

1use core::fmt::Display;
2use std::error::Error;
3
4macro_rules! define_errors {
5    ($(($err_name: ident, $err_descr: expr)),+) => {
6        $(
7            #[doc = $err_descr]
8            #[derive(Debug,Clone)]
9            pub struct $err_name(
10                #[doc = "Error message associated with "]
11                #[doc = stringify!($err_name)]
12                #[doc = " error type."]
13                pub String,
14            );
15
16            impl Display for $err_name {
17                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
18                    write!(f, "{}", self.0)
19                }
20            }
21
22            impl Error for $err_name {}
23        )+
24    }
25}
26
27/// Error during decomposition of a SimulationDomain into multiple subdomains
28#[derive(Clone, Debug)]
29pub enum DecomposeError {
30    /// Generic error encountered during domain-decomposition
31    Generic(String),
32    /// [BoundaryError] which is encountered during domain-decomposition
33    BoundaryError(BoundaryError),
34    /// [IndexError] encountered during domain-decomposition
35    IndexError(IndexError),
36}
37
38impl Display for DecomposeError {
39    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
40        let message = match self {
41            DecomposeError::Generic(m) => m,
42            DecomposeError::BoundaryError(b) => &format!("{b}"),
43            DecomposeError::IndexError(i) => &format!("{i}"),
44        };
45        write!(f, "{}", message)
46    }
47}
48
49impl Error for DecomposeError {}
50
51impl From<BoundaryError> for DecomposeError {
52    fn from(value: BoundaryError) -> Self {
53        DecomposeError::BoundaryError(value)
54    }
55}
56
57impl From<IndexError> for DecomposeError {
58    fn from(value: IndexError) -> Self {
59        DecomposeError::IndexError(value)
60    }
61}
62
63define_errors!(
64    (SetupError, "Occurs during setup of a new simulation"),
65    (CalcError, "General Calculation Error"),
66    (
67        TimeError,
68        "Error related to advancing the simulation time or displaying its progress"
69    ),
70    // (
71    //     DecomposeError,
72    //     "Error during decomposition of a SimulationDomain into multiple subdomains"
73    // ),
74    (DivisionError, "Errors related to a cell dividing process"),
75    (
76        DeathError,
77        "Errors occurring during the final death step of a cell"
78    ),
79    (
80        IndexError,
81        "Can occur internally when information is not present at expected place"
82    ),
83    (
84        RequestError,
85        "Ask the wrong object for information and receive this error"
86    ),
87    (
88        CommunicationError,
89        "Error which occurs during sending, receiving or transmitting information between threads"
90    ),
91    (BoundaryError, "Can occur during boundary calculation"),
92    (
93        ControllerError,
94        "Occurs when incorrectly applying a controller effect"
95    ),
96    (DrawingError, "Used to catch errors related to plotting"),
97    (
98        RngError,
99        "Can occur when generating distributions or drawing samples from them."
100    )
101);
102
103impl From<String> for TimeError {
104    fn from(value: String) -> Self {
105        TimeError(value)
106    }
107}
108
109impl From<std::io::Error> for DecomposeError {
110    fn from(value: std::io::Error) -> Self {
111        DecomposeError::BoundaryError(BoundaryError(format!("{}", value)))
112    }
113}
114
115impl From<CalcError> for SetupError {
116    fn from(value: CalcError) -> Self {
117        SetupError(format!("{}", value))
118    }
119}
120
121#[cfg(feature = "plotters")]
122#[cfg_attr(docsrs, doc(cfg(feature = "plotters")))]
123impl<E> From<plotters::drawing::DrawingAreaErrorKind<E>> for DrawingError
124where
125    E: Error + Send + Sync,
126{
127    fn from(drawing_error: plotters::drawing::DrawingAreaErrorKind<E>) -> DrawingError {
128        DrawingError(drawing_error.to_string())
129    }
130}
131
132/// For internal use: formats an error message to include a link to the bug tracker on github.
133#[doc(hidden)]
134#[macro_export]
135macro_rules! format_error_message(
136    (@function) => {
137        {
138            fn f() {}
139            let name = std::any::type_name_of_val(&f);
140            name.strip_suffix("::f").unwrap()
141        }
142    };
143    ($bug_title:expr, $error_msg:expr) => {
144        {//#[cfg(debug_assertions)]
145         //TODO think about enabling these debug_assertions (performance difference unclear to me)
146        let __cr_private_error = {
147            let title = $bug_title.replace(" ", "%20");
148            let mut body = String::from($error_msg);
149            body = body + &format!("%0A%0AFile: {}", file!());
150            body = body + &format!("%0ALine: {}", line!());
151            body = body + &format!("%0AColumn: {}", column!());
152            body = body.replace(" ", "%20");
153            format!("Internal Error in file {} function {}: +++ {} +++ Please file a bug-report: \
154                https://github.com/jonaspleyer/cellular_raza/issues/new?\
155                title={}&body={}",
156                format_error_message!(@function),
157                file!(),
158                $error_msg,
159                title,
160                body,
161            )
162        };
163        //#[cfg(not(debug_assertions))]
164        //let __cr_private_error = format!("Encountered internal error: {} with message: \
165        //    {} Run in debug mode for more details.",
166        //    $bug_title,
167        //    $error_msg
168        //);
169        __cr_private_error
170        }
171    };
172);