Skip to main content

ddb_core/functions/
registry.rs

1// Function registry - maps function names to implementations
2use super::Value;
3use crate::error::Result;
4use std::collections::HashMap;
5
6/// Function signature types
7#[derive(Debug, Clone)]
8pub enum FunctionSignature {
9    /// Function with no arguments
10    Nullary(fn() -> Value),
11    /// Function with one argument
12    Unary(fn(&Value) -> Result<Value>),
13    /// Function with two arguments
14    Binary(fn(&Value, &Value) -> Result<Value>),
15    /// Function with three arguments
16    Ternary(fn(&Value, &Value, &Value) -> Result<Value>),
17    /// Function with variable arguments
18    Variadic(fn(&[Value]) -> Result<Value>),
19    /// Function with optional second argument
20    UnaryOptional(fn(&Value, Option<&Value>) -> Result<Value>),
21    /// Aggregate function (operates on multiple values)
22    Aggregate(fn(&[Value]) -> Result<Value>),
23}
24
25/// Function metadata
26#[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
45/// Global function registry
46pub 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    /// Register a function
60    pub fn register(&mut self, info: FunctionInfo) {
61        let name = info.name.to_uppercase();
62        self.functions.insert(name, info);
63    }
64
65    /// Get function by name
66    pub fn get(&self, name: &str) -> Option<&FunctionInfo> {
67        self.functions.get(&name.to_uppercase())
68    }
69
70    /// List all functions
71    pub fn list(&self) -> Vec<&FunctionInfo> {
72        self.functions.values().collect()
73    }
74
75    /// List functions by category
76    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    /// Register all built-in functions
84    fn register_all(&mut self) {
85        // Math functions
86        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        // String functions
164        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        // Conversion functions
207        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        // Date/Time functions
236        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        // System functions
258        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        // Conditional functions
273        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        // Aggregate functions
302        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}