mod i18n;
mod math;
#[cfg(feature = "rand")]
mod rand;
use std::collections::HashMap;
use crate::error::{DialogueError, Result};
use crate::value::Value;
pub type HostFn = Box<dyn Fn(Vec<Value>) -> Result<Value> + Send + Sync + 'static>;
pub struct FunctionLibrary {
fns: HashMap<String, HostFn>,
}
impl FunctionLibrary {
#[must_use]
pub fn new() -> Self {
let mut lib = Self {
fns: HashMap::new(),
};
lib.register_builtins();
lib
}
pub fn register<F>(&mut self, name: impl Into<String>, f: F)
where
F: Fn(Vec<Value>) -> Result<Value> + Send + Sync + 'static,
{
self.fns.insert(name.into(), Box::new(f));
}
pub fn call(&self, name: &str, args: Vec<Value>) -> Result<Value> {
self.fns.get(name).map_or_else(
|| {
Err(DialogueError::Function {
name: name.to_owned(),
message: "unknown function".into(),
})
},
|f| f(args),
)
}
fn register_builtins(&mut self) {
#[cfg(feature = "rand")]
self.register_rand_builtins();
self.register_math_builtins();
self.register_i18n_builtins();
}
}
impl Default for FunctionLibrary {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for FunctionLibrary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let names: Vec<&str> = self.fns.keys().map(String::as_str).collect();
f.debug_struct("FunctionLibrary")
.field("functions", &names)
.finish()
}
}
#[cfg(test)]
#[path = "library_tests/mod.rs"]
mod tests;