abacus/abacus-core/src/engine.rs

102 lines
2.5 KiB
Rust
Raw Normal View History

use std::sync::Arc;
2022-10-08 20:48:17 +00:00
use crate::dataframe;
#[derive(Debug)]
pub struct Engine<'a> {
2022-10-08 20:48:17 +00:00
engine: rhai::Engine,
scope: rhai::Scope<'a>,
2022-10-08 20:48:17 +00:00
}
impl<'a> Default for Engine<'a> {
2022-10-08 20:48:17 +00:00
fn default() -> Self {
let mut engine = rhai::Engine::new();
engine.set_fast_operators(false);
dataframe::setup_engine(&mut engine);
Self {
engine,
scope: rhai::Scope::new(),
2022-10-08 20:48:17 +00:00
}
}
}
impl<'a> Engine<'a> {
pub fn process_script(&mut self, script: &str) -> Output {
match self
.engine
.eval_with_scope::<rhai::Dynamic>(&mut self.scope, script)
{
Ok(res) if res.is::<dataframe::DataFrame>() => {
let frame = rhai::Dynamic::cast::<dataframe::DataFrame>(res);
Output::DataFrame(frame)
2022-10-08 20:48:17 +00:00
}
Ok(res) if res.is::<()>() => Output::None,
Ok(res) if res.is::<dataframe::Series>() => {
let series = rhai::Dynamic::cast::<dataframe::Series>(res);
Output::Series(series)
}
Ok(res) => Output::Scalar(res.to_string()),
Err(e) => Output::Error(e.to_string()),
2022-10-08 20:48:17 +00:00
}
}
}
#[derive(Debug, Clone)]
pub enum Output {
None,
Scalar(String),
2022-10-08 20:48:17 +00:00
DataFrame(dataframe::DataFrame),
Series(dataframe::Series),
Error(String),
}
impl Default for Output {
fn default() -> Self {
Output::None
}
}
impl PartialEq for Output {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Scalar(l0), Self::Scalar(r0)) => l0.to_string() == r0.to_string(),
(Self::DataFrame(l0), Self::DataFrame(r0)) => l0 == r0,
(Self::Series(l0), Self::Series(r0)) => l0 == r0,
(Self::Error(l0), Self::Error(r0)) => l0 == r0,
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
}
}
}
2022-10-08 20:48:17 +00:00
impl Output {
pub fn into_frame(self) -> dataframe::DataFrame {
if let Self::DataFrame(v) = self {
return v;
}
panic!("Not a dataframe");
}
pub fn into_series(self) -> dataframe::Series {
if let Self::Series(v) = self {
return v;
}
panic!("Not a series");
}
pub fn into_scalar(self) -> String {
2022-10-08 20:48:17 +00:00
if let Self::Scalar(v) = self {
return v;
}
panic!("Not a scalar");
}
}
#[cfg(test)]
pub mod tests {
use super::*;
pub fn process(script: &str) -> Output {
let mut engine = Engine::default();
engine.process_script(script)
2022-10-08 20:48:17 +00:00
}
}