aether/engine/
scoped.rs

1//! 闭包模式引擎
2//!
3//! 使用闭包风格的API,每次都创建新引擎,完全隔离。
4//! 类似于 Py3o 的使用方式,适合临时执行或需要完全隔离的场景。
5
6use crate::{Aether, Value};
7
8/// 闭包模式引擎
9///
10/// # 使用场景
11///
12/// - ✅ 临时脚本执行
13/// - ✅ 需要完全隔离(每次都是新引擎)
14/// - ✅ 偶尔使用(不频繁)
15/// - ✅ 简单API(类似 Py3o)
16/// - ❌ 高频调用(性能较低,请使用 GlobalEngine 或 PooledEngine)
17///
18/// # 特点
19///
20/// - **完全隔离**:每次都创建新引擎实例
21/// - **简洁API**:闭包风格,自动管理生命周期
22/// - **无缓存**:无法利用 AST 缓存(每次都是新引擎)
23/// - **线程安全**:每个线程独立创建引擎
24///
25/// # 示例
26///
27/// ```rust
28/// use aether::engine::ScopedEngine;
29///
30/// // 基本使用
31/// let result = ScopedEngine::with(|engine| {
32///     engine.eval("Set X 10\n(X + 20)")
33/// }).unwrap();
34/// assert_eq!(result.to_string(), "30");
35///
36/// // 多步骤执行
37/// let result = ScopedEngine::with(|engine| {
38///     engine.eval("Set X 10")?;
39///     engine.eval("Set Y 20")?;
40///     engine.eval("(X + Y)")
41/// }).unwrap();
42/// assert_eq!(result.to_string(), "30");
43///
44/// // 简化版:直接执行单行代码
45/// let result = ScopedEngine::eval("(10 + 20)").unwrap();
46/// assert_eq!(result.to_string(), "30");
47/// ```
48///
49/// # 与其他模式对比
50///
51/// ```rust
52/// use aether::engine::{GlobalEngine, EnginePool, ScopedEngine};
53///
54/// // GlobalEngine - 性能最优,但单线程
55/// let result1 = GlobalEngine::eval_isolated("Set X 10\n(X + 20)").unwrap();
56///
57/// // PooledEngine - 多线程,性能好
58/// let pool = EnginePool::new(4);
59/// let result2 = pool.acquire().eval("Set X 10\n(X + 20)").unwrap();
60///
61/// // ScopedEngine - API最简洁,完全隔离
62/// let result3 = ScopedEngine::eval("Set X 10\n(X + 20)").unwrap();
63///
64/// assert_eq!(result1, result2);
65/// assert_eq!(result2, result3);
66/// ```
67pub struct ScopedEngine;
68
69impl ScopedEngine {
70    /// 使用闭包执行代码(完全隔离)
71    ///
72    /// 每次调用都会创建新的引擎实例,执行完毕后自动销毁。
73    ///
74    /// # 参数
75    ///
76    /// - `f`: 接收 `&mut Aether` 的闭包,返回 `Result<T, String>`
77    ///
78    /// # 返回
79    ///
80    /// - `Ok(T)`: 闭包的返回值
81    /// - `Err(String)`: 错误信息
82    ///
83    /// # 类型参数
84    ///
85    /// - `F`: 闭包类型
86    /// - `T`: 返回值类型
87    ///
88    /// # 示例
89    ///
90    /// ```rust
91    /// use aether::engine::ScopedEngine;
92    ///
93    /// // 单步执行
94    /// let result = ScopedEngine::with(|engine| {
95    ///     engine.eval("(10 + 20)")
96    /// }).unwrap();
97    ///
98    /// // 多步执行
99    /// let result = ScopedEngine::with(|engine| {
100    ///     engine.eval("Set X 10")?;
101    ///     engine.eval("Set Y (X * 2)")?;
102    ///     engine.eval("(X + Y)")
103    /// }).unwrap();
104    ///
105    /// // 自定义返回类型
106    /// let (x, y) = ScopedEngine::with(|engine| {
107    ///     engine.eval("Set X 10")?;
108    ///     engine.eval("Set Y 20")?;
109    ///     let x = engine.eval("X")?;
110    ///     let y = engine.eval("Y")?;
111    ///     Ok((x, y))
112    /// }).unwrap();
113    /// ```
114    pub fn with<F, T>(f: F) -> Result<T, String>
115    where
116        F: FnOnce(&mut Aether) -> Result<T, String>,
117    {
118        let mut engine = Aether::new();
119        f(&mut engine)
120    }
121
122    /// 使用闭包执行代码(启用所有权限)
123    ///
124    /// 创建的引擎会启用所有 IO 权限(文件系统、网络等)。
125    ///
126    /// # 警告
127    ///
128    /// 仅在信任代码来源时使用。用户提供的代码可能包含恶意操作。
129    ///
130    /// # 示例
131    ///
132    /// ```rust
133    /// use aether::engine::ScopedEngine;
134    ///
135    /// let result = ScopedEngine::with_all_permissions(|engine| {
136    ///     // 可以使用文件系统操作
137    ///     engine.eval(r#"
138    ///         Set Content (ReadFile "config.txt")
139    ///         (Length Content)
140    ///     "#)
141    /// });
142    /// ```
143    pub fn with_all_permissions<F, T>(f: F) -> Result<T, String>
144    where
145        F: FnOnce(&mut Aether) -> Result<T, String>,
146    {
147        let mut engine = Aether::with_all_permissions();
148        f(&mut engine)
149    }
150
151    /// 直接执行代码(简化版)
152    ///
153    /// 创建新引擎,执行代码,返回结果。
154    /// 适合简单的单行代码执行。
155    ///
156    /// # 参数
157    ///
158    /// - `code`: 要执行的 Aether 代码
159    ///
160    /// # 返回
161    ///
162    /// - `Ok(Value)`: 执行结果
163    /// - `Err(String)`: 错误信息
164    ///
165    /// # 示例
166    ///
167    /// ```rust
168    /// use aether::engine::ScopedEngine;
169    ///
170    /// // 简单表达式
171    /// let result = ScopedEngine::eval("(10 + 20)").unwrap();
172    /// assert_eq!(result.to_string(), "30");
173    ///
174    /// // 多行代码
175    /// let result = ScopedEngine::eval("Set X 10\nSet Y 20\n(X + Y)").unwrap();
176    /// assert_eq!(result.to_string(), "30");
177    /// ```
178    pub fn eval(code: &str) -> Result<Value, String> {
179        Self::with(|engine| engine.eval(code))
180    }
181
182    /// 直接执行代码(启用所有权限)
183    ///
184    /// 创建启用所有 IO 权限的引擎,执行代码。
185    ///
186    /// # 警告
187    ///
188    /// 仅在信任代码来源时使用。
189    pub fn eval_with_all_permissions(code: &str) -> Result<Value, String> {
190        Self::with_all_permissions(|engine| engine.eval(code))
191    }
192
193    /// 使用闭包异步执行代码(requires "async" feature)
194    ///
195    /// # 示例
196    ///
197    /// ```no_run
198    /// use aether::engine::ScopedEngine;
199    ///
200    /// #[tokio::main]
201    /// async fn main() {
202    ///     let result = ScopedEngine::with_async(|engine| async move {
203    ///         engine.eval("Set X 10")?;
204    ///         engine.eval("(X + 20)")
205    ///     }).await.unwrap();
206    ///     println!("Result: {}", result);
207    /// }
208    /// ```
209    #[cfg(feature = "async")]
210    pub async fn with_async<F, Fut, T>(f: F) -> Result<T, String>
211    where
212        F: FnOnce(&mut Aether) -> Fut,
213        Fut: std::future::Future<Output = Result<T, String>>,
214    {
215        tokio::task::yield_now().await;
216        let mut engine = Aether::new();
217        f(&mut engine).await
218    }
219
220    /// 异步执行代码(简化版,requires "async" feature)
221    ///
222    /// # 示例
223    ///
224    /// ```no_run
225    /// use aether::engine::ScopedEngine;
226    ///
227    /// #[tokio::main]
228    /// async fn main() {
229    ///     let result = ScopedEngine::eval_async("Set X 10\n(X + 20)").await.unwrap();
230    ///     println!("Result: {}", result);
231    /// }
232    /// ```
233    #[cfg(feature = "async")]
234    pub async fn eval_async(code: &str) -> Result<Value, String> {
235        tokio::task::yield_now().await;
236        Self::eval(code)
237    }
238
239    /// 异步执行代码(启用所有权限,requires "async" feature)
240    #[cfg(feature = "async")]
241    pub async fn eval_with_all_permissions_async(code: &str) -> Result<Value, String> {
242        tokio::task::yield_now().await;
243        Self::eval_with_all_permissions(code)
244    }
245}
246
247#[cfg(test)]
248mod tests {
249    use super::*;
250
251    #[test]
252    fn test_scoped_engine_basic() {
253        let result = ScopedEngine::eval("Set X 10\n(X + 20)").unwrap();
254        assert_eq!(result.to_string(), "30");
255    }
256
257    #[test]
258    fn test_scoped_engine_isolation() {
259        // 第一次执行
260        ScopedEngine::eval("Set X 10").unwrap();
261
262        // 第二次执行(新引擎,X 不存在)
263        let result = ScopedEngine::eval("X");
264        assert!(result.is_err());
265    }
266
267    #[test]
268    fn test_scoped_engine_with_closure() {
269        let result = ScopedEngine::with(|engine| {
270            engine.eval("Set X 10")?;
271            engine.eval("Set Y 20")?;
272            engine.eval("(X + Y)")
273        })
274        .unwrap();
275
276        assert_eq!(result.to_string(), "30");
277    }
278
279    #[test]
280    fn test_scoped_engine_custom_return() {
281        let (x, y) = ScopedEngine::with(|engine| {
282            engine.eval("Set X 10")?;
283            engine.eval("Set Y 20")?;
284            let x = engine.eval("X")?;
285            let y = engine.eval("Y")?;
286            Ok((x, y))
287        })
288        .unwrap();
289
290        assert_eq!(x.to_string(), "10");
291        assert_eq!(y.to_string(), "20");
292    }
293}