1mod i18n;
4mod math;
5#[cfg(feature = "rand")]
6mod rand;
7
8use std::collections::HashMap;
9
10use crate::error::{DialogueError, Result};
11use crate::value::Value;
12
13pub type HostFn = Box<dyn Fn(Vec<Value>) -> Result<Value> + Send + Sync + 'static>;
15
16pub struct FunctionLibrary {
21 fns: HashMap<String, HostFn>,
22}
23
24impl FunctionLibrary {
25 #[must_use]
27 pub fn new() -> Self {
28 let mut lib = Self {
29 fns: HashMap::new(),
30 };
31 lib.register_builtins();
32 lib
33 }
34
35 pub fn register<F>(&mut self, name: impl Into<String>, f: F)
39 where
40 F: Fn(Vec<Value>) -> Result<Value> + Send + Sync + 'static,
41 {
42 self.fns.insert(name.into(), Box::new(f));
43 }
44
45 pub fn call(&self, name: &str, args: Vec<Value>) -> Result<Value> {
50 self.fns.get(name).map_or_else(
51 || {
52 Err(DialogueError::Function {
53 name: name.to_owned(),
54 message: "unknown function".into(),
55 })
56 },
57 |f| f(args),
58 )
59 }
60
61 fn register_builtins(&mut self) {
62 #[cfg(feature = "rand")]
63 self.register_rand_builtins();
64 self.register_math_builtins();
65 self.register_i18n_builtins();
66 }
67}
68
69impl Default for FunctionLibrary {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl std::fmt::Debug for FunctionLibrary {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 let names: Vec<&str> = self.fns.keys().map(String::as_str).collect();
78 f.debug_struct("FunctionLibrary")
79 .field("functions", &names)
80 .finish()
81 }
82}
83
84#[cfg(test)]
85#[path = "library_tests/mod.rs"]
86mod tests;