datalogic_rs/logic/
error.rs1use std::error::Error;
6use std::fmt;
7use std::result;
8
9pub type Result<T> = result::Result<T, LogicError>;
11
12#[derive(Debug, Clone, PartialEq)]
14pub enum LogicError {
15 ParseError {
17 reason: String,
19 },
20
21 VariableError {
23 path: String,
25 reason: String,
27 },
28
29 OperatorNotFoundError {
31 operator: String,
33 },
34
35 NaNError,
36
37 InvalidArgumentsError,
38
39 ThrownError {
41 r#type: String,
43 },
44
45 Custom(String),
47}
48
49impl fmt::Display for LogicError {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match self {
52 LogicError::ParseError { reason } => {
53 write!(f, "Parse error: {}", reason)
54 }
55 LogicError::VariableError { path, reason } => {
56 write!(f, "Variable '{}' error: {}", path, reason)
57 }
58 LogicError::NaNError => {
59 write!(f, "NaN error")
60 }
61 LogicError::InvalidArgumentsError => {
62 write!(f, "Invalid arguments error")
63 }
64 LogicError::ThrownError { r#type } => {
65 write!(f, "Thrown error: {}", r#type)
66 }
67 LogicError::Custom(msg) => {
68 write!(f, "{}", msg)
69 }
70 LogicError::OperatorNotFoundError { operator } => {
71 write!(f, "Operator '{}' not found", operator)
72 }
73 }
74 }
75}
76
77impl Error for LogicError {}
78
79pub trait LogicResultExt<T> {
81 fn with_context<F>(self, f: F) -> Result<T>
83 where
84 F: FnOnce() -> String;
85}
86
87impl<T> LogicResultExt<T> for Result<T> {
88 fn with_context<F>(self, f: F) -> Result<T>
89 where
90 F: FnOnce() -> String,
91 {
92 self.map_err(|err| {
93 let context = f();
94 LogicError::Custom(format!("{}: {}", context, err))
95 })
96 }
97}
98
99impl LogicError {
100 pub fn parse_error(reason: impl Into<String>) -> Self {
102 LogicError::ParseError {
103 reason: reason.into(),
104 }
105 }
106
107 pub fn variable_error(path: impl Into<String>, reason: impl Into<String>) -> Self {
109 LogicError::VariableError {
110 path: path.into(),
111 reason: reason.into(),
112 }
113 }
114
115 pub fn thrown_error(r#type: impl Into<String>) -> Self {
117 LogicError::ThrownError {
118 r#type: r#type.into(),
119 }
120 }
121
122 pub fn custom(message: impl Into<String>) -> Self {
124 LogicError::Custom(message.into())
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_parse_error() {
134 let err = LogicError::ParseError {
135 reason: "unexpected token".to_string(),
136 };
137 assert_eq!(err.to_string(), "Parse error: unexpected token");
138 }
139
140 #[test]
141 fn test_variable_error() {
142 let err = LogicError::VariableError {
143 path: "user.age".to_string(),
144 reason: "not found".to_string(),
145 };
146 assert_eq!(err.to_string(), "Variable 'user.age' error: not found");
147 }
148
149 #[test]
150 fn test_with_context() {
151 let result: Result<()> = Err(LogicError::ParseError {
152 reason: "unexpected token".to_string(),
153 });
154
155 let result_with_context =
156 result.with_context(|| "Failed to parse logic expression".to_string());
157
158 assert!(result_with_context.is_err());
159 if let Err(err) = result_with_context {
160 if let LogicError::Custom(msg) = err {
161 assert_eq!(
162 msg,
163 "Failed to parse logic expression: Parse error: unexpected token"
164 );
165 } else {
166 panic!("Expected Custom error variant");
167 }
168 }
169 }
170}