qml_rs/processing/
activator.rs

1//! Job activator for method invocation
2//!
3//! This module contains the JobActivator that provides a mechanism to invoke
4//! job methods dynamically. This is a foundation for future reflection-based
5//! job execution systems.
6
7use crate::error::{QmlError, Result};
8use std::collections::HashMap;
9
10/// Trait for activating and invoking job methods
11///
12/// This trait provides an abstraction for different ways of invoking job methods.
13/// Implementations might use reflection, function registries, or other mechanisms.
14pub trait JobActivator: Send + Sync {
15    /// Invoke a job method with the given arguments
16    fn invoke(&self, method: &str, arguments: &[String]) -> Result<String>;
17
18    /// Check if a method can be activated
19    fn can_activate(&self, method: &str) -> bool;
20}
21
22/// Simple function-based job activator
23///
24/// This activator uses a registry of function pointers to invoke job methods.
25/// It's a simple implementation suitable for basic use cases.
26pub struct FunctionActivator {
27    functions: HashMap<String, Box<dyn Fn(&[String]) -> Result<String> + Send + Sync>>,
28}
29
30impl FunctionActivator {
31    /// Create a new function activator
32    pub fn new() -> Self {
33        Self {
34            functions: HashMap::new(),
35        }
36    }
37
38    /// Register a function for a method name
39    pub fn register<F>(&mut self, method: String, function: F)
40    where
41        F: Fn(&[String]) -> Result<String> + Send + Sync + 'static,
42    {
43        self.functions.insert(method, Box::new(function));
44    }
45
46    /// Get the number of registered functions
47    pub fn len(&self) -> usize {
48        self.functions.len()
49    }
50
51    /// Check if any functions are registered
52    pub fn is_empty(&self) -> bool {
53        self.functions.is_empty()
54    }
55}
56
57impl Default for FunctionActivator {
58    fn default() -> Self {
59        Self::new()
60    }
61}
62
63impl JobActivator for FunctionActivator {
64    fn invoke(&self, method: &str, arguments: &[String]) -> Result<String> {
65        match self.functions.get(method) {
66            Some(function) => function(arguments),
67            None => Err(QmlError::WorkerError {
68                message: format!("No function registered for method: {}", method),
69            }),
70        }
71    }
72
73    fn can_activate(&self, method: &str) -> bool {
74        self.functions.contains_key(method)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_function_activator() {
84        let mut activator = FunctionActivator::new();
85
86        // Register a simple function
87        activator.register("greet".to_string(), |args| {
88            if args.is_empty() {
89                Ok("Hello, World!".to_string())
90            } else {
91                Ok(format!("Hello, {}!", args[0]))
92            }
93        });
94
95        // Test function invocation
96        assert!(activator.can_activate("greet"));
97        assert!(!activator.can_activate("unknown"));
98
99        let result = activator.invoke("greet", &[]).unwrap();
100        assert_eq!(result, "Hello, World!");
101
102        let result = activator.invoke("greet", &["Alice".to_string()]).unwrap();
103        assert_eq!(result, "Hello, Alice!");
104
105        // Test unknown method
106        assert!(activator.invoke("unknown", &[]).is_err());
107    }
108}