1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
//! The `error` module contains the `Error` enum that contains all error types used by this crate. //! //! The `Error` enum implements constructors for its struct variants, because those are ugly to construct. //! //! The module also contains some helper functions starting with `expect_` that check for a condition and return `Err(_)` if the condition is not fulfilled. //! They are meant as shortcuts to not write the same error checking code everywhere. use token::PartialToken; use value::{value_type::ValueType, TupleType}; use crate::value::Value; mod display; /// Errors used in this crate. #[derive(Debug, PartialEq)] pub enum EvalexprError { /// An operator was called with a wrong amount of arguments. WrongOperatorArgumentAmount { /// The expected amount of arguments. expected: usize, /// The actual amount of arguments. actual: usize, }, /// A function was called with a wrong amount of arguments. WrongFunctionArgumentAmount { /// The expected amount of arguments. expected: usize, /// The actual amount of arguments. actual: usize, }, /// A string value was expected. ExpectedString { /// The actual value. actual: Value, }, /// An integer value was expected. ExpectedInt { /// The actual value. actual: Value, }, /// A float value was expected. ExpectedFloat { /// The actual value. actual: Value, }, /// A numeric value was expected. /// Numeric values are the variants `Value::Int` and `Value::Float`. ExpectedNumber { /// The actual value. actual: Value, }, /// A numeric or string value was expected. /// Numeric values are the variants `Value::Int` and `Value::Float`. ExpectedNumberOrString { /// The actual value. actual: Value, }, /// A boolean value was expected. ExpectedBoolean { /// The actual value. actual: Value, }, /// A tuple value was expected. ExpectedTuple { /// The actual value. actual: Value, }, /// An empty value was expected. ExpectedEmpty { /// The actual value. actual: Value, }, /// Tried to append a child to a leaf node. /// Leaf nodes cannot have children. AppendedToLeafNode, /// Tried to append a child to a node such that the precedence of the child is not higher. /// This error should never occur. /// If it does, please file a bug report. PrecedenceViolation, /// A `VariableIdentifier` operation did not find its value in the context. VariableIdentifierNotFound(String), /// A `FunctionIdentifier` operation did not find its value in the context. FunctionIdentifierNotFound(String), /// A value has the wrong type. /// Only use this if there is no other error that describes the expected and provided types in more detail. TypeError { /// The expected types. expected: TupleType, /// The actual value. actual: Value, }, /// An opening brace without a matching closing brace was found. UnmatchedLBrace, /// A closing brace without a matching opening brace was found. UnmatchedRBrace, /// A `PartialToken` is unmatched, such that it cannot be combined into a full `Token`. /// This happens if for example a single `=` is found, surrounded by whitespace. /// It is not a token, but it is part of the string representation of some tokens. UnmatchedPartialToken { /// The unmatched partial token. first: PartialToken, /// The token that follows the unmatched partial token and that cannot be matched to the partial token, or `None`, if `first` is the last partial token in the stream. second: Option<PartialToken>, }, /// An addition operation performed by Rust failed. AdditionError { /// The first argument of the addition. augend: Value, /// The second argument of the addition. addend: Value, }, /// A subtraction operation performed by Rust failed. SubtractionError { /// The first argument of the subtraction. minuend: Value, /// The second argument of the subtraction. subtrahend: Value, }, /// A negation operation performed by Rust failed. NegationError { /// The argument of the negation. argument: Value, }, /// A multiplication operation performed by Rust failed. MultiplicationError { /// The first argument of the multiplication. multiplicand: Value, /// The second argument of the multiplication. multiplier: Value, }, /// A division operation performed by Rust failed. DivisionError { /// The first argument of the division. dividend: Value, /// The second argument of the division. divisor: Value, }, /// A modulation operation performed by Rust failed. ModulationError { /// The first argument of the modulation. dividend: Value, /// The second argument of the modulation. divisor: Value, }, /// A regular expression could not be parsed InvalidRegex { /// The invalid regular expression regex: String, /// Failure message from the regex engine message: String, }, /// A modification was attempted on a `Context` that does not allow modifications. ContextNotManipulable, /// An escape sequence within a string literal is illegal. IllegalEscapeSequence(String), /// A custom error explained by its message. CustomMessage(String), } impl EvalexprError { pub(crate) fn wrong_operator_argument_amount(actual: usize, expected: usize) -> Self { EvalexprError::WrongOperatorArgumentAmount { actual, expected } } pub(crate) fn wrong_function_argument_amount(actual: usize, expected: usize) -> Self { EvalexprError::WrongFunctionArgumentAmount { actual, expected } } /// Constructs `Error::TypeError{actual, expected}`. pub fn type_error(actual: Value, expected: TupleType) -> Self { EvalexprError::TypeError { actual, expected } } /// Constructs `Error::ExpectedString{actual}`. pub fn expected_string(actual: Value) -> Self { EvalexprError::ExpectedString { actual } } /// Constructs `Error::ExpectedInt{actual}`. pub fn expected_int(actual: Value) -> Self { EvalexprError::ExpectedInt { actual } } /// Constructs `Error::ExpectedFloat{actual}`. pub fn expected_float(actual: Value) -> Self { EvalexprError::ExpectedFloat { actual } } /// Constructs `Error::ExpectedNumber{actual}`. pub fn expected_number(actual: Value) -> Self { EvalexprError::ExpectedNumber { actual } } /// Constructs `Error::ExpectedNumberOrString{actual}`. pub fn expected_number_or_string(actual: Value) -> Self { EvalexprError::ExpectedNumberOrString { actual } } /// Constructs `Error::ExpectedBoolean{actual}`. pub fn expected_boolean(actual: Value) -> Self { EvalexprError::ExpectedBoolean { actual } } /// Constructs `Error::ExpectedTuple{actual}`. pub fn expected_tuple(actual: Value) -> Self { EvalexprError::ExpectedTuple { actual } } /// Constructs `Error::ExpectedEmpty{actual}`. pub fn expected_empty(actual: Value) -> Self { EvalexprError::ExpectedEmpty { actual } } /// Constructs an error that expresses that the type of `expected` was expected, but `actual` was found. pub(crate) fn expected_type(expected: &Value, actual: Value) -> Self { match ValueType::from(expected) { ValueType::String => Self::expected_string(actual), ValueType::Int => Self::expected_int(actual), ValueType::Float => Self::expected_float(actual), ValueType::Boolean => Self::expected_boolean(actual), ValueType::Tuple => Self::expected_tuple(actual), ValueType::Empty => Self::expected_empty(actual), } } pub(crate) fn unmatched_partial_token( first: PartialToken, second: Option<PartialToken>, ) -> Self { EvalexprError::UnmatchedPartialToken { first, second } } pub(crate) fn addition_error(augend: Value, addend: Value) -> Self { EvalexprError::AdditionError { augend, addend } } pub(crate) fn subtraction_error(minuend: Value, subtrahend: Value) -> Self { EvalexprError::SubtractionError { minuend, subtrahend, } } pub(crate) fn negation_error(argument: Value) -> Self { EvalexprError::NegationError { argument } } pub(crate) fn multiplication_error(multiplicand: Value, multiplier: Value) -> Self { EvalexprError::MultiplicationError { multiplicand, multiplier, } } pub(crate) fn division_error(dividend: Value, divisor: Value) -> Self { EvalexprError::DivisionError { dividend, divisor } } pub(crate) fn modulation_error(dividend: Value, divisor: Value) -> Self { EvalexprError::ModulationError { dividend, divisor } } /// Constructs `EvalexprError::InvalidRegex(regex)` pub fn invalid_regex(regex: String, message: String) -> Self { EvalexprError::InvalidRegex { regex, message } } } /// Returns `Ok(())` if the actual and expected parameters are equal, and `Err(Error::WrongOperatorArgumentAmount)` otherwise. pub(crate) fn expect_operator_argument_amount( actual: usize, expected: usize, ) -> EvalexprResult<()> { if actual == expected { Ok(()) } else { Err(EvalexprError::wrong_operator_argument_amount( actual, expected, )) } } /// Returns `Ok(())` if the actual and expected parameters are equal, and `Err(Error::WrongFunctionArgumentAmount)` otherwise. pub fn expect_function_argument_amount(actual: usize, expected: usize) -> EvalexprResult<()> { if actual == expected { Ok(()) } else { Err(EvalexprError::wrong_function_argument_amount( actual, expected, )) } } /// Returns `Ok(&str)` if the given value is a `Value::String`, or `Err(Error::ExpectedString)` otherwise. pub fn expect_string(actual: &Value) -> EvalexprResult<&str> { match actual { Value::String(string) => Ok(string), _ => Err(EvalexprError::expected_string(actual.clone())), } } /// Returns `Ok(())` if the given value is numeric. /// Numeric types are `Value::Int` and `Value::Float`. /// Otherwise, `Err(Error::ExpectedNumber)` is returned. pub fn expect_number(actual: &Value) -> EvalexprResult<()> { match actual { Value::Float(_) | Value::Int(_) => Ok(()), _ => Err(EvalexprError::expected_number(actual.clone())), } } /// Returns `Ok(())` if the given value is a string or a numeric pub fn expect_number_or_string(actual: &Value) -> EvalexprResult<()> { match actual { Value::String(_) | Value::Float(_) | Value::Int(_) => Ok(()), _ => Err(EvalexprError::expected_number_or_string(actual.clone())), } } /// Returns `Ok(bool)` if the given value is a `Value::Boolean`, or `Err(Error::ExpectedBoolean)` otherwise. pub fn expect_boolean(actual: &Value) -> EvalexprResult<bool> { match actual { Value::Boolean(boolean) => Ok(*boolean), _ => Err(EvalexprError::expected_boolean(actual.clone())), } } impl std::error::Error for EvalexprError {} /// Standard result type used by this crate. pub type EvalexprResult<T> = Result<T, EvalexprError>;