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}