phlow_sdk/structs/
modules.rs1use crate::context::Context;
2use crossbeam::channel;
3use std::collections::HashMap;
4use tokio::sync::oneshot;
5use valu3::value::Value;
6
7#[derive(Debug, Clone)]
8pub enum ModulesError {
9 ModuleNotFound(String),
10 ModuleNotLoaded(String),
11 ModuleError(String),
12}
13
14#[derive(Debug, Clone)]
15pub struct ModuleResponse {
16 pub error: Option<String>,
17 pub data: Value,
18}
19
20impl Into<ModuleResponse> for Value {
21 fn into(self) -> ModuleResponse {
22 ModuleResponse {
23 error: None,
24 data: self,
25 }
26 }
27}
28
29impl ModuleResponse {
30 pub fn from_error(error: String) -> Self {
31 Self {
32 error: Some(error),
33 data: Value::Null,
34 }
35 }
36
37 pub fn from_success(value: Value) -> Self {
38 Self {
39 error: None,
40 data: value,
41 }
42 }
43}
44
45#[derive(Debug)]
46pub struct ModulePackage {
47 pub context: Context,
48 pub sender: oneshot::Sender<ModuleResponse>,
49}
50
51impl ModulePackage {
52 pub fn input(&self) -> Option<Value> {
53 self.context.input.clone()
54 }
55}
56
57#[derive(Debug, Default, Clone)]
58pub struct Modules {
59 pub modules: HashMap<String, channel::Sender<ModulePackage>>,
60}
61
62impl Modules {
63 pub fn extract(&self) -> Self {
64 Self {
65 modules: self.modules.clone(),
66 }
67 }
68
69 pub fn register(&mut self, name: &str, sender: channel::Sender<ModulePackage>) {
70 self.modules.insert(name.to_string(), sender);
71 }
72
73 pub async fn execute(
74 &self,
75 name: &str,
76 context: &Context,
77 ) -> Result<ModuleResponse, ModulesError> {
78 if let Some(module_sender) = self.modules.get(name) {
79 let (package_sender, package_receiver) = oneshot::channel();
80 let package = ModulePackage {
81 context: context.clone(),
82 sender: package_sender,
83 };
84
85 let _ = module_sender.send(package);
86
87 let value = package_receiver.await.unwrap_or(ModuleResponse::from_error(
88 "Module response channel closed".to_string(),
89 ));
90
91 Ok(value)
92 } else {
93 Err(ModulesError::ModuleNotLoaded(name.to_string()))
94 }
95 }
96}