espresso_logic/expression/
error.rs

1//! Error types for boolean expression parsing
2
3use std::fmt;
4use std::io;
5use std::sync::Arc;
6
7/// Errors related to boolean expression parsing
8///
9/// These errors occur when parsing a boolean expression string fails.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum ExpressionParseError {
12    /// Failed to parse a boolean expression due to invalid syntax
13    InvalidSyntax {
14        /// The error message from the parser
15        message: Arc<str>,
16        /// The original input string that failed to parse
17        input: Arc<str>,
18        /// Optional position in the input where the error occurred
19        position: Option<usize>,
20    },
21}
22
23impl fmt::Display for ExpressionParseError {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match self {
26            ExpressionParseError::InvalidSyntax {
27                message,
28                input,
29                position,
30            } => {
31                if let Some(pos) = position {
32                    write!(
33                        f,
34                        "Failed to parse boolean expression at position {}: {}. Input: {:?}",
35                        pos, message, input
36                    )
37                } else {
38                    write!(
39                        f,
40                        "Failed to parse boolean expression: {}. Input: {:?}",
41                        message, input
42                    )
43                }
44            }
45        }
46    }
47}
48
49impl std::error::Error for ExpressionParseError {}
50
51impl From<ExpressionParseError> for io::Error {
52    fn from(err: ExpressionParseError) -> Self {
53        io::Error::new(io::ErrorKind::InvalidData, err)
54    }
55}
56
57/// Errors that can occur when parsing a boolean expression
58///
59/// This error type is returned by `BoolExpr::parse()`.
60#[derive(Debug)]
61pub enum ParseBoolExprError {
62    /// Expression parsing error
63    Parse(ExpressionParseError),
64}
65
66impl fmt::Display for ParseBoolExprError {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        match self {
69            ParseBoolExprError::Parse(e) => write!(f, "{}", e),
70        }
71    }
72}
73
74impl std::error::Error for ParseBoolExprError {
75    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
76        match self {
77            ParseBoolExprError::Parse(e) => Some(e),
78        }
79    }
80}
81
82impl From<ExpressionParseError> for ParseBoolExprError {
83    fn from(err: ExpressionParseError) -> Self {
84        ParseBoolExprError::Parse(err)
85    }
86}
87
88impl From<ParseBoolExprError> for io::Error {
89    fn from(err: ParseBoolExprError) -> Self {
90        match err {
91            ParseBoolExprError::Parse(e) => io::Error::new(io::ErrorKind::InvalidData, e),
92        }
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn test_expression_parse_error_with_position() {
102        let err = ExpressionParseError::InvalidSyntax {
103            message: Arc::from("unexpected token"),
104            input: Arc::from("a * b ++"),
105            position: Some(6),
106        };
107        let msg = err.to_string();
108        assert!(msg.contains("position 6"));
109        assert!(msg.contains("unexpected token"));
110    }
111
112    #[test]
113    fn test_expression_parse_error_without_position() {
114        let err = ExpressionParseError::InvalidSyntax {
115            message: Arc::from("unexpected end"),
116            input: Arc::from("a * b +"),
117            position: None,
118        };
119        let msg = err.to_string();
120        assert!(!msg.contains("position"));
121        assert!(msg.contains("unexpected end"));
122    }
123
124    #[test]
125    fn test_parse_bool_expr_error() {
126        let parse_err = ExpressionParseError::InvalidSyntax {
127            message: Arc::from("test"),
128            input: Arc::from("bad input"),
129            position: Some(5),
130        };
131        let bool_err: ParseBoolExprError = parse_err.into();
132        assert!(matches!(bool_err, ParseBoolExprError::Parse(_)));
133    }
134
135    #[test]
136    fn test_expression_parse_error_to_io_error() {
137        let err = ExpressionParseError::InvalidSyntax {
138            message: Arc::from("test"),
139            input: Arc::from("bad input"),
140            position: Some(5),
141        };
142        let io_err: io::Error = err.into();
143        assert_eq!(io_err.kind(), io::ErrorKind::InvalidData);
144    }
145
146    #[test]
147    fn test_parse_bool_expr_error_to_io_error() {
148        let parse_err = ExpressionParseError::InvalidSyntax {
149            message: Arc::from("test"),
150            input: Arc::from("bad input"),
151            position: Some(5),
152        };
153        let bool_err = ParseBoolExprError::Parse(parse_err);
154        let io_err: io::Error = bool_err.into();
155        assert_eq!(io_err.kind(), io::ErrorKind::InvalidData);
156    }
157}