acts_next/env/
mod.rs

1mod moudle;
2#[cfg(test)]
3mod tests;
4mod value;
5
6use crate::{ActError, Result, ShareLock, Vars};
7use core::fmt;
8use rquickjs::{Context as JsContext, Ctx as JsCtx, FromJs, Runtime as JsRuntime};
9use serde::{de::DeserializeOwned, Deserialize, Serialize};
10use std::sync::{Arc, RwLock};
11
12use self::value::ActValue;
13
14/// ActModule to extend the js features
15///
16/// # Example
17/// ```rust
18///   use acts_next::{ActModule, Result};
19///   #[derive(Clone)]
20///   pub struct TestModule;
21///   impl ActModule for TestModule {
22///     fn init<'a>(&self, _ctx: &rquickjs::Ctx<'a>) -> Result<()> {
23///         Ok(())
24///     }
25///   }
26/// ```
27pub trait ActModule: Send + Sync {
28    fn init(&self, ctx: &JsCtx<'_>) -> Result<()>;
29}
30
31pub struct Enviroment {
32    vars: ShareLock<Vars>,
33    modules: ShareLock<Vec<Box<dyn ActModule>>>,
34}
35
36impl fmt::Debug for Enviroment {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        f.debug_struct("Enviroment")
39            .field("vars", &self.vars.read().unwrap())
40            .finish()
41    }
42}
43
44unsafe impl Send for Enviroment {}
45unsafe impl Sync for Enviroment {}
46
47impl Default for Enviroment {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl Enviroment {
54    pub fn new() -> Self {
55        let mut env = Enviroment {
56            modules: Arc::new(RwLock::new(Vec::new())),
57            vars: Arc::new(RwLock::new(Vars::new())),
58        };
59        env.init();
60        env
61    }
62
63    #[cfg(test)]
64    pub fn modules_count(&self) -> usize {
65        self.modules.read().unwrap().len()
66    }
67
68    pub fn register_module<T: ActModule + Clone + 'static>(&self, module: &T) {
69        let mut modules = self.modules.write().unwrap();
70        modules.push(Box::new(module.clone()));
71    }
72
73    pub fn get<T>(&self, name: &str) -> Option<T>
74    where
75        T: for<'de> Deserialize<'de> + Clone,
76    {
77        self.vars.read().unwrap().get::<T>(name)
78    }
79
80    pub fn set<T>(&self, name: &str, value: T)
81    where
82        T: Serialize + Clone,
83    {
84        self.vars.write().unwrap().set(name, value);
85    }
86
87    pub fn update<F: FnOnce(&mut Vars)>(&self, f: F) {
88        let mut vars = self.vars.write().unwrap();
89        f(&mut vars);
90    }
91
92    pub fn eval<T>(&self, expr: &str) -> Result<T>
93    where
94        T: DeserializeOwned,
95    {
96        let runtime = JsRuntime::new().unwrap();
97        let ctx = JsContext::full(&runtime).unwrap();
98        ctx.with(|ctx| {
99            let modules = self.modules.read().unwrap();
100            for m in modules.iter() {
101                m.init(&ctx)?;
102            }
103
104            let result = ctx.eval::<ActValue, &str>(expr);
105            if let Err(rquickjs::Error::Exception) = result {
106                let exception = rquickjs::Exception::from_js(&ctx, ctx.catch()).unwrap();
107                eprintln!("error: {exception:?}");
108                return Err(ActError::Exception {
109                    ecode: "".to_string(),
110                    message: exception.message().unwrap_or_default(),
111                });
112            }
113
114            let value = result.map_err(ActError::from)?;
115            let ret = serde_json::from_value::<T>(value.into()).map_err(ActError::from)?;
116            Ok(ret)
117        })
118    }
119}