1use super::Value;
3use crate::error::Result;
4use std::collections::HashMap;
5
6#[derive(Debug, Clone)]
8pub enum FunctionSignature {
9 Nullary(fn() -> Value),
11 Unary(fn(&Value) -> Result<Value>),
13 Binary(fn(&Value, &Value) -> Result<Value>),
15 Ternary(fn(&Value, &Value, &Value) -> Result<Value>),
17 Variadic(fn(&[Value]) -> Result<Value>),
19 UnaryOptional(fn(&Value, Option<&Value>) -> Result<Value>),
21 Aggregate(fn(&[Value]) -> Result<Value>),
23}
24
25#[derive(Debug, Clone)]
27pub struct FunctionInfo {
28 pub name: String,
29 pub signature: FunctionSignature,
30 pub description: String,
31 pub category: FunctionCategory,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub enum FunctionCategory {
36 Math,
37 String,
38 Conversion,
39 DateTime,
40 System,
41 Conditional,
42 Aggregate,
43}
44
45pub struct FunctionRegistry {
47 functions: HashMap<String, FunctionInfo>,
48}
49
50impl FunctionRegistry {
51 pub fn new() -> Self {
52 let mut registry = Self {
53 functions: HashMap::new(),
54 };
55 registry.register_all();
56 registry
57 }
58
59 pub fn register(&mut self, info: FunctionInfo) {
61 let name = info.name.to_uppercase();
62 self.functions.insert(name, info);
63 }
64
65 pub fn get(&self, name: &str) -> Option<&FunctionInfo> {
67 self.functions.get(&name.to_uppercase())
68 }
69
70 pub fn list(&self) -> Vec<&FunctionInfo> {
72 self.functions.values().collect()
73 }
74
75 pub fn list_by_category(&self, category: FunctionCategory) -> Vec<&FunctionInfo> {
77 self.functions
78 .values()
79 .filter(|f| f.category == category)
80 .collect()
81 }
82
83 fn register_all(&mut self) {
85 self.register(FunctionInfo {
87 name: "ABS".to_string(),
88 signature: FunctionSignature::Unary(super::math::abs),
89 description: "Absolute value".to_string(),
90 category: FunctionCategory::Math,
91 });
92
93 self.register(FunctionInfo {
94 name: "CEIL".to_string(),
95 signature: FunctionSignature::Unary(super::math::ceil),
96 description: "Round up to nearest integer".to_string(),
97 category: FunctionCategory::Math,
98 });
99
100 self.register(FunctionInfo {
101 name: "FLOOR".to_string(),
102 signature: FunctionSignature::Unary(super::math::floor),
103 description: "Round down to nearest integer".to_string(),
104 category: FunctionCategory::Math,
105 });
106
107 self.register(FunctionInfo {
108 name: "SQRT".to_string(),
109 signature: FunctionSignature::Unary(super::math::sqrt),
110 description: "Square root".to_string(),
111 category: FunctionCategory::Math,
112 });
113
114 self.register(FunctionInfo {
115 name: "POW".to_string(),
116 signature: FunctionSignature::Binary(super::math::pow),
117 description: "Power (x^y)".to_string(),
118 category: FunctionCategory::Math,
119 });
120
121 self.register(FunctionInfo {
122 name: "EXP".to_string(),
123 signature: FunctionSignature::Unary(super::math::exp),
124 description: "e^x".to_string(),
125 category: FunctionCategory::Math,
126 });
127
128 self.register(FunctionInfo {
129 name: "LN".to_string(),
130 signature: FunctionSignature::Unary(super::math::ln),
131 description: "Natural logarithm".to_string(),
132 category: FunctionCategory::Math,
133 });
134
135 self.register(FunctionInfo {
136 name: "LOG10".to_string(),
137 signature: FunctionSignature::Unary(super::math::log10),
138 description: "Base-10 logarithm".to_string(),
139 category: FunctionCategory::Math,
140 });
141
142 self.register(FunctionInfo {
143 name: "MOD".to_string(),
144 signature: FunctionSignature::Binary(super::math::modulo),
145 description: "Modulo operation".to_string(),
146 category: FunctionCategory::Math,
147 });
148
149 self.register(FunctionInfo {
150 name: "SIGN".to_string(),
151 signature: FunctionSignature::Unary(super::math::sign),
152 description: "Sign of number (-1, 0, 1)".to_string(),
153 category: FunctionCategory::Math,
154 });
155
156 self.register(FunctionInfo {
157 name: "PI".to_string(),
158 signature: FunctionSignature::Nullary(super::math::pi),
159 description: "Pi constant".to_string(),
160 category: FunctionCategory::Math,
161 });
162
163 self.register(FunctionInfo {
165 name: "CONCAT".to_string(),
166 signature: FunctionSignature::Variadic(super::string::concat),
167 description: "Concatenate strings".to_string(),
168 category: FunctionCategory::String,
169 });
170
171 self.register(FunctionInfo {
172 name: "UPPER".to_string(),
173 signature: FunctionSignature::Unary(super::string::upper),
174 description: "Convert to uppercase".to_string(),
175 category: FunctionCategory::String,
176 });
177
178 self.register(FunctionInfo {
179 name: "LOWER".to_string(),
180 signature: FunctionSignature::Unary(super::string::lower),
181 description: "Convert to lowercase".to_string(),
182 category: FunctionCategory::String,
183 });
184
185 self.register(FunctionInfo {
186 name: "LENGTH".to_string(),
187 signature: FunctionSignature::Unary(super::string::length),
188 description: "String length".to_string(),
189 category: FunctionCategory::String,
190 });
191
192 self.register(FunctionInfo {
193 name: "TRIM".to_string(),
194 signature: FunctionSignature::Unary(super::string::trim),
195 description: "Remove whitespace".to_string(),
196 category: FunctionCategory::String,
197 });
198
199 self.register(FunctionInfo {
200 name: "REVERSE".to_string(),
201 signature: FunctionSignature::Unary(super::string::reverse),
202 description: "Reverse string".to_string(),
203 category: FunctionCategory::String,
204 });
205
206 self.register(FunctionInfo {
208 name: "ATOF".to_string(),
209 signature: FunctionSignature::Unary(super::conversion::atof),
210 description: "ASCII to float".to_string(),
211 category: FunctionCategory::Conversion,
212 });
213
214 self.register(FunctionInfo {
215 name: "ATOI".to_string(),
216 signature: FunctionSignature::Unary(super::conversion::atoi),
217 description: "ASCII to integer".to_string(),
218 category: FunctionCategory::Conversion,
219 });
220
221 self.register(FunctionInfo {
222 name: "HEX".to_string(),
223 signature: FunctionSignature::Unary(super::conversion::hex),
224 description: "Convert to hexadecimal".to_string(),
225 category: FunctionCategory::Conversion,
226 });
227
228 self.register(FunctionInfo {
229 name: "BIN".to_string(),
230 signature: FunctionSignature::Unary(super::conversion::bin),
231 description: "Convert to binary".to_string(),
232 category: FunctionCategory::Conversion,
233 });
234
235 self.register(FunctionInfo {
237 name: "NOW".to_string(),
238 signature: FunctionSignature::Nullary(super::datetime::now),
239 description: "Current date and time".to_string(),
240 category: FunctionCategory::DateTime,
241 });
242
243 self.register(FunctionInfo {
244 name: "CURDATE".to_string(),
245 signature: FunctionSignature::Nullary(super::datetime::curdate),
246 description: "Current date".to_string(),
247 category: FunctionCategory::DateTime,
248 });
249
250 self.register(FunctionInfo {
251 name: "CURTIME".to_string(),
252 signature: FunctionSignature::Nullary(super::datetime::curtime),
253 description: "Current time".to_string(),
254 category: FunctionCategory::DateTime,
255 });
256
257 self.register(FunctionInfo {
259 name: "VERSION".to_string(),
260 signature: FunctionSignature::Nullary(super::system::version),
261 description: "DDB version".to_string(),
262 category: FunctionCategory::System,
263 });
264
265 self.register(FunctionInfo {
266 name: "UUID".to_string(),
267 signature: FunctionSignature::Nullary(super::system::uuid),
268 description: "Generate UUID".to_string(),
269 category: FunctionCategory::System,
270 });
271
272 self.register(FunctionInfo {
274 name: "IF".to_string(),
275 signature: FunctionSignature::Ternary(super::conditional::if_fn),
276 description: "Conditional expression".to_string(),
277 category: FunctionCategory::Conditional,
278 });
279
280 self.register(FunctionInfo {
281 name: "IFNULL".to_string(),
282 signature: FunctionSignature::Binary(super::conditional::ifnull),
283 description: "Return alt if NULL".to_string(),
284 category: FunctionCategory::Conditional,
285 });
286
287 self.register(FunctionInfo {
288 name: "NULLIF".to_string(),
289 signature: FunctionSignature::Binary(super::conditional::nullif),
290 description: "Return NULL if equal".to_string(),
291 category: FunctionCategory::Conditional,
292 });
293
294 self.register(FunctionInfo {
295 name: "COALESCE".to_string(),
296 signature: FunctionSignature::Variadic(super::conditional::coalesce),
297 description: "First non-NULL value".to_string(),
298 category: FunctionCategory::Conditional,
299 });
300
301 self.register(FunctionInfo {
303 name: "MAX".to_string(),
304 signature: FunctionSignature::Aggregate(super::aggregate::max),
305 description: "Maximum value".to_string(),
306 category: FunctionCategory::Aggregate,
307 });
308
309 self.register(FunctionInfo {
310 name: "MIN".to_string(),
311 signature: FunctionSignature::Aggregate(super::aggregate::min),
312 description: "Minimum value".to_string(),
313 category: FunctionCategory::Aggregate,
314 });
315 }
316}
317
318impl Default for FunctionRegistry {
319 fn default() -> Self {
320 Self::new()
321 }
322}
323
324#[cfg(test)]
325mod tests {
326 use super::*;
327
328 #[test]
329 fn test_registry() {
330 let registry = FunctionRegistry::new();
331
332 assert!(registry.get("ABS").is_some());
333 assert!(registry.get("CONCAT").is_some());
334 assert!(registry.get("NOW").is_some());
335 assert!(registry.get("nonexistent").is_none());
336 }
337
338 #[test]
339 fn test_category_filter() {
340 let registry = FunctionRegistry::new();
341 let math_funcs = registry.list_by_category(FunctionCategory::Math);
342 assert!(!math_funcs.is_empty());
343 }
344}