reifydb_routine/function/
error.rs1use reifydb_type::{
5 error::{Diagnostic, Error, IntoDiagnostic, TypeError},
6 fragment::Fragment,
7 value::r#type::Type,
8};
9
10#[derive(Debug, thiserror::Error)]
11pub enum FunctionError {
12 #[error("function {} expects {expected} arguments, got {actual}", function.text())]
13 ArityMismatch {
14 function: Fragment,
15 expected: usize,
16 actual: usize,
17 },
18
19 #[error("function {} argument {} has invalid type: got {actual:?}", function.text(), argument_index + 1)]
20 InvalidArgumentType {
21 function: Fragment,
22 argument_index: usize,
23 expected: Vec<Type>,
24 actual: Type,
25 },
26
27 #[error("function {} execution failed: {reason}", function.text())]
28 ExecutionFailed {
29 function: Fragment,
30 reason: String,
31 },
32
33 #[error("generator function '{}' not found", function.text())]
34 NotFound {
35 function: Fragment,
36 },
37
38 #[error(transparent)]
39 Wrapped(Box<Error>),
40}
41
42impl From<Error> for FunctionError {
43 fn from(err: Error) -> Self {
44 FunctionError::Wrapped(Box::new(err))
45 }
46}
47
48impl From<TypeError> for FunctionError {
49 fn from(err: TypeError) -> Self {
50 FunctionError::Wrapped(Box::new(Error::from(err)))
51 }
52}
53
54impl From<Box<TypeError>> for FunctionError {
55 fn from(err: Box<TypeError>) -> Self {
56 FunctionError::Wrapped(Box::new(Error::from(err)))
57 }
58}
59
60impl FunctionError {
61 pub fn with_context(self, function: Fragment) -> Error {
65 match self {
66 FunctionError::Wrapped(inner) => {
67 let name = function.text().to_string();
68 let mut cause = *inner.0;
69 cause.with_fragment(function.clone());
70 Error(Box::new(Diagnostic {
71 code: "FUNCTION_007".to_string(),
72 statement: None,
73 message: format!("Function {} execution failed", name),
74 column: None,
75 fragment: function,
76 label: Some("execution failed".to_string()),
77 help: Some("Check function arguments and data".to_string()),
78 notes: vec![],
79 cause: Some(Box::new(cause)),
80 operator_chain: None,
81 }))
82 }
83 other => Error(Box::new(other.into_diagnostic())),
84 }
85 }
86}
87
88impl From<FunctionError> for Error {
89 fn from(err: FunctionError) -> Self {
90 Error(Box::new(err.into_diagnostic()))
91 }
92}
93
94impl IntoDiagnostic for FunctionError {
95 fn into_diagnostic(self) -> Diagnostic {
96 match self {
97 FunctionError::ArityMismatch {
98 function,
99 expected,
100 actual,
101 } => {
102 let name = function.text().to_string();
103 Diagnostic {
104 code: "FUNCTION_002".to_string(),
105 statement: None,
106 message: format!(
107 "Function {} expects {} arguments, got {}",
108 name, expected, actual
109 ),
110 column: None,
111 fragment: function,
112 label: Some("wrong number of arguments".to_string()),
113 help: Some(format!(
114 "Provide exactly {} arguments to function {}",
115 expected, name
116 )),
117 notes: vec![],
118 cause: None,
119 operator_chain: None,
120 }
121 }
122 FunctionError::InvalidArgumentType {
123 function,
124 argument_index,
125 expected,
126 actual,
127 } => {
128 let name = function.text().to_string();
129 let expected_types =
130 expected.iter().map(|t| format!("{:?}", t)).collect::<Vec<_>>().join(", ");
131 Diagnostic {
132 code: "FUNCTION_004".to_string(),
133 statement: None,
134 message: format!(
135 "Function {} argument {} has invalid type: expected one of [{}], got {:?}",
136 name,
137 argument_index + 1,
138 expected_types,
139 actual
140 ),
141 column: None,
142 fragment: function,
143 label: Some("invalid argument type".to_string()),
144 help: Some(format!("Provide an argument of type: {}", expected_types)),
145 notes: vec![],
146 cause: None,
147 operator_chain: None,
148 }
149 }
150 FunctionError::ExecutionFailed {
151 function,
152 reason,
153 } => {
154 let name = function.text().to_string();
155 Diagnostic {
156 code: "FUNCTION_007".to_string(),
157 statement: None,
158 message: format!("Function {} execution failed: {}", name, reason),
159 column: None,
160 fragment: function,
161 label: Some("execution failed".to_string()),
162 help: Some("Check function arguments and data".to_string()),
163 notes: vec![],
164 cause: None,
165 operator_chain: None,
166 }
167 }
168 FunctionError::NotFound {
169 function,
170 } => {
171 let name = function.text().to_string();
172 Diagnostic {
173 code: "FUNCTION_009".to_string(),
174 statement: None,
175 message: format!("Generator function '{}' not found", name),
176 column: None,
177 fragment: function,
178 label: Some("unknown generator function".to_string()),
179 help: Some("Check the generator function name and ensure it is registered"
180 .to_string()),
181 notes: vec![],
182 cause: None,
183 operator_chain: None,
184 }
185 }
186 FunctionError::Wrapped(err) => *err.0,
187 }
188 }
189}