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
use super::Joinable;
use super::LastErrorAffectable;
use crate::execution_step::execution_context::LastErrorObjectError;
use crate::execution_step::lambda_applier::LambdaError;
use crate::JValue;
use crate::ToErrorCode;
use strum::IntoEnumIterator;
use strum_macros::EnumDiscriminants;
use strum_macros::EnumIter;
use thiserror::Error as ThisError;
use std::rc::Rc;
#[derive(ThisError, EnumDiscriminants, Debug)]
#[strum_discriminants(derive(EnumIter))]
pub enum CatchableError {
#[error("Local service error, ret_code is {0}, error message is '{1}'")]
LocalServiceError(i32, Rc<String>),
#[error("variable with name '{0}' wasn't defined during script execution")]
VariableNotFound(String),
#[error(
"expected JValue type '{expected_value_type}' for the variable `{variable_name}`, but got '{actual_value}'"
)]
IncompatibleJValueType {
variable_name: String,
actual_value: JValue,
expected_value_type: &'static str,
},
#[error("expression '{1}' returned non-array value '{0}' for fold iterable")]
FoldIteratesOverNonArray(JValue, String),
#[error("match is used without corresponding xor")]
MatchValuesNotEqual,
#[error("mismatch is used without corresponding xor")]
MismatchValuesEqual,
#[error("fail with '{error}' is used without corresponding xor")]
UserError { error: Rc<JValue> },
#[error(transparent)]
LambdaApplierError(#[from] LambdaError),
#[error(transparent)]
InvalidLastErrorObjectError(#[from] LastErrorObjectError),
#[error("variable with name '{0}' was cleared by new and then wasn't set")]
VariableWasNotInitializedAfterNew(String),
#[error("the length functor could applied only to an array-like value, but it's applied to '{0}'")]
LengthFunctorAppliedToNotArray(JValue),
#[error("call cannot resolve non-String triplet variable part `{variable_name}` with value '{actual_value}'")]
NonStringValueInTripletResolution {
variable_name: String,
actual_value: JValue,
},
}
impl From<LambdaError> for Rc<CatchableError> {
fn from(e: LambdaError) -> Self {
Rc::new(CatchableError::LambdaApplierError(e))
}
}
impl ToErrorCode for Rc<CatchableError> {
fn to_error_code(&self) -> i64 {
self.as_ref().to_error_code()
}
}
impl ToErrorCode for CatchableError {
fn to_error_code(&self) -> i64 {
use crate::utils::CATCHABLE_ERRORS_START_ID;
crate::generate_to_error_code!(self, CatchableError, CATCHABLE_ERRORS_START_ID)
}
}
impl LastErrorAffectable for CatchableError {
fn affects_last_error(&self) -> bool {
!matches!(
self,
CatchableError::MatchValuesNotEqual | CatchableError::MismatchValuesEqual
)
}
}
macro_rules! log_join {
($($args:tt)*) => {
log::trace!(target: air_log_targets::JOIN_BEHAVIOUR, $($args)*)
}
}
#[rustfmt::skip::macros(log_join)]
impl Joinable for CatchableError {
fn is_joinable(&self) -> bool {
use CatchableError::*;
match self {
VariableNotFound(var_name) => {
log_join!(" waiting for an argument with name '{}'", var_name);
true
}
_ => false,
}
}
}