use std::sync::Arc;
use indexmap::IndexMap;
use super::value::Val;
use super::EvalError;
pub trait Method: Send + Sync {
fn call(&self, recv: Val, args: &[Val]) -> Result<Val, EvalError>;
}
impl<F> Method for F
where
F: Fn(Val, &[Val]) -> Result<Val, EvalError> + Send + Sync,
{
#[inline]
fn call(&self, recv: Val, args: &[Val]) -> Result<Val, EvalError> {
self(recv, args)
}
}
#[derive(Clone)]
pub struct MethodRegistry {
methods: IndexMap<String, Arc<dyn Method>>,
}
impl MethodRegistry {
pub fn new() -> Self {
Self { methods: IndexMap::new() }
}
pub fn register(&mut self, name: impl Into<String>, method: impl Method + 'static) {
self.methods.insert(name.into(), Arc::new(method));
}
#[inline]
pub fn get(&self, name: &str) -> Option<&Arc<dyn Method>> {
self.methods.get(name)
}
pub fn is_empty(&self) -> bool { self.methods.is_empty() }
pub fn iter(&self) -> impl Iterator<Item = (&str, &Arc<dyn Method>)> {
self.methods.iter().map(|(n, m)| (n.as_str(), m))
}
pub fn register_arc(&mut self, name: impl Into<String>, method: Arc<dyn Method>) {
self.methods.insert(name.into(), method);
}
}
impl Default for MethodRegistry {
fn default() -> Self { Self::new() }
}