use super::{FfiError, FfiFunction, RegisteredFunction, FfiStats, FfiSignature};
use super::builtin_ffi_module::BuiltinFfiModule;
use super::registry::FfiModule;
use crate::eval::Value;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
#[derive(Debug, Default)]
pub struct FfiRegistry {
functions: RwLock<HashMap<String, RegisteredFunction>>,
stats: RwLock<FfiStats>,
}
impl FfiRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn with_builtins() -> Self {
let registry = Self::new();
registry.register_builtins();
registry
}
pub fn register<F>(&self, function: F) -> std::result::Result<(), FfiError>
where
F: FfiFunction + 'static,
{
let name = function.signature().name.clone();
let registered_fn = RegisteredFunction {
function: Arc::new(function),
registered_at: std::time::SystemTime::now(),
};
{
let mut functions = self.functions.write().unwrap();
functions.insert(name, registered_fn);
}
{
let mut stats = self.stats.write().unwrap();
stats.registered_functions = self.functions.read().unwrap().len();
}
Ok(())
}
pub fn call(&self, name: &str, args: &[Value]) -> std::result::Result<Value, FfiError> {
let function = {
let functions = self.functions.read().unwrap();
functions.get(name).cloned()
};
let function = function.ok_or_else(|| FfiError::FunctionNotFound(name.to_string()))?;
{
let mut stats = self.stats.write().unwrap();
stats.total_calls += 1;
}
function.function.validate_args(args)?;
let result = function.function.call(args);
{
let mut stats = self.stats.write().unwrap();
match &result {
Ok(_) => stats.successful_calls += 1,
Err(_) => stats.failed_calls += 1,
}
}
result
}
pub fn get_function_info(&self, name: &str) -> Option<FfiSignature> {
let functions = self.functions.read().unwrap();
functions.get(name).map(|f| f.function.signature().clone())
}
pub fn list_functions(&self) -> Vec<String> {
let functions = self.functions.read().unwrap();
functions.keys().cloned().collect()
}
pub fn stats(&self) -> FfiStats {
self.stats.read().unwrap().clone()
}
pub fn clear(&self) {
{
let mut functions = self.functions.write().unwrap();
functions.clear();
}
{
let mut stats = self.stats.write().unwrap();
stats.registered_functions = 0;
}
}
fn register_builtins(&self) {
BuiltinFfiModule::register_functions(self).ok();
}
}