l_system_fractals/
errors.rs

1// src/errors.rs
2//
3// This file is part of l-system-fractals
4//
5// Copyright 2024 Christopher Phan
6//
7// See README.md in repository root directory for copyright/license info
8//
9// SPDX-License-Identifier: MIT OR Apache-2.0
10
11//! Provides an error type for the crate.
12use std::error::Error;
13use std::fmt;
14
15/// Combined error type for the crate.
16#[derive(Debug)]
17pub enum LSystemError {
18    /// Indicates division by zero attempted.
19    ///
20    /// # Example
21    ///
22    /// ```
23    /// use std::collections::HashMap;
24    ///
25    /// use l_system_fractals::rules::DrawRules;
26    ///
27    /// let dr = DrawRules::new_simple(
28    ///     HashMap::from([('A', "A-A+A-A".into())]),
29    ///     1,
30    ///     0 // denominator of a fraction
31    /// );
32    ///
33    /// assert!(dr.is_err());
34    ///
35    /// let err_msg = format!("{:?}", dr);
36    /// assert!(err_msg.contains("DivideByZero"));
37    /// ```
38    DivideByZero,
39    /// Indicates a float that is NaN or ±∞.
40    ///
41    /// These do not make sense in the context of SVG coordinates.
42    ///
43    /// This error is raised by, e.g., [`crate::num_validity::err_if_invalid`].
44    ///
45    /// # Example
46    ///
47    /// ```
48    /// use l_system_fractals::num_validity::err_if_invalid;
49    ///
50    /// let x = err_if_invalid(f64::NAN);
51    ///
52    /// let err_msg = format!("{:?}", x);
53    /// assert!(err_msg.contains("InvalidFloat"));
54    /// ```
55    InvalidFloat,
56    /// Indicates that no bounding box could be computed in a context where it is required.
57    ///
58    /// This error is raised by, e.g., [`crate::paths::Path::bounding_box`].
59    ///
60    /// # Example
61    ///
62    /// ```
63    /// use l_system_fractals::paths::{Path, Point};
64    ///
65    /// let empty_vec: Vec<Point> = vec![];
66    /// let empty_path = Path::from(empty_vec);
67    /// let bb = empty_path.bounding_box();
68    ///
69    /// let err_msg = format!("{:?}", bb);
70    /// assert!(err_msg.contains("NoBoundingBox"));
71    /// ```
72    NoBoundingBox,
73    /// Indicates a file system error (e.g. incorrect file name).
74    FileSystemError(Box<dyn Error>),
75    /// Indicates a problem in the deserialization process (e.g. malformed JSON).
76    DeserializationError(Box<dyn Error>),
77}
78
79impl fmt::Display for LSystemError {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        match self {
82            Self::DivideByZero => write!(f, "divide by zero error"),
83            Self::InvalidFloat => write!(f, "float is NaN or +/-INF"),
84            Self::NoBoundingBox => write!(f, "no bounding box"),
85            Self::FileSystemError(e) => write!(f, "file system error: {}", e),
86            Self::DeserializationError(e) => write!(f, "deserialization error: {}", e),
87        }
88    }
89}
90
91impl Error for LSystemError {}