1use crossbeam::channel;
2use std::collections::HashMap;
3use tokio::sync::oneshot;
4use valu3::value::Value;
5
6use crate::Context;
7
8#[derive(Debug, Clone)]
9pub enum ModulesError {
10 ModuleNotFound(String),
11 ModuleNotLoaded(String),
12}
13
14#[derive(Debug)]
15pub struct ModulePackage {
16 pub context: Context,
17 pub sender: oneshot::Sender<Value>,
18}
19
20#[derive(Debug, Default, Clone)]
21pub struct Modules {
22 pub modules: HashMap<String, channel::Sender<ModulePackage>>,
23}
24
25impl Modules {
26 pub fn extract(&self) -> Self {
27 Self {
28 modules: self.modules.clone(),
29 }
30 }
31
32 pub fn register(&mut self, name: &str, sender: channel::Sender<ModulePackage>) {
33 self.modules.insert(name.to_string(), sender);
34 }
35
36 pub async fn execute(&self, name: &str, context: &Context) -> Result<Value, ModulesError> {
37 if let Some(module_sender) = self.modules.get(name) {
38 let (package_sender, package_receiver) = oneshot::channel();
39 let package = ModulePackage {
40 context: context.clone(),
41 sender: package_sender,
42 };
43
44 let _ = module_sender.send(package);
45
46 let value = package_receiver.await.unwrap_or(Value::Null);
47
48 Ok(value)
49 } else {
50 Err(ModulesError::ModuleNotLoaded(name.to_string()))
51 }
52 }
53}