use crate::{Aether, Value};
pub struct ScopedEngine;
impl ScopedEngine {
pub fn with<F, T>(f: F) -> Result<T, String>
where
F: FnOnce(&mut Aether) -> Result<T, String>,
{
let mut engine = Aether::new();
f(&mut engine)
}
pub fn with_all_permissions<F, T>(f: F) -> Result<T, String>
where
F: FnOnce(&mut Aether) -> Result<T, String>,
{
let mut engine = Aether::with_all_permissions();
f(&mut engine)
}
pub fn eval(code: &str) -> Result<Value, String> {
Self::with(|engine| engine.eval(code))
}
pub fn eval_with_all_permissions(code: &str) -> Result<Value, String> {
Self::with_all_permissions(|engine| engine.eval(code))
}
#[cfg(feature = "async")]
pub async fn with_async<F, Fut, T>(f: F) -> Result<T, String>
where
F: FnOnce(&mut Aether) -> Fut,
Fut: std::future::Future<Output = Result<T, String>>,
{
tokio::task::yield_now().await;
let mut engine = Aether::new();
f(&mut engine).await
}
#[cfg(feature = "async")]
pub async fn eval_async(code: &str) -> Result<Value, String> {
tokio::task::yield_now().await;
Self::eval(code)
}
#[cfg(feature = "async")]
pub async fn eval_with_all_permissions_async(code: &str) -> Result<Value, String> {
tokio::task::yield_now().await;
Self::eval_with_all_permissions(code)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scoped_engine_basic() {
let result = ScopedEngine::eval("Set X 10\n(X + 20)").unwrap();
assert_eq!(result.to_string(), "30");
}
#[test]
fn test_scoped_engine_isolation() {
ScopedEngine::eval("Set X 10").unwrap();
let result = ScopedEngine::eval("X");
assert!(result.is_err());
}
#[test]
fn test_scoped_engine_with_closure() {
let result = ScopedEngine::with(|engine| {
engine.eval("Set X 10")?;
engine.eval("Set Y 20")?;
engine.eval("(X + Y)")
})
.unwrap();
assert_eq!(result.to_string(), "30");
}
#[test]
fn test_scoped_engine_custom_return() {
let (x, y) = ScopedEngine::with(|engine| {
engine.eval("Set X 10")?;
engine.eval("Set Y 20")?;
let x = engine.eval("X")?;
let y = engine.eval("Y")?;
Ok((x, y))
})
.unwrap();
assert_eq!(x.to_string(), "10");
assert_eq!(y.to_string(), "20");
}
}